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}