1use fn_dsa::{
2 DOMAIN_NONE, FN_DSA_LOGN_1024, HASH_ID_RAW, KeyPairGenerator, KeyPairGeneratorStandard,
3 SigningKey, SigningKeyStandard, VerifyingKey, VerifyingKeyStandard, sign_key_size,
4 signature_size, vrfy_key_size,
5};
6use rand_core::OsRng;
7use zeroize::Zeroizing;
8
9use crate::errors::CryptoError;
10
11pub const PUBLIC_KEY_BYTES: usize = vrfy_key_size(FN_DSA_LOGN_1024);
13pub const SECRET_KEY_BYTES: usize = sign_key_size(FN_DSA_LOGN_1024);
15pub const SIGNATURE_BYTES: usize = signature_size(FN_DSA_LOGN_1024);
17
18pub type PublicKeyBytes = [u8; PUBLIC_KEY_BYTES];
20pub type SecretKeyBytes = [u8; SECRET_KEY_BYTES];
22pub type SignatureBytes = [u8; SIGNATURE_BYTES];
24
25pub trait ViewOperations {
30 fn pub_key_bytes(&self) -> &PublicKeyBytes;
32
33 fn verify(&self, msg: &[u8], sig: &[u8]) -> bool {
42 VerifyingKeyStandard::decode(self.pub_key_bytes())
43 .is_some_and(|vk| vk.verify(sig, &DOMAIN_NONE, &HASH_ID_RAW, msg))
44 }
45}
46
47#[derive(Clone)]
52pub struct VerifierPair {
53 pub_key: PublicKeyBytes,
54}
55
56impl VerifierPair {
57 pub fn new(pub_key: &[u8]) -> Result<Self, CryptoError> {
66 let pub_key: PublicKeyBytes = pub_key
67 .try_into()
68 .map_err(|_| CryptoError::IncongruentLength(PUBLIC_KEY_BYTES, pub_key.len()))?;
69 VerifyingKeyStandard::decode(&pub_key).ok_or(CryptoError::InvalidKey)?;
70 Ok(Self { pub_key })
71 }
72
73 pub fn from_bytes(pub_key: &[u8]) -> Result<Self, CryptoError> {
81 Self::new(pub_key)
82 }
83
84 pub fn to_bytes(&self) -> PublicKeyBytes {
89 self.pub_key
90 }
91}
92
93impl ViewOperations for VerifierPair {
94 fn pub_key_bytes(&self) -> &PublicKeyBytes {
95 &self.pub_key
96 }
97}
98
99pub struct SignerPair {
106 pub_key: PublicKeyBytes,
107 sec_key: Zeroizing<SecretKeyBytes>,
108 signing_key: Box<SigningKeyStandard>,
110}
111
112impl SignerPair {
113 pub fn create() -> Self {
118 let mut pub_key = [0u8; PUBLIC_KEY_BYTES];
119 let mut sec_key = Zeroizing::new([0u8; SECRET_KEY_BYTES]);
120 KeyPairGeneratorStandard::default().keygen(
121 FN_DSA_LOGN_1024,
122 &mut OsRng,
123 &mut sec_key[..],
124 &mut pub_key,
125 );
126 let signing_key = decode_signing_key(&sec_key).expect("freshly generated key decodes");
127 Self {
128 pub_key,
129 sec_key,
130 signing_key,
131 }
132 }
133
134 pub fn sign(&mut self, msg: &[u8]) -> Result<SignatureBytes, CryptoError> {
143 let mut sig = [0u8; SIGNATURE_BYTES];
144 self.signing_key
145 .sign(&mut OsRng, &DOMAIN_NONE, &HASH_ID_RAW, msg, &mut sig)
146 .ok_or(CryptoError::InvalidKey)?;
147 Ok(sig)
148 }
149
150 pub fn from_bytes(pub_key: &[u8], sec_key: &[u8]) -> Result<Self, CryptoError> {
160 let sec_key: Zeroizing<SecretKeyBytes> = Zeroizing::new(
161 sec_key
162 .try_into()
163 .map_err(|_| CryptoError::IncongruentLength(SECRET_KEY_BYTES, sec_key.len()))?,
164 );
165 let signing_key = decode_signing_key(&sec_key).ok_or(CryptoError::InvalidKey)?;
166 let mut derived = [0u8; PUBLIC_KEY_BYTES];
167 signing_key.to_verifying_key(&mut derived);
168 if derived[..] != *pub_key {
169 return Err(CryptoError::InvalidKey);
170 }
171 Ok(Self {
172 pub_key: derived,
173 sec_key,
174 signing_key,
175 })
176 }
177
178 pub fn to_bytes(&self) -> (PublicKeyBytes, Zeroizing<SecretKeyBytes>) {
183 (self.pub_key, self.sec_key.clone())
184 }
185
186 pub fn to_bytes_uniform(&self) -> Zeroizing<Vec<u8>> {
191 Zeroizing::new([&self.pub_key[..], &self.sec_key[..]].concat())
192 }
193
194 pub fn from_bytes_uniform(bytes: &[u8]) -> Result<Self, CryptoError> {
202 if bytes.len() != PUBLIC_KEY_BYTES + SECRET_KEY_BYTES {
203 return Err(CryptoError::IncongruentLength(
204 PUBLIC_KEY_BYTES + SECRET_KEY_BYTES,
205 bytes.len(),
206 ));
207 }
208 let (pub_key, sec_key) = bytes.split_at(PUBLIC_KEY_BYTES);
209 Self::from_bytes(pub_key, sec_key)
210 }
211}
212
213impl Clone for SignerPair {
214 fn clone(&self) -> Self {
215 Self {
216 pub_key: self.pub_key,
217 sec_key: self.sec_key.clone(),
218 signing_key: decode_signing_key(&self.sec_key).expect("a decoded key decodes again"),
219 }
220 }
221}
222
223impl ViewOperations for SignerPair {
224 fn pub_key_bytes(&self) -> &PublicKeyBytes {
225 &self.pub_key
226 }
227}
228
229fn decode_signing_key(sec_key: &SecretKeyBytes) -> Option<Box<SigningKeyStandard>> {
236 let decode = || SigningKeyStandard::decode(sec_key).map(Box::new);
237 std::thread::scope(|scope| {
238 match std::thread::Builder::new()
239 .stack_size(8 << 20)
240 .spawn_scoped(scope, decode)
241 {
242 Ok(handle) => handle
243 .join()
244 .unwrap_or_else(|panic| std::panic::resume_unwind(panic)),
245 Err(_) => decode(),
247 }
248 })
249}
250
251#[cfg(test)]
252mod tests {
253 use super::*;
254
255 #[test]
256 fn test_signer_sign() {
257 let mut signer = SignerPair::create();
258 let msg = b"Hello, World!";
259 let sig = signer.sign(msg).unwrap();
260
261 assert!(signer.verify(msg, &sig));
262 assert!(!signer.verify(b"Hello, World?", &sig));
263 }
264
265 #[test]
266 fn test_verifier_verify() {
267 let mut signer = SignerPair::create();
268 let msg = b"Hello, World!";
269 let sig = signer.sign(msg).unwrap();
270
271 let verifier = VerifierPair::new(signer.pub_key_bytes()).unwrap();
272 assert!(verifier.verify(msg, &sig));
273
274 let other = VerifierPair::new(SignerPair::create().pub_key_bytes()).unwrap();
275 assert!(!other.verify(msg, &sig));
276 }
277
278 #[test]
279 fn test_signer_bytes() {
280 let signer = SignerPair::create();
281 let (pub_key, sec_key) = signer.to_bytes();
282
283 let mut signer2 = SignerPair::from_bytes(&pub_key, &sec_key[..]).unwrap();
284 assert_eq!(signer.pub_key_bytes(), signer2.pub_key_bytes());
285 assert!(signer.verify(b"msg", &signer2.sign(b"msg").unwrap()));
286
287 let signer3 = SignerPair::from_bytes_uniform(&signer.to_bytes_uniform()).unwrap();
288 assert_eq!(signer.pub_key_bytes(), signer3.pub_key_bytes());
289
290 assert!(signer.verify(b"msg", &signer3.clone().sign(b"msg").unwrap()));
292 }
293
294 #[test]
295 fn test_invalid_inputs() {
296 let mut signer = SignerPair::create();
297 let (pub_key, sec_key) = signer.to_bytes();
298
299 assert!(matches!(
300 SignerPair::from_bytes_uniform(&[0u8; 10]),
301 Err(CryptoError::IncongruentLength(n, 10)) if n == PUBLIC_KEY_BYTES + SECRET_KEY_BYTES
302 ));
303 assert!(matches!(
304 SignerPair::from_bytes(&pub_key, &sec_key[1..]),
305 Err(CryptoError::IncongruentLength(SECRET_KEY_BYTES, _))
306 ));
307
308 let mut bad_sec = sec_key.clone();
310 bad_sec[0] ^= 0xFF;
311 assert!(matches!(
312 SignerPair::from_bytes(&pub_key, &bad_sec[..]),
313 Err(CryptoError::InvalidKey)
314 ));
315 let mut bad_pub = pub_key;
316 bad_pub[0] ^= 0xFF;
317 assert!(matches!(
318 VerifierPair::new(&bad_pub),
319 Err(CryptoError::InvalidKey)
320 ));
321
322 let sig = signer.sign(b"msg").unwrap();
324 assert!(!signer.verify(b"msg", &sig[..10]));
325 assert!(!signer.verify(b"msg", &[]));
326 let mut flipped = sig;
327 flipped[100] ^= 1;
328 assert!(!signer.verify(b"msg", &flipped));
329 }
330
331 #[test]
332 fn test_works_on_small_stack() {
333 let bytes = SignerPair::create().to_bytes_uniform();
336 std::thread::Builder::new()
337 .stack_size(512 << 10)
338 .spawn(move || {
339 let mut signer = SignerPair::from_bytes_uniform(&bytes).unwrap();
340 let sig = signer.sign(b"msg").unwrap();
341 assert!(signer.verify(b"msg", &sig));
342 assert!(signer.clone().verify(b"msg", &sig));
343 })
344 .unwrap()
345 .join()
346 .unwrap();
347 }
348
349 #[test]
350 fn test_signer_rejects_foreign_pubkey() {
351 let signer = SignerPair::create();
352 let other = SignerPair::create();
353 let result = SignerPair::from_bytes(other.pub_key_bytes(), &signer.to_bytes().1[..]);
354 assert!(matches!(result, Err(CryptoError::InvalidKey)));
355 }
356
357 #[test]
358 fn test_verifier_bytes() {
359 let signer = SignerPair::create();
360 let verifier = VerifierPair::new(signer.pub_key_bytes()).unwrap();
361 let pub_key = verifier.to_bytes();
362
363 let verifier2 = VerifierPair::from_bytes(&pub_key).unwrap();
364 assert_eq!(verifier.pub_key_bytes(), verifier2.pub_key_bytes());
365
366 assert!(matches!(
367 VerifierPair::new(&pub_key[1..]),
368 Err(CryptoError::IncongruentLength(PUBLIC_KEY_BYTES, _))
369 ));
370 }
371}