Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions schnorr_fun/src/frost/chilldkg/encpedpop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,11 @@ impl AggKeygenInput {
let tweak_poly = shared_key.grind_fingerprint::<H>(fingerprint);
// replace our poly with the one that has the fingerprint
self.inner.agg_poly = shared_key.point_polynomial()[1..].to_vec();
debug_assert!(self.shared_key().check_fingerprint::<H>(fingerprint));
debug_assert!(
self.shared_key()
.check_fingerprint::<H>(fingerprint)
.is_some()
);

for (share_index, (_encryption_key, encrypted_secret_share)) in &mut self.encrypted_shares {
// 💡 The share encryption is homomorphic so we can apply the tweak
Expand Down Expand Up @@ -556,8 +560,10 @@ mod test {
for share in paired_shares {
assert_eq!(shared_key.pair_secret_share(*share.secret_share()), Some(share));
}
let bits_matched = shared_key.check_fingerprint::<sha2::Sha256>(fingerprint).unwrap();

assert!(shared_key.check_fingerprint::<sha2::Sha256>(fingerprint), "fingerprint was grinded correctly");
let should_have_matched = ((threshold - 1) * bits_per_coeff as u32).min(max_bits_total as u32);
assert_eq!(bits_matched, should_have_matched as usize, "fingerprint was grinded correctly");
}
}

Expand Down
35 changes: 21 additions & 14 deletions schnorr_fun/src/frost/shared_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,15 +193,21 @@ impl<T: Normalized, Z: ZeroChoice> SharedKey<T, Z> {
/// This allows detection of shares from the same DKG session and helps
/// identify corrupted or mismatched shares.
///
/// Returns `true` if all coefficients match the fingerprint pattern, `false`
/// if any coefficient fails to meet the difficulty requirement.
pub fn check_fingerprint<H: crate::fun::hash::Hash32>(&self, fingerprint: Fingerprint) -> bool {
/// Returns `Some(n)` where `n` is the number of bits verified if
/// successful, or `None` if verification failed. Returns `Some(0)` if the
/// polynomial is too short (≤1 coefficients) to contain a fingerprint. It
/// will never return more than `max_bits_total` which indicates a complete
/// match.
pub fn check_fingerprint<H: crate::fun::hash::Hash32>(
&self,
fingerprint: Fingerprint,
) -> Option<usize> {
use crate::fun::hash::HashAdd;

// the fingerprint is only placed on the non-constant coefficients so it
// can't be detected with a length 1 polynomial
if self.point_polynomial.len() <= 1 {
return true;
return Some(0);
}

let mut hash_state = H::default()
Expand All @@ -214,20 +220,19 @@ impl<T: Normalized, Z: ZeroChoice> SharedKey<T, Z> {

// Check each non-constant coefficient
for i in 1..self.point_polynomial.len() {
// Update hash state with next coefficient
hash_state = hash_state.add(self.point_polynomial[i]);

let hash_result = hash_state.clone().finalize_fixed();
let hash_bytes: &[u8] = hash_result.as_ref();

let remaining_total = fingerprint
.max_bits_total
.saturating_sub(verified_bits as u8) as usize;
if remaining_total == 0 {
// We've verified enough bits total
break;
}

// Update hash state with next coefficient
hash_state = hash_state.add(self.point_polynomial[i]);

let hash_result = hash_state.clone().finalize_fixed();
let hash_bytes: &[u8] = hash_result.as_ref();

// NOTE: we don't get the zero bits and just substract it from the
// total and move on -- we need to make sure each coefficient has at
// least the required number of bits to make sure it really was part
Expand All @@ -236,13 +241,13 @@ impl<T: Normalized, Z: ZeroChoice> SharedKey<T, Z> {
let actual_bits = Fingerprint::leading_zero_bits(hash_bytes);

if actual_bits < expected_bits {
return false;
return None;
}

verified_bits += expected_bits;
}

true
Some(verified_bits)
}

/// Grinds polynomial coefficients to embed the specified `fingerprint` through
Expand Down Expand Up @@ -594,7 +599,9 @@ mod test {

// Verify the fingerprint is valid
assert!(
shared_key.check_fingerprint::<sha2::Sha256>(fingerprint),
shared_key
.check_fingerprint::<sha2::Sha256>(fingerprint)
.is_some(),
"Grinded fingerprint should be valid"
);
}
Expand Down