ciphersuite_mirror/
kp256.rs1use zeroize::Zeroize;
2
3use sha2::Sha256;
4
5use group::ff::PrimeField;
6
7use elliptic_curve::{
8 generic_array::GenericArray,
9 bigint::{NonZero, CheckedAdd, Encoding, U384},
10 hash2curve::{Expander, ExpandMsg, ExpandMsgXmd},
11};
12
13use crate::Ciphersuite;
14
15macro_rules! kp_curve {
16 (
17 $feature: literal,
18 $lib: ident,
19
20 $Ciphersuite: ident,
21 $ID: literal
22 ) => {
23 impl Ciphersuite for $Ciphersuite {
24 type F = $lib::Scalar;
25 type G = $lib::ProjectivePoint;
26 type H = Sha256;
27
28 const ID: &'static [u8] = $ID;
29
30 fn generator() -> Self::G {
31 $lib::ProjectivePoint::GENERATOR
32 }
33
34 fn hash_to_F(dst: &[u8], msg: &[u8]) -> Self::F {
35 const K: usize = 128;
52
53 const L: usize = (256 + K) / 8; let mut modulus = [0; L];
62 modulus[16 ..].copy_from_slice(&(Self::F::ZERO - Self::F::ONE).to_bytes());
65 let modulus = U384::from_be_slice(&modulus).checked_add(&U384::ONE).unwrap();
70
71 let mut wide = U384::from_be_bytes({
73 let mut bytes = [0; 48];
74 ExpandMsgXmd::<Sha256>::expand_message(&[msg], &[dst], 48)
75 .unwrap()
76 .fill_bytes(&mut bytes);
77 bytes
78 })
79 .rem(&NonZero::new(modulus).unwrap())
80 .to_be_bytes();
81
82 let mut array = *GenericArray::from_slice(&wide[16 ..]);
84 let res = $lib::Scalar::from_repr(array).unwrap();
85
86 wide.zeroize();
88 array.zeroize();
89 res
90 }
91 }
92 };
93}
94
95#[cfg(test)]
96fn test_oversize_dst<C: Ciphersuite>() {
97 use sha2::Digest;
98
99 let oversize_dst = [0x00; 256];
101 let actual_dst = Sha256::digest([b"H2C-OVERSIZE-DST-".as_ref(), &oversize_dst].concat());
102 assert_eq!(C::hash_to_F(&oversize_dst, &[]), C::hash_to_F(&actual_dst, &[]));
105}
106
107#[cfg(feature = "secp256k1")]
111#[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize)]
112pub struct Secp256k1;
113#[cfg(feature = "secp256k1")]
114kp_curve!("secp256k1", k256, Secp256k1, b"secp256k1");
115#[cfg(feature = "secp256k1")]
116#[test]
117fn test_secp256k1() {
118 ff_group_tests::group::test_prime_group_bits::<_, k256::ProjectivePoint>(&mut rand_core::OsRng);
119
120 assert_eq!(
126 Secp256k1::hash_to_F(
127 b"FROST-secp256k1-SHA256-v11nonce",
128 &hex::decode(
129 "\
13080cbea5e405d169999d8c4b30b755fedb26ab07ec8198cda4873ed8ce5e16773\
13108f89ffe80ac94dcb920c26f3f46140bfc7f95b493f8310f5fc1ea2b01f4254c"
132 )
133 .unwrap()
134 )
135 .to_repr()
136 .iter()
137 .copied()
138 .collect::<Vec<_>>(),
139 hex::decode("acc83278035223c1ba464e2d11bfacfc872b2b23e1041cf5f6130da21e4d8068").unwrap()
140 );
141
142 test_oversize_dst::<Secp256k1>();
143}
144
145#[cfg(feature = "p256")]
149#[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize)]
150pub struct P256;
151#[cfg(feature = "p256")]
152kp_curve!("p256", p256, P256, b"P-256");
153#[cfg(feature = "p256")]
154#[test]
155fn test_p256() {
156 ff_group_tests::group::test_prime_group_bits::<_, p256::ProjectivePoint>(&mut rand_core::OsRng);
157
158 assert_eq!(
159 P256::hash_to_F(
160 b"FROST-P256-SHA256-v11nonce",
161 &hex::decode(
162 "\
163f4e8cf80aec3f888d997900ac7e3e349944b5a6b47649fc32186d2f1238103c6\
1640c9c1a0fe806c184add50bbdcac913dda73e482daf95dcb9f35dbb0d8a9f7731"
165 )
166 .unwrap()
167 )
168 .to_repr()
169 .iter()
170 .copied()
171 .collect::<Vec<_>>(),
172 hex::decode("f871dfcf6bcd199342651adc361b92c941cb6a0d8c8c1a3b91d79e2c1bf3722d").unwrap()
173 );
174
175 test_oversize_dst::<P256>();
176}