winterwallet_core/
privkey.rs1use crate::{WinternitzError, WinternitzPubkey, WinternitzSignature};
2use zeroize::{Zeroize, ZeroizeOnDrop};
3
4#[repr(C)]
14#[derive(Zeroize, ZeroizeOnDrop)]
15pub struct WinternitzPrivkey<const N: usize> {
16 scalars: [[u8; 32]; N],
17 checksum: [[u8; 32]; 2],
18}
19
20impl<const N: usize> WinternitzPrivkey<N> {
21 pub(crate) fn new(scalars: [[u8; 32]; N], checksum: [[u8; 32]; 2]) -> Self {
22 const { crate::assert_n::<N>() };
23 Self { scalars, checksum }
24 }
25
26 pub fn as_bytes(&self) -> &[u8] {
29 unsafe {
31 core::slice::from_raw_parts(
32 self as *const Self as *const u8,
33 core::mem::size_of::<Self>(),
34 )
35 }
36 }
37
38 pub fn sign(self, message: &[&[u8]]) -> WinternitzSignature<N> {
47 const { crate::assert_n::<N>() };
48 let h = Self::hash(message);
49 self.sign_prehashed(&h)
50 }
51
52 #[inline(always)]
54 pub fn sign_prehashed(self, hash: &[u8; N]) -> WinternitzSignature<N> {
55 const { crate::assert_n::<N>() };
56 let mut sig_scalars = [[0u8; 32]; N];
57 let mut checksum_sum: u16 = 0;
58 for i in 0..N {
59 let b = hash[i];
60 sig_scalars[i] = crate::chain(&self.scalars[i], b);
61 checksum_sum += 255u16 - b as u16;
62 }
63 let sig_checksum = [
64 crate::chain(&self.checksum[0], (checksum_sum >> 8) as u8),
65 crate::chain(&self.checksum[1], checksum_sum as u8),
66 ];
67 WinternitzSignature::new(sig_scalars, sig_checksum)
68 }
69
70 #[inline(always)]
74 pub fn hash(message: &[&[u8]]) -> [u8; N] {
75 crate::hash::<N>(message)
76 }
77
78 pub fn to_pubkey(&self) -> WinternitzPubkey<N> {
81 const { crate::assert_n::<N>() };
82 let mut scalars = [[0u8; 32]; N];
83 for (out, sk) in scalars.iter_mut().zip(self.scalars.iter()) {
84 *out = crate::chain(sk, 255);
85 }
86 let checksum = [
87 crate::chain(&self.checksum[0], 255),
88 crate::chain(&self.checksum[1], 255),
89 ];
90 WinternitzPubkey::new(scalars, checksum)
91 }
92}
93
94impl<const N: usize> core::fmt::Display for WinternitzPrivkey<N> {
95 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
96 write!(f, "0x")?;
97 for s in self.scalars.iter().chain(self.checksum.iter()) {
98 for b in s {
99 write!(f, "{:02x}", b)?;
100 }
101 }
102 Ok(())
103 }
104}
105
106impl<const N: usize> From<WinternitzPrivkey<N>> for WinternitzPubkey<N> {
107 fn from(sk: WinternitzPrivkey<N>) -> Self {
108 const { crate::assert_n::<N>() };
109 sk.to_pubkey()
110 }
111}
112
113impl<const N: usize> From<&WinternitzPrivkey<N>> for WinternitzPubkey<N> {
114 fn from(sk: &WinternitzPrivkey<N>) -> Self {
115 const { crate::assert_n::<N>() };
116 sk.to_pubkey()
117 }
118}
119
120impl<'a, const N: usize> TryFrom<&'a [u8]> for &'a WinternitzPrivkey<N> {
121 type Error = WinternitzError;
122
123 fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
124 const { crate::assert_n::<N>() };
125 if value.len() != (N + 2) * 32 {
126 return Err(WinternitzError::InvalidLength);
127 }
128 Ok(unsafe { &*value.as_ptr().cast::<WinternitzPrivkey<N>>() })
130 }
131}