Skip to content

Commit 01c1a79

Browse files
nategrafmmaker
andauthored
Implement scalar multiplication, negation, and subtraction for variables (#48)
Co-authored-by: Michele Orrù <[email protected]>
1 parent 3f44c8c commit 01c1a79

File tree

15 files changed

+576
-127
lines changed

15 files changed

+576
-127
lines changed

examples/schnorr.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,14 @@ fn create_relation(P: RistrettoPoint) -> LinearRelation<RistrettoPoint> {
3434
/// generate a proof that P = x * G
3535
#[allow(non_snake_case)]
3636
fn prove(x: Scalar, P: RistrettoPoint) -> ProofResult<Vec<u8>> {
37-
let nizk = create_relation(P).into_nizk(b"schnorr-proof");
37+
let nizk = create_relation(P).into_nizk(b"sigma-rs::examples");
3838
nizk.prove_batchable(&vec![x], &mut OsRng)
3939
}
4040

4141
/// Verify a proof of knowledge of discrete logarithm for the given public key P
4242
#[allow(non_snake_case)]
4343
fn verify(P: RistrettoPoint, proof: &[u8]) -> ProofResult<()> {
44-
let nizk = create_relation(P).into_nizk(b"schnorr-proof");
44+
let nizk = create_relation(P).into_nizk(b"sigma-rs::examples");
4545
nizk.verify_batchable(proof)
4646
}
4747

@@ -61,9 +61,9 @@ fn main() {
6161
// Verify the proof
6262
match verify(P, &proof) {
6363
Ok(()) => println!("✓ Proof verified successfully!"),
64-
Err(e) => println!("✗ Proof verification failed: {:?}", e),
64+
Err(e) => println!("✗ Proof verification failed: {e:?}"),
6565
}
6666
}
67-
Err(e) => println!("✗ Failed to generate proof: {:?}", e),
67+
Err(e) => println!("✗ Failed to generate proof: {e:?}"),
6868
}
6969
}

examples/simple_composition.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,9 @@ fn main() {
9595
// Verify the proof
9696
match verify(P1, P2, Q, H, &proof) {
9797
Ok(()) => println!("✓ Proof verified successfully!"),
98-
Err(e) => println!("✗ Proof verification failed: {:?}", e),
98+
Err(e) => println!("✗ Proof verification failed: {e:?}"),
9999
}
100100
}
101-
Err(e) => println!("✗ Failed to generate proof: {:?}", e),
101+
Err(e) => println!("✗ Failed to generate proof: {e:?}"),
102102
}
103103
}

src/codec.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub trait Codec {
2222
type Challenge;
2323

2424
/// Generates an empty codec that can be identified by a domain separator.
25-
fn new(domain_sep: &[u8]) -> Self;
25+
fn new(protocol_identifier: &[u8], session_identifier: &[u8], instance_label: &[u8]) -> Self;
2626

2727
/// Allows for precomputed initialization of the codec with a specific IV.
2828
fn from_iv(iv: [u8; 32]) -> Self;
@@ -60,10 +60,14 @@ where
6060
{
6161
type Challenge = <G as Group>::Scalar;
6262

63-
fn new(domain_sep: &[u8]) -> Self {
63+
fn new(protocol_id: &[u8], session_id: &[u8], instance_label: &[u8]) -> Self {
6464
let iv = {
6565
let mut tmp = H::new([0u8; 32]);
66-
tmp.absorb(domain_sep);
66+
tmp.absorb(protocol_id);
67+
tmp.ratchet();
68+
tmp.absorb(session_id);
69+
tmp.ratchet();
70+
tmp.absorb(instance_label);
6771
tmp.squeeze(32).try_into().unwrap()
6872
};
6973

src/composition.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
1111
use ff::{Field, PrimeField};
1212
use group::{Group, GroupEncoding};
13+
use sha3::Digest;
14+
use sha3::Sha3_256;
1315

1416
use crate::{
1517
errors::Error,
@@ -273,6 +275,57 @@ impl<G: Group + GroupEncoding> SigmaProtocol for Protocol<G> {
273275
serialize_scalars::<G>(&[*challenge])
274276
}
275277

278+
fn instance_label(&self) -> impl AsRef<[u8]> {
279+
match self {
280+
Protocol::Simple(p) => {
281+
let label = p.instance_label();
282+
label.as_ref().to_vec()
283+
}
284+
Protocol::And(ps) => {
285+
let mut bytes = Vec::new();
286+
for p in ps {
287+
bytes.extend(p.instance_label().as_ref());
288+
}
289+
bytes
290+
}
291+
Protocol::Or(ps) => {
292+
let mut bytes = Vec::new();
293+
for p in ps {
294+
bytes.extend(p.instance_label().as_ref());
295+
}
296+
bytes
297+
}
298+
}
299+
}
300+
301+
fn protocol_identifier(&self) -> impl AsRef<[u8]> {
302+
let mut hasher = Sha3_256::new();
303+
304+
match self {
305+
Protocol::Simple(p) => {
306+
// take the digest of the simple protocol id
307+
hasher.update([0u8; 32]);
308+
hasher.update(p.protocol_identifier());
309+
}
310+
Protocol::And(protocols) => {
311+
let mut hasher = Sha3_256::new();
312+
hasher.update([1u8; 32]);
313+
for p in protocols {
314+
hasher.update(p.protocol_identifier());
315+
}
316+
}
317+
Protocol::Or(protocols) => {
318+
let mut hasher = Sha3_256::new();
319+
hasher.update([2u8; 32]);
320+
for p in protocols {
321+
hasher.update(p.protocol_identifier());
322+
}
323+
}
324+
}
325+
326+
hasher.finalize()
327+
}
328+
276329
fn serialize_response(&self, response: &Self::Response) -> Vec<u8> {
277330
match (self, response) {
278331
(Protocol::Simple(p), ProtocolResponse::Simple(r)) => p.serialize_response(r),

src/duplex_sponge/keccak.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,12 @@ impl DuplexSpongeInterface for KeccakDuplexSponge {
9696
}
9797
output
9898
}
99+
100+
fn ratchet(&mut self) {
101+
self.state.permute();
102+
self.absorb_index = 0;
103+
self.squeeze_index = RATE;
104+
}
99105
}
100106

101107
#[cfg(test)]

src/duplex_sponge/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,6 @@ pub trait DuplexSpongeInterface {
2323

2424
/// Squeezes output data from the sponge state.
2525
fn squeeze(&mut self, length: usize) -> Vec<u8>;
26+
27+
fn ratchet(&mut self);
2628
}

src/duplex_sponge/shake.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
use crate::duplex_sponge::DuplexSpongeInterface;
66
use sha3::{
7-
digest::{ExtendableOutput, Update},
7+
digest::{ExtendableOutput, Reset, Update},
88
Shake128,
99
};
1010

@@ -28,4 +28,11 @@ impl DuplexSpongeInterface for ShakeDuplexSponge {
2828
self.0.clone().finalize_xof_into(&mut output);
2929
output
3030
}
31+
32+
fn ratchet(&mut self) {
33+
let mut output = [0u8; 32];
34+
self.0.clone().finalize_xof_into(&mut output);
35+
self.0.reset();
36+
self.0.update(&output);
37+
}
3138
}

src/fiat_shamir.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,15 @@ where
6262
///
6363
/// # Returns
6464
/// A new [`NISigmaProtocol`] that can generate and verify non-interactive proofs.
65-
pub fn new(iv: &[u8], instance: P) -> Self {
66-
let hash_state = C::new(iv);
65+
pub fn new(session_identifier: &[u8], interactive_proof: P) -> Self {
66+
let hash_state = C::new(
67+
interactive_proof.protocol_identifier().as_ref(),
68+
session_identifier,
69+
interactive_proof.instance_label().as_ref(),
70+
);
6771
Self {
6872
hash_state,
69-
ip: instance,
73+
ip: interactive_proof,
7074
}
7175
}
7276

0 commit comments

Comments
 (0)