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}