use subtle::ConstantTimeEq;
use crate::keys::KeriPublicKey;
use crate::types::Said;
pub fn compute_next_commitment(key: &KeriPublicKey) -> Said {
#[allow(clippy::expect_used)] let qb64 = key
.to_qb64()
.expect("a valid KeriPublicKey always CESR-encodes");
let hash = blake3::hash(qb64.as_bytes());
#[allow(clippy::expect_used)] let said = crate::cesr_encode::encode_blake3_digest(hash.as_bytes())
.expect("32-byte Blake3 digest always encodes");
Said::new_unchecked(said)
}
pub fn verify_commitment(key: &KeriPublicKey, commitment: &Said) -> bool {
let computed = compute_next_commitment(key);
computed
.as_str()
.as_bytes()
.ct_eq(commitment.as_str().as_bytes())
.into()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn commitment_verification_works() {
let key = KeriPublicKey::Ed25519([1u8; 32]);
let commitment = compute_next_commitment(&key);
assert!(verify_commitment(&key, &commitment));
assert!(!verify_commitment(
&KeriPublicKey::Ed25519([2u8; 32]),
&commitment
));
}
#[test]
fn commitment_is_deterministic() {
let key = KeriPublicKey::Ed25519([42u8; 32]);
let c1 = compute_next_commitment(&key);
let c2 = compute_next_commitment(&key);
assert_eq!(c1, c2);
assert!(c1.as_str().starts_with('E'));
}
#[test]
fn commitment_has_correct_length() {
let commitment = compute_next_commitment(&KeriPublicKey::Ed25519([0u8; 32]));
assert_eq!(commitment.as_str().len(), 44);
}
}