wots_rs/
public.rs

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