#![allow(dead_code)]
use super::bn;
use crate::frost::hashing::sha512_256i;
use purecrypto::bignum::BoxedUint;
use purecrypto::rng::RngCore;
pub(crate) fn commit<R: RngCore>(
secrets: &[BoxedUint],
rng: &mut R,
) -> (BoxedUint, Vec<BoxedUint>) {
let r = bn::rand_bits(256, rng);
let mut d = Vec::with_capacity(secrets.len() + 1);
d.push(r);
d.extend_from_slice(secrets);
let c = hash_ints(&d);
(c, d)
}
pub(crate) fn decommit(c: &BoxedUint, d: &[BoxedUint]) -> Option<Vec<BoxedUint>> {
if d.len() < 2 {
return None;
}
let got = hash_ints(d);
if bn::to_be(&got) == bn::to_be(c) {
Some(d[1..].to_vec())
} else {
None
}
}
pub(crate) fn build_secrets(parts: &[Vec<BoxedUint>]) -> Vec<BoxedUint> {
let mut out = Vec::new();
for p in parts {
out.push(bn::u64(p.len() as u64));
out.extend_from_slice(p);
}
out
}
pub(crate) fn parse_secrets(secrets: &[BoxedUint]) -> Option<Vec<Vec<BoxedUint>>> {
if secrets.len() < 2 {
return None;
}
let mut parts = Vec::new();
let mut el = 0usize;
let mut is_len = true;
let mut next_len = 0usize;
while el < secrets.len() {
if is_len {
if secrets[el].bit_len() > 64 {
return None;
}
next_len = usize::try_from(bn::to_u64(&secrets[el])).ok()?;
el += 1;
} else {
let end = el.checked_add(next_len)?;
if end > secrets.len() {
return None;
}
parts.push(secrets[el..end].to_vec());
el = end;
}
is_len = !is_len;
}
Some(parts)
}
fn hash_ints(v: &[BoxedUint]) -> BoxedUint {
let bytes: Vec<Vec<u8>> = v.iter().map(bn::to_be).collect();
let refs: Vec<&[u8]> = bytes.iter().map(|b| b.as_slice()).collect();
bn::from_be(&sha512_256i(&refs))
}