decaf377_rdsa/
signing_key.rs1use decaf377::Fr;
2use rand_core::{CryptoRng, RngCore};
3
4use crate::{Domain, Error, Signature, SpendAuth, VerificationKey};
5
6#[derive(Copy, Clone)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[cfg_attr(feature = "serde", serde(try_from = "SerdeHelper"))]
10#[cfg_attr(feature = "serde", serde(into = "SerdeHelper"))]
11#[cfg_attr(feature = "serde", serde(bound = "D: Domain"))]
12pub struct SigningKey<D: Domain> {
13 sk: Fr,
14 pk: VerificationKey<D>,
15}
16
17impl<'a, D: Domain> From<&'a SigningKey<D>> for VerificationKey<D> {
18 fn from(sk: &'a SigningKey<D>) -> VerificationKey<D> {
19 sk.pk.clone()
20 }
21}
22
23impl<'a, D: Domain> From<SigningKey<D>> for VerificationKey<D> {
24 fn from(sk: SigningKey<D>) -> VerificationKey<D> {
25 sk.pk.clone()
26 }
27}
28
29impl<D: Domain> From<SigningKey<D>> for [u8; 32] {
30 fn from(sk: SigningKey<D>) -> [u8; 32] {
31 sk.sk.to_bytes()
32 }
33}
34
35impl<D: Domain> SigningKey<D> {
36 pub fn to_bytes(&self) -> [u8; 32] {
40 self.sk.to_bytes()
41 }
42}
43
44impl<D: Domain> TryFrom<[u8; 32]> for SigningKey<D> {
45 type Error = Error;
46
47 fn try_from(bytes: [u8; 32]) -> Result<Self, Self::Error> {
48 let sk = Fr::from_bytes_checked(&bytes).map_err(|_| Error::MalformedSigningKey)?;
49 Ok(Self::new_from_field(sk))
50 }
51}
52
53impl<D: Domain> TryFrom<&[u8]> for SigningKey<D> {
54 type Error = Error;
55
56 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
57 if bytes.len() == 32 {
58 let mut bytes32 = [0u8; 32];
59 bytes32.copy_from_slice(bytes);
60 bytes32.try_into()
61 } else {
62 Err(Error::WrongSliceLength {
63 expected: 32,
64 found: bytes.len(),
65 })
66 }
67 }
68}
69
70impl<D: Domain> From<Fr> for SigningKey<D> {
71 fn from(sk: Fr) -> Self {
72 Self::new_from_field(sk)
73 }
74}
75
76#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
77struct SerdeHelper([u8; 32]);
78
79impl<D: Domain> TryFrom<SerdeHelper> for SigningKey<D> {
80 type Error = Error;
81
82 fn try_from(helper: SerdeHelper) -> Result<Self, Self::Error> {
83 helper.0.try_into()
84 }
85}
86
87impl<D: Domain> From<SigningKey<D>> for SerdeHelper {
88 fn from(sk: SigningKey<D>) -> Self {
89 Self(sk.into())
90 }
91}
92
93impl SigningKey<SpendAuth> {
94 pub fn randomize(&self, randomizer: &Fr) -> SigningKey<SpendAuth> {
96 let sk = self.sk + randomizer;
97 let pk = VerificationKey::from(&sk);
98 SigningKey { sk, pk }
99 }
100}
101
102impl<D: Domain> SigningKey<D> {
103 pub fn new<R: RngCore + CryptoRng>(mut rng: R) -> SigningKey<D> {
105 let sk = {
106 let mut bytes = [0; 64];
107 rng.fill_bytes(&mut bytes);
108 Fr::from_le_bytes_mod_order(&bytes[..])
109 };
110 Self::new_from_field(sk)
111 }
112
113 pub fn new_from_field(sk: Fr) -> SigningKey<D> {
120 let pk = VerificationKey::from(&sk);
121 SigningKey { sk, pk }
122 }
123
124 pub fn sign<R: RngCore + CryptoRng>(&self, mut rng: R, msg: &[u8]) -> Signature<D> {
127 let mut bonus_randomness = [0u8; 48];
128 rng.fill_bytes(&mut bonus_randomness);
129 self.sign_inner(&bonus_randomness, msg)
130 }
131
132 pub fn sign_deterministic(&self, msg: &[u8]) -> Signature<D> {
136 let bonus_randomness = [0u8; 48];
137 self.sign_inner(&bonus_randomness, msg)
138 }
139
140 fn sign_inner(&self, bonus_randomness: &[u8; 48], msg: &[u8]) -> Signature<D> {
141 use crate::HStar;
142
143 let nonce = HStar::default()
151 .update(&self.sk.to_bytes()[..])
152 .update(&bonus_randomness[..])
153 .update(&self.pk.bytes.bytes[..]) .update(msg)
155 .finalize();
156
157 let r_bytes = (&D::basepoint() * &nonce).vartime_compress().0;
158
159 let c = HStar::default()
160 .update(&r_bytes[..])
161 .update(&self.pk.bytes.bytes[..]) .update(msg)
163 .finalize();
164
165 let s_bytes = (nonce + (c * self.sk)).to_bytes();
166
167 Signature::from_parts(r_bytes, s_bytes)
168 }
169}
170
171#[cfg(feature = "std")]
172mod std_only {
173 use super::*;
174 use std::fmt;
175
176 use crate::Binding;
177
178 impl fmt::Debug for SigningKey<Binding> {
179 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180 f.debug_tuple("SigningKey<Binding>")
181 .field(&hex::encode(&<[u8; 32]>::from(*self)))
182 .finish()
183 }
184 }
185
186 impl fmt::Debug for SigningKey<SpendAuth> {
187 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
188 f.debug_tuple("SigningKey<SpendAuth>")
189 .field(&hex::encode(&<[u8; 32]>::from(*self)))
190 .finish()
191 }
192 }
193}
194
195#[cfg(feature = "std")]
196pub use std_only::*;