Skip to content

Commit

Permalink
feat: non-interactive fiat-shamir transform
Browse files Browse the repository at this point in the history
  • Loading branch information
OnlyF0uR committed Nov 10, 2024
1 parent a7d87d2 commit b13c33d
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 1 deletion.
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ sha3 = "0.10.8"
rocksdb = "0.22.0"
bincode = "1.3.3"
tempfile = "3.13.0"
wasmparser = "0.219.1"
once_cell = "1.20.2"
serde = { version = "1.0.213", features = ["derive"] }
wasmer = { version = "5.0.0", features = ["singlepass"] }
Expand Down
45 changes: 45 additions & 0 deletions crates/cesium-crypto/src/zk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,49 @@ mod tests {
// Commitments should be different due to random salt
assert_ne!(commitment1.0, commitment2.0);
}

#[test]
fn test_non_interactive() {
let account = Account::create();
let secret = b"my secret value";

let (commitment, response) =
ProverProtocol::generate_non_interactive(&account, secret).unwrap();

let valid =
VerifierProtocol::verify_non_interactive(&account, &commitment, &response).unwrap();
assert!(valid);
}

#[test]
fn test_non_interactive_wrong_account() {
let account = Account::create();
let wrong_account = Account::create();
let secret = b"my secret value";

let (commitment, response) =
ProverProtocol::generate_non_interactive(&account, secret).unwrap();

let valid =
VerifierProtocol::verify_non_interactive(&wrong_account, &commitment, &response)
.unwrap();

assert!(!valid);
}

#[test]
fn test_non_interactive_wrong_commitment() {
let account = Account::create();
let secret = b"my secret value";

let (_, response) = ProverProtocol::generate_non_interactive(&account, secret).unwrap();

let wrong_commitment = Commitment(vec![0; CHALLENGE_LENGTH]);

let valid =
VerifierProtocol::verify_non_interactive(&account, &wrong_commitment, &response)
.unwrap();

assert!(!valid);
}
}
37 changes: 37 additions & 0 deletions crates/cesium-crypto/src/zk/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,41 @@ impl ProverProtocol {

Ok(Response(signature))
}

/// Generate commitment and response non-interactive
pub fn generate_non_interactive(
account: &Account,
secret: &[u8],
) -> Result<(Commitment, Response), ZkError> {
let mut rng = OsRng;
let mut salt = vec![0u8; SALT_LENGTH];
rng.fill(&mut salt[..]);

let mut hasher = Shake256::default();
hasher.update(secret);
hasher.update(&salt);

let mut commitment = vec![0u8; CHALLENGE_LENGTH];
let mut xof = hasher.finalize_xof();
let _ = xof.read(&mut commitment);

// Use Fiat-Shamir transform to generate a challenge from commitment
let mut challenge_hasher = Shake256::default();
challenge_hasher.update(&commitment);

let mut challenge = vec![0u8; CHALLENGE_LENGTH];
let mut xof_challenge = challenge_hasher.finalize_xof();
let _ = xof_challenge.read(&mut challenge);

// Create a response by signing the commitment and challenge
let mut message = Vec::new();
message.extend_from_slice(&commitment);
message.extend_from_slice(&challenge);

let signature = account
.digest(&message)
.map_err(|e| ZkError::SigningError(e.to_string()))?;

Ok((Commitment(commitment), Response(signature)))
}
}
31 changes: 31 additions & 0 deletions crates/cesium-crypto/src/zk/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,35 @@ impl VerifierProtocol {
}
}
}

pub fn verify_non_interactive(
account: &Account,
commitment: &Commitment,
response: &Response,
) -> Result<bool, ZkError> {
// Deterministically recreate the challenge from the commitment
let mut hasher = Shake256::default();
hasher.update(&commitment.0);

let mut challenge = vec![0u8; CHALLENGE_LENGTH];
let mut xof = hasher.finalize_xof();
let _ = xof.read(&mut challenge);

// Reconstruct the message that was signed
let mut message = Vec::new();
message.extend_from_slice(&commitment.0);
message.extend_from_slice(&challenge);

// Verify the response signature
match account.verify(&message, &response.0) {
Ok(b) => Ok(b),
Err(e) => {
if e.to_string().contains("verification failed") {
Ok(false)
} else {
Err(ZkError::VerificationError(e.to_string()))
}
}
}
}
}

0 comments on commit b13c33d

Please sign in to comment.