1#![allow(dead_code)]
2
3use crate::{
4 Ciphersuite,
5 consts::ecvrf::{
6 challenge::{ECVRF_CHAL_GEN_DST_BACK, ECVRF_CHAL_GEN_DST_FRONT},
7 e2c::{ECVRF_E2C_DST_BACK, ECVRF_E2C_DST_FRONT},
8 proof::{ECVRF_PROOF_DST_BACK, ECVRF_PROOF_DST_FRONT},
9 },
10};
11
12pub(crate) fn encode_to_curve_tai_generator<H: digest::Digest>(
13 suite: Ciphersuite,
14 salt: &[u8],
15 alpha: &[u8],
16) -> impl Iterator<Item = digest::Output<H>> {
17 let mut ctr = 0u8;
19 std::iter::from_fn(move || {
20 let next_ctr_value = ctr.checked_add(1)?;
21 let hash_string = H::new()
27 .chain_update([*suite, ECVRF_E2C_DST_FRONT])
28 .chain_update(salt)
29 .chain_update(alpha)
30 .chain_update([ctr, ECVRF_E2C_DST_BACK])
31 .finalize();
32
33 ctr = next_ctr_value;
34 Some(hash_string)
35 })
36}
37
38pub(crate) fn proof_to_hash<H: digest::Digest>(
39 suite: Ciphersuite,
40 gamma_string: &[u8],
41) -> digest::Output<H> {
42 H::new()
43 .chain_update([*suite, ECVRF_PROOF_DST_FRONT])
44 .chain_update(gamma_string)
45 .chain_update([ECVRF_PROOF_DST_BACK])
46 .finalize()
47}
48
49pub(crate) fn challenge_bytes<'a, const CHALLENGE_LEN: usize, H: digest::Digest>(
50 suite: Ciphersuite,
51 points: impl Iterator<Item = &'a [u8]>,
52) -> zeroize::Zeroizing<[u8; CHALLENGE_LEN]> {
53 let mut hasher = H::new();
54 hasher.update([*suite, ECVRF_CHAL_GEN_DST_FRONT]);
55 let mut point_count = 0u8;
56 for point in points {
57 hasher.update(point);
58 point_count += 1;
59 }
60 debug_assert_eq!(point_count, 5, "Point count MUST be 5");
61 hasher.update([ECVRF_CHAL_GEN_DST_BACK]);
62 let c_string = hasher.finalize();
63
64 zeroize::Zeroizing::new(c_string[..CHALLENGE_LEN].try_into().unwrap())
65}