1use crypto_bigint::{U256, Uint, Zero};
21
22type Tag = [u8; 256 / 8];
24
25pub trait Curve {
27 const LEN: usize;
29
30 const PERSONALIZATION_STRING: &'static [u8];
32
33 type Output;
36
37 fn generate(temp: &[u8]) -> Option<Self::Output>;
39}
40
41pub struct Keygen<C: Curve> {
43 k: Tag,
44 v: Tag,
45 _phantom: std::marker::PhantomData<C>,
46}
47
48impl<C: Curve> Keygen<C> {
49 pub fn new(seed: &[u8]) -> Self {
51 let k = [0; 256 / 8];
52 let v = [1; 256 / 8];
53
54 let k = hmac256(
55 k.as_ref(),
56 [v.as_slice(), &[0u8], seed, C::PERSONALIZATION_STRING]
57 .concat()
58 .as_ref(),
59 );
60
61 let v = hmac256(k.as_ref(), &v);
62
63 let k = hmac256(
64 k.as_ref(),
65 [v.as_slice(), &[1u8], seed, C::PERSONALIZATION_STRING]
66 .concat()
67 .as_ref(),
68 );
69
70 let v = hmac256(k.as_ref(), v.as_ref());
71
72 Self {
73 k,
74 v,
75 _phantom: std::marker::PhantomData,
76 }
77 }
78
79 #[doc(hidden)]
80 fn candidate(&mut self) -> Vec<u8> {
81 let mut temp = vec![];
82
83 while temp.len() < C::LEN {
84 self.v = hmac256(self.k.as_ref(), self.v.as_ref());
85 temp.extend_from_slice(self.v.as_ref());
86 }
87
88 temp
89 }
90
91 pub fn generate(mut self) -> C::Output {
93 let temp = self.candidate();
94 let res = C::generate(&temp);
95
96 res.unwrap_or_else(|| {
97 self.k = hmac256(
99 self.k.as_ref(),
100 [self.v.as_slice(), &[0u8]].concat().as_ref(),
101 );
102 self.v = hmac256(self.k.as_slice(), self.v.as_ref());
103
104 let temp = self.candidate();
105 C::generate(&temp).unwrap()
106 })
107 }
108}
109
110pub struct P256 {}
112
113impl Curve for P256 {
114 const PERSONALIZATION_STRING: &'static [u8] = b"det ECDSA key gen P-256";
115 const LEN: usize = 32;
116
117 type Output = [u8; Self::LEN];
118
119 fn generate(temp: &[u8]) -> Option<Self::Output> {
120 const N: U256 =
121 U256::from_be_hex("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551");
122
123 let d = bits2int(temp, 256);
124
125 if d.is_zero().into() || d >= N {
126 None
127 } else {
128 Some(d.to_be_bytes())
129 }
130 }
131}
132
133fn bits2int<const LIMBS: usize>(data: &[u8], qlen: usize) -> Uint<LIMBS> {
134 let mut x = Uint::<LIMBS>::from_be_slice(data);
135
136 let blen = data.len() * 8;
137
138 if blen > qlen {
139 let shift = blen - qlen;
140 x >>= shift;
141 }
142
143 x
144}
145
146#[cfg(feature = "ring")]
147fn hmac256(k: &[u8], v: &[u8]) -> Tag {
148 use ring::hmac;
149
150 let k = hmac::Key::new(hmac::HMAC_SHA256, k);
151 hmac::sign(&k, v)
152 .as_ref()
153 .try_into()
154 .expect("tag larger then 256 bits")
155}
156
157#[cfg(test)]
158mod test {
159 use super::*;
160
161 use std::fs;
162
163 use base64::{Engine as _, engine::general_purpose};
164 use p256::SecretKey;
165 use pkcs8::EncodePrivateKey;
166 use proptest::prelude::*;
167 use ring::{
168 rand::SystemRandom,
169 signature::{
170 ECDSA_P256_SHA256_FIXED, ECDSA_P256_SHA256_FIXED_SIGNING, EcdsaKeyPair, KeyPair,
171 UnparsedPublicKey,
172 },
173 };
174 use serde::{Deserialize, Deserializer};
175
176 fn deserialize_base64<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
177 where
178 D: Deserializer<'de>,
179 {
180 let s: String = Deserialize::deserialize(deserializer)?;
181 general_purpose::STANDARD
182 .decode(&s)
183 .map_err(serde::de::Error::custom)
184 }
185
186 #[derive(Deserialize, Debug)]
187 struct TestVector {
188 curve: String,
189 #[serde(deserialize_with = "deserialize_base64")]
190 seed: Vec<u8>,
191 private_key_pkcs8: String,
192 }
193
194 proptest! {
195 #[test]
196 fn test_fuzz_p256(seed: Vec<u8>) {
197 prop_assume!(!seed.is_empty());
198
199 const MSG: &[u8] = b"hello world";
200
201 let rng = SystemRandom::new();
202
203 let g = Keygen::<P256>::new(&seed);
204 let key = g.generate();
205
206 let key = SecretKey::from_bytes(&key.into()).unwrap();
207 let key = key.to_pkcs8_der().unwrap();
208 let keys =
209 EcdsaKeyPair::from_pkcs8(&ECDSA_P256_SHA256_FIXED_SIGNING, key.as_bytes(), &rng)
210 .unwrap();
211
212 let signature = keys.sign(&rng, MSG).unwrap();
213
214 let public_key = UnparsedPublicKey::new(&ECDSA_P256_SHA256_FIXED, keys.public_key());
215
216 let _sig = public_key.verify(MSG, signature.as_ref()).unwrap();
217 }
218 }
219
220 #[test]
221 fn test_vectors() {
222 let rng = SystemRandom::new();
223
224 let vectors = fs::read_to_string("src/escdsa.json").unwrap();
225 let vectors: Vec<TestVector> = serde_json::from_str(&vectors).unwrap();
226
227 for vector in vectors.iter().filter(|v| v.curve == "secp256r1") {
228 let g = Keygen::<P256>::new(&vector.seed);
229
230 let key = g.generate();
231 let key = SecretKey::from_bytes(&key.into()).unwrap();
232 let key = key.to_pkcs8_der().unwrap();
233 let key = key.as_bytes();
234
235 let _keys = EcdsaKeyPair::from_pkcs8(&ECDSA_P256_SHA256_FIXED_SIGNING, key, &rng);
236
237 let key = general_purpose::STANDARD.encode(key);
238 assert_eq!(
239 key, vector.private_key_pkcs8,
240 "testing with key {:?}",
241 vector.private_key_pkcs8
242 );
243 }
244 }
245}