@@ -193,15 +193,21 @@ impl<T: Normalized, Z: ZeroChoice> SharedKey<T, Z> {
193193 /// This allows detection of shares from the same DKG session and helps
194194 /// identify corrupted or mismatched shares.
195195 ///
196- /// Returns `true` if all coefficients match the fingerprint pattern, `false`
197- /// if any coefficient fails to meet the difficulty requirement.
198- pub fn check_fingerprint < H : crate :: fun:: hash:: Hash32 > ( & self , fingerprint : Fingerprint ) -> bool {
196+ /// Returns `Some(n)` where `n` is the number of bits verified if
197+ /// successful, or `None` if verification failed. Returns `Some(0)` if the
198+ /// polynomial is too short (≤1 coefficients) to contain a fingerprint. It
199+ /// will never return more than `max_bits_total` which indicates a complete
200+ /// match.
201+ pub fn check_fingerprint < H : crate :: fun:: hash:: Hash32 > (
202+ & self ,
203+ fingerprint : Fingerprint ,
204+ ) -> Option < usize > {
199205 use crate :: fun:: hash:: HashAdd ;
200206
201207 // the fingerprint is only placed on the non-constant coefficients so it
202208 // can't be detected with a length 1 polynomial
203209 if self . point_polynomial . len ( ) <= 1 {
204- return true ;
210+ return Some ( 0 ) ;
205211 }
206212
207213 let mut hash_state = H :: default ( )
@@ -214,20 +220,19 @@ impl<T: Normalized, Z: ZeroChoice> SharedKey<T, Z> {
214220
215221 // Check each non-constant coefficient
216222 for i in 1 ..self . point_polynomial . len ( ) {
217- // Update hash state with next coefficient
218- hash_state = hash_state. add ( self . point_polynomial [ i] ) ;
219-
220- let hash_result = hash_state. clone ( ) . finalize_fixed ( ) ;
221- let hash_bytes: & [ u8 ] = hash_result. as_ref ( ) ;
222-
223223 let remaining_total = fingerprint
224224 . max_bits_total
225225 . saturating_sub ( verified_bits as u8 ) as usize ;
226226 if remaining_total == 0 {
227- // We've verified enough bits total
228227 break ;
229228 }
230229
230+ // Update hash state with next coefficient
231+ hash_state = hash_state. add ( self . point_polynomial [ i] ) ;
232+
233+ let hash_result = hash_state. clone ( ) . finalize_fixed ( ) ;
234+ let hash_bytes: & [ u8 ] = hash_result. as_ref ( ) ;
235+
231236 // NOTE: we don't get the zero bits and just substract it from the
232237 // total and move on -- we need to make sure each coefficient has at
233238 // least the required number of bits to make sure it really was part
@@ -236,13 +241,13 @@ impl<T: Normalized, Z: ZeroChoice> SharedKey<T, Z> {
236241 let actual_bits = Fingerprint :: leading_zero_bits ( hash_bytes) ;
237242
238243 if actual_bits < expected_bits {
239- return false ;
244+ return None ;
240245 }
241246
242247 verified_bits += expected_bits;
243248 }
244249
245- true
250+ Some ( verified_bits )
246251 }
247252
248253 /// Grinds polynomial coefficients to embed the specified `fingerprint` through
@@ -594,7 +599,9 @@ mod test {
594599
595600 // Verify the fingerprint is valid
596601 assert ! (
597- shared_key. check_fingerprint:: <sha2:: Sha256 >( fingerprint) ,
602+ shared_key
603+ . check_fingerprint:: <sha2:: Sha256 >( fingerprint)
604+ . is_some( ) ,
598605 "Grinded fingerprint should be valid"
599606 ) ;
600607 }
0 commit comments