wots_rs/secret.rs
1//! WOTS secret keys.
2use crate::signature::Signature;
3use rand::{CryptoRng, RngCore};
4use sha256_rs::*;
5
6/// An WOTS secret key.
7#[derive(Eq, PartialEq)]
8pub struct SecretKey([[u8; 32]; 32]);
9
10impl SecretKey {
11 /// Generate a `SecretKey` from a `csprng`.
12 ///
13 /// # Example
14 ///
15 /// ```
16 /// use rand::rngs::OsRng;
17 /// use wots_rs::SecretKey;
18 ///
19 /// let mut csprng = OsRng{};
20 /// let secret_key: SecretKey = SecretKey::generate(&mut csprng);
21 ///
22 /// ```
23 ///
24 /// # Input
25 ///
26 /// A CSPRNG with a `fill_bytes()` method, e.g. `rand_os::OsRng`.
27 pub fn generate<R>(csprng: &mut R) -> Self
28 where
29 R: CryptoRng + RngCore,
30 {
31 let mut secret_key = [[0u8; 32]; 32];
32
33 for key in secret_key.iter_mut() {
34 let mut temp = [0u8; 32];
35 csprng.fill_bytes(&mut temp);
36 *key = temp;
37 }
38
39 SecretKey(secret_key)
40 }
41
42 // Sign a `message` with this `SecretKey` using the
43 /// WOTS algorithm.
44 ///
45 /// # Inputs
46 ///
47 /// * `message` in bytes representation.
48 ///
49 /// # Returns
50 ///
51 /// An WOTS [`Signature`] on the `message`.
52 ///
53 /// # Example
54 ///
55 /// ```
56 /// use rand::rngs::OsRng;
57 /// use wots_rs::SecretKey;
58 ///
59 /// let mut csprng = OsRng{};
60 /// let secret_key: SecretKey = SecretKey::generate(&mut csprng);
61 ///
62 /// let message = b"hello";
63 /// let signature = secret_key.sign(message);
64 ///
65 /// ```
66 pub fn sign(&self, message: &[u8]) -> Signature {
67 let secret_key = self.0;
68
69 let mut signature = [[0u8; 32]; 32];
70 let hash = sha256(message);
71
72 for (i, s) in signature.iter_mut().enumerate() {
73 let mut key = secret_key[i];
74 let n = hash[i];
75
76 for _ in 0..256 - n as usize {
77 key = sha256(&key);
78 }
79
80 *s = key;
81 }
82
83 Signature::from(signature)
84 }
85
86 /// Convert this secret key to a byte array.
87 pub fn to_bytes(&self) -> [[u8; 32]; 32] {
88 self.0
89 }
90}
91
92/// Construct a `SecretKey` from a bytes.
93impl From<[[u8; 32]; 32]> for SecretKey {
94 fn from(value: [[u8; 32]; 32]) -> Self {
95 Self(value)
96 }
97}