@@ -31,28 +31,38 @@ where
3131 <G as GroupElement >:: ScalarType : FiatShamirChallenge ,
3232{
3333 /// Create a new NIZKPoK for the DDH tuple `(G, H=eG, xG, xH)` using the given RNG.
34+ /// `dst` is a domain separation tag bound into the Fiat-Shamir challenge; the same `dst` must
35+ /// be passed to [Self::verify].
3436 pub fn create < R : AllowedRng > (
3537 x : & G :: ScalarType ,
3638 g : & G ,
3739 h : & G ,
3840 x_g : & G ,
3941 x_h : & G ,
42+ dst : & [ u8 ] ,
4043 rng : & mut R ,
4144 ) -> Self {
4245 let r = G :: ScalarType :: rand ( rng) ;
4346 let a = * g * r;
4447 let b = * h * r;
45- let challenge = Self :: fiat_shamir_challenge ( g, h, x_g, x_h, & a, & b) ;
48+ let challenge = Self :: fiat_shamir_challenge ( g, h, x_g, x_h, & a, & b, dst ) ;
4649 let z = challenge * x + r;
4750 DdhTupleNizk { a, b, z }
4851 }
4952
50- /// Verify this NIZKPoK.
51- pub fn verify ( & self , g : & G , h : & G , x_g : & G , x_h : & G ) -> FastCryptoResult < ( ) > {
53+ /// Verify this NIZKPoK. `dst` must match the value used in [Self::create].
54+ pub fn verify (
55+ & self ,
56+ g : & G ,
57+ h : & G ,
58+ x_g : & G ,
59+ x_h : & G ,
60+ dst : & [ u8 ] ,
61+ ) -> FastCryptoResult < ( ) > {
5262 if * g == G :: zero ( ) || * h == G :: zero ( ) || * x_g == G :: zero ( ) || * x_h == G :: zero ( ) {
5363 return Err ( FastCryptoError :: InvalidProof ) ;
5464 }
55- let challenge = Self :: fiat_shamir_challenge ( g, h, x_g, x_h, & self . a , & self . b ) ;
65+ let challenge = Self :: fiat_shamir_challenge ( g, h, x_g, x_h, & self . a , & self . b , dst ) ;
5666 if !is_valid_relation ( & self . a , x_g, g, & self . z , & challenge)
5767 || !is_valid_relation (
5868 & self . b , // B
6676 }
6777
6878 /// Returns the challenge for Fiat-Shamir.
69- fn fiat_shamir_challenge ( g : & G , h : & G , x_g : & G , x_h : & G , a : & G , b : & G ) -> G :: ScalarType {
70- let output = Sha3_256 :: digest ( bcs:: to_bytes ( & ( g, h, x_g, x_h, a, b) ) . unwrap ( ) ) ;
79+ fn fiat_shamir_challenge (
80+ g : & G ,
81+ h : & G ,
82+ x_g : & G ,
83+ x_h : & G ,
84+ a : & G ,
85+ b : & G ,
86+ dst : & [ u8 ] ,
87+ ) -> G :: ScalarType {
88+ let output = Sha3_256 :: digest ( bcs:: to_bytes ( & ( dst, g, h, x_g, x_h, a, b) ) . unwrap ( ) ) ;
7189 G :: ScalarType :: fiat_shamir_reduction_to_group_element ( & output. digest )
7290 }
7391}
@@ -107,31 +125,35 @@ mod tests {
107125
108126 #[ test]
109127 fn test_nizk_flow ( ) {
128+ let dst = b"test" ;
110129 let e = S :: rand ( & mut thread_rng ( ) ) ;
111130 let x = S :: rand ( & mut thread_rng ( ) ) ;
112131 let g = G :: generator ( ) * S :: rand ( & mut thread_rng ( ) ) ;
113132 let h = g * e;
114133 let x_g = g * x;
115134 let x_h = h * x;
116- let nizk = DdhTupleNizk :: create ( & x, & g, & h, & x_g, & x_h, & mut thread_rng ( ) ) ;
117- assert ! ( nizk. verify( & g, & h, & x_g, & x_h) . is_ok( ) ) ;
135+ let nizk = DdhTupleNizk :: create ( & x, & g, & h, & x_g, & x_h, dst, & mut thread_rng ( ) ) ;
136+ assert ! ( nizk. verify( & g, & h, & x_g, & x_h, dst) . is_ok( ) ) ;
137+
138+ // A different DST must not verify
139+ assert ! ( nizk. verify( & g, & h, & x_g, & x_h, b"other" ) . is_err( ) ) ;
118140
119141 let invalid_witness = x + S :: generator ( ) ;
120142 let invalid_nizk =
121- DdhTupleNizk :: create ( & invalid_witness, & g, & h, & x_g, & x_h, & mut thread_rng ( ) ) ;
122- assert ! ( invalid_nizk. verify( & g, & h, & x_g, & x_h) . is_err( ) ) ;
143+ DdhTupleNizk :: create ( & invalid_witness, & g, & h, & x_g, & x_h, dst , & mut thread_rng ( ) ) ;
144+ assert ! ( invalid_nizk. verify( & g, & h, & x_g, & x_h, dst ) . is_err( ) ) ;
123145
124146 let other_g = g + G :: generator ( ) ;
125- assert ! ( nizk. verify( & other_g, & h, & x_g, & x_h) . is_err( ) ) ;
147+ assert ! ( nizk. verify( & other_g, & h, & x_g, & x_h, dst ) . is_err( ) ) ;
126148
127149 let other_h = h + G :: generator ( ) ;
128- assert ! ( nizk. verify( & g, & other_h, & x_g, & x_h) . is_err( ) ) ;
150+ assert ! ( nizk. verify( & g, & other_h, & x_g, & x_h, dst ) . is_err( ) ) ;
129151
130152 let other_x_g = x_g + G :: generator ( ) ;
131- assert ! ( nizk. verify( & g, & h, & other_x_g, & x_h) . is_err( ) ) ;
153+ assert ! ( nizk. verify( & g, & h, & other_x_g, & x_h, dst ) . is_err( ) ) ;
132154
133155 let other_x_h = x_h + G :: generator ( ) ;
134- assert ! ( nizk. verify( & g, & h, & x_g, & other_x_h) . is_err( ) ) ;
156+ assert ! ( nizk. verify( & g, & h, & x_g, & other_x_h, dst ) . is_err( ) ) ;
135157 }
136158
137159 #[ test]
@@ -145,10 +167,10 @@ mod tests {
145167 let r = S :: from ( 91u64 ) ;
146168 let a = g * r;
147169 let b = h * r;
148- let c = DdhTupleNizk :: fiat_shamir_challenge ( & g, & h, & x_g, & x_h, & a, & b) ;
170+ let c = DdhTupleNizk :: fiat_shamir_challenge ( & g, & h, & x_g, & x_h, & a, & b, b"test" ) ;
149171 assert_eq ! (
150172 & c. to_byte_array( ) ,
151- Hex :: decode( "30db2f4121471c4af67d2dcfdede1f4aefb15475867c20c0dd5c228c0721f80e " )
173+ Hex :: decode( "308ef93a3c19c20dcbf293b99363eeb4158c90aff86fe006477c80f6140e6a0f " )
152174 . unwrap( )
153175 . as_slice( )
154176 ) ;
@@ -157,30 +179,32 @@ mod tests {
157179 #[ test]
158180 fn test_invalid_proofs ( ) {
159181 // x_g/h_g/h=inf should be rejected
182+ let dst = b"test" ;
160183 let e = S :: zero ( ) ;
161184 let x = S :: rand ( & mut thread_rng ( ) ) ;
162185 let g = G :: generator ( ) * S :: rand ( & mut thread_rng ( ) ) ;
163186 let h = g * e;
164187 let x_g = g * x;
165188 let x_h = h * x;
166- let nizk = DdhTupleNizk :: create ( & x, & g, & h, & x_g, & x_h, & mut thread_rng ( ) ) ;
189+ let nizk = DdhTupleNizk :: create ( & x, & g, & h, & x_g, & x_h, dst , & mut thread_rng ( ) ) ;
167190
168- assert ! ( nizk. verify( & G :: zero( ) , & h, & x_g, & x_h) . is_err( ) ) ;
169- assert ! ( nizk. verify( & g, & G :: zero( ) , & x_g, & x_h) . is_err( ) ) ;
170- assert ! ( nizk. verify( & g, & h, & G :: zero( ) , & x_h) . is_err( ) ) ;
171- assert ! ( nizk. verify( & g, & h, & x_g, & G :: zero( ) ) . is_err( ) ) ;
191+ assert ! ( nizk. verify( & G :: zero( ) , & h, & x_g, & x_h, dst ) . is_err( ) ) ;
192+ assert ! ( nizk. verify( & g, & G :: zero( ) , & x_g, & x_h, dst ) . is_err( ) ) ;
193+ assert ! ( nizk. verify( & g, & h, & G :: zero( ) , & x_h, dst ) . is_err( ) ) ;
194+ assert ! ( nizk. verify( & g, & h, & x_g, & G :: zero( ) , dst ) . is_err( ) ) ;
172195 }
173196
174197 #[ test]
175198 fn test_serde ( ) {
199+ let dst = b"test" ;
176200 let e = S :: rand ( & mut thread_rng ( ) ) ;
177201 let x2 = S :: rand ( & mut thread_rng ( ) ) ;
178202 let g = G :: generator ( ) * S :: rand ( & mut thread_rng ( ) ) ;
179203 let h = g * e;
180204 let x_g = g * x2;
181205 let x_h = h * x2;
182- let nizk = DdhTupleNizk :: create ( & x2, & g, & h, & x_g, & x_h, & mut thread_rng ( ) ) ;
183- assert ! ( nizk. verify( & g, & h, & x_g, & x_h) . is_ok( ) ) ;
206+ let nizk = DdhTupleNizk :: create ( & x2, & g, & h, & x_g, & x_h, dst , & mut thread_rng ( ) ) ;
207+ assert ! ( nizk. verify( & g, & h, & x_g, & x_h, dst ) . is_ok( ) ) ;
184208
185209 let as_bytes = bcs:: to_bytes ( & nizk) . unwrap ( ) ;
186210 let nizk2: DdhTupleNizk < G > = bcs:: from_bytes ( & as_bytes) . unwrap ( ) ;
0 commit comments