1use super::{AUX_TAG, CHALLENGE_TAG, NONCE_TAG, Signature, VerifyingKey, tagged_hash};
4use crate::{
5 AffinePoint, FieldBytes, NonZeroScalar, ProjectivePoint, PublicKey, Scalar, SecretKey,
6};
7use core::fmt;
8use elliptic_curve::{
9 Generate,
10 ops::Reduce,
11 rand_core::{CryptoRng, TryCryptoRng},
12 subtle::ConditionallySelectable,
13 zeroize::{Zeroize, ZeroizeOnDrop},
14};
15use sha2::{Digest, Sha256};
16use signature::{
17 DigestSigner, Error, KeypairRef, MultipartSigner, RandomizedDigestSigner,
18 RandomizedMultipartSigner, RandomizedSigner, Result, Signer,
19 digest::{Update, consts::U32},
20 hazmat::{PrehashSigner, RandomizedPrehashSigner},
21};
22
23#[cfg(feature = "serde")]
24use serdect::serde::{Deserialize, Serialize, de, ser};
25#[cfg(debug_assertions)]
26use signature::hazmat::PrehashVerifier;
27
28const AUX_RAND_BYTES: usize = 32;
30
31#[derive(Clone)]
33pub struct SigningKey {
34 secret_key: NonZeroScalar,
36
37 verifying_key: VerifyingKey,
39}
40
41impl SigningKey {
42 pub fn from_bytes(bytes: &FieldBytes) -> Result<Self> {
47 NonZeroScalar::from_repr(*bytes)
48 .into_option()
49 .map(Into::into)
50 .ok_or_else(Error::new)
51 }
52
53 pub fn from_slice(bytes: &[u8]) -> Result<Self> {
58 let x_bytes = FieldBytes::try_from(bytes).map_err(|_| Error::new())?;
59 Self::from_bytes(&x_bytes)
60 }
61
62 #[must_use]
64 pub fn to_bytes(&self) -> FieldBytes {
65 self.secret_key.to_bytes()
66 }
67
68 #[must_use]
70 pub fn verifying_key(&self) -> &VerifyingKey {
71 &self.verifying_key
72 }
73
74 #[must_use]
82 pub fn as_nonzero_scalar(&self) -> &NonZeroScalar {
83 &self.secret_key
84 }
85
86 #[doc(hidden)]
97 pub fn sign_raw(&self, msg: &[u8], aux_rand: &[u8; AUX_RAND_BYTES]) -> Result<Signature> {
98 let mut t = tagged_hash(AUX_TAG).chain_update(aux_rand).finalize();
99
100 for (a, b) in t.iter_mut().zip(self.secret_key.to_bytes().iter()) {
101 *a ^= b;
102 }
103
104 let rand = tagged_hash(NONCE_TAG)
105 .chain_update(t)
106 .chain_update(self.verifying_key.as_affine().x.to_bytes())
107 .chain_update(msg)
108 .finalize();
109
110 let mut k = NonZeroScalar::new(Scalar::reduce(&rand))
111 .into_option()
112 .ok_or_else(Error::new)?;
113
114 let R = ProjectivePoint::mul_by_generator(&k).to_affine();
117 let odd = R.y.normalize().is_odd();
118 k.conditional_assign(&-k, odd);
119 let r = R.x.normalize();
120
121 let e = Scalar::reduce(
122 &tagged_hash(CHALLENGE_TAG)
123 .chain_update(r.to_bytes())
124 .chain_update(self.verifying_key.to_bytes())
125 .chain_update(msg)
126 .finalize(),
127 );
128
129 let s = *k + e * *self.secret_key;
130 let s = NonZeroScalar::new(s).into_option().ok_or_else(Error::new)?;
131 let sig = Signature { r, s };
132
133 #[cfg(debug_assertions)]
134 self.verifying_key.verify_prehash(msg, &sig)?;
135
136 Ok(sig)
137 }
138
139 #[deprecated(since = "0.14.0", note = "use the `Generate` trait instead")]
141 pub fn random<R: CryptoRng + ?Sized>(rng: &mut R) -> Self {
142 Self::generate_from_rng(rng)
143 }
144}
145
146impl From<NonZeroScalar> for SigningKey {
147 #[inline]
148 fn from(mut secret_key: NonZeroScalar) -> SigningKey {
149 let point = ProjectivePoint::mul_by_generator(&secret_key).to_affine();
152 let odd = point.y.normalize().is_odd();
153
154 secret_key.conditional_assign(&-secret_key, odd);
155 let neg_point = -point;
156 let correct_point = AffinePoint::conditional_select(&point, &neg_point, odd);
157
158 let verifying_key = VerifyingKey {
159 inner: PublicKey::from_affine(correct_point)
160 .unwrap_or_else(|_| PublicKey::from_secret_scalar(&secret_key)),
161 };
162
163 SigningKey {
164 secret_key,
165 verifying_key,
166 }
167 }
168}
169
170impl From<SecretKey> for SigningKey {
171 #[inline]
172 fn from(secret_key: SecretKey) -> SigningKey {
173 SigningKey::from(&secret_key)
174 }
175}
176
177impl From<&SecretKey> for SigningKey {
178 fn from(secret_key: &SecretKey) -> SigningKey {
179 secret_key.to_nonzero_scalar().into()
180 }
181}
182
183impl Generate for SigningKey {
184 fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(
185 rng: &mut R,
186 ) -> core::result::Result<Self, R::Error> {
187 Ok(NonZeroScalar::try_generate_from_rng(rng)?.into())
188 }
189}
190
191impl TryFrom<&[u8]> for SigningKey {
192 type Error = Error;
193
194 fn try_from(bytes: &[u8]) -> Result<SigningKey> {
195 Self::from_slice(bytes)
196 }
197}
198
199impl fmt::Debug for SigningKey {
200 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201 f.debug_struct("SigningKey")
202 .field("verifying_key", &self.verifying_key)
203 .finish_non_exhaustive()
204 }
205}
206
207impl<D> DigestSigner<D, Signature> for SigningKey
212where
213 D: Digest<OutputSize = U32> + Update,
214{
215 fn try_sign_digest<F: Fn(&mut D) -> Result<()>>(&self, f: F) -> Result<Signature> {
216 let mut digest = D::new();
217 f(&mut digest)?;
218 self.sign_prehash(&digest.finalize())
219 }
220}
221
222impl PrehashSigner<Signature> for SigningKey {
223 fn sign_prehash(&self, prehash: &[u8]) -> Result<Signature> {
224 for i in 0..=u8::MAX {
227 let mut aux_rand = [0u8; AUX_RAND_BYTES];
228 aux_rand[0] = i;
229
230 if let Ok(sig) = self.sign_raw(prehash, &aux_rand) {
231 return Ok(sig);
232 }
233 }
234
235 Err(Error::new())
236 }
237}
238
239impl<D> RandomizedDigestSigner<D, Signature> for SigningKey
240where
241 D: Digest<OutputSize = U32> + Update,
242{
243 fn try_sign_digest_with_rng<R: TryCryptoRng + ?Sized, F: Fn(&mut D) -> Result<()>>(
244 &self,
245 rng: &mut R,
246 f: F,
247 ) -> Result<Signature> {
248 let mut digest = D::new();
249 f(&mut digest)?;
250
251 let mut aux_rand = [0u8; AUX_RAND_BYTES];
252 rng.try_fill_bytes(&mut aux_rand)
253 .map_err(|_| Error::new())?;
254 self.sign_raw(&digest.finalize(), &aux_rand)
255 }
256}
257
258impl RandomizedSigner<Signature> for SigningKey {
259 fn try_sign_with_rng<R: TryCryptoRng + ?Sized>(
260 &self,
261 rng: &mut R,
262 msg: &[u8],
263 ) -> Result<Signature> {
264 self.try_multipart_sign_with_rng(rng, &[msg])
265 }
266}
267
268impl RandomizedMultipartSigner<Signature> for SigningKey {
269 fn try_multipart_sign_with_rng<R: TryCryptoRng + ?Sized>(
270 &self,
271 rng: &mut R,
272 msg: &[&[u8]],
273 ) -> Result<Signature> {
274 self.try_sign_digest_with_rng(rng, |digest: &mut Sha256| {
275 msg.iter().for_each(|&slice| Update::update(digest, slice));
276 Ok(())
277 })
278 }
279}
280
281impl RandomizedPrehashSigner<Signature> for SigningKey {
282 fn sign_prehash_with_rng<R: TryCryptoRng + ?Sized>(
283 &self,
284 rng: &mut R,
285 prehash: &[u8],
286 ) -> Result<Signature> {
287 let mut aux_rand = [0u8; AUX_RAND_BYTES];
288 rng.try_fill_bytes(&mut aux_rand)
289 .map_err(|_| Error::new())?;
290
291 self.sign_raw(prehash, &aux_rand)
292 }
293}
294
295impl Signer<Signature> for SigningKey {
296 fn try_sign(&self, msg: &[u8]) -> Result<Signature> {
297 self.try_multipart_sign(&[msg])
298 }
299}
300
301impl MultipartSigner<Signature> for SigningKey {
302 fn try_multipart_sign(&self, msg: &[&[u8]]) -> Result<Signature> {
303 self.try_sign_digest(|digest: &mut Sha256| {
304 msg.iter().for_each(|&slice| Update::update(digest, slice));
305 Ok(())
306 })
307 }
308}
309
310impl AsRef<VerifyingKey> for SigningKey {
315 fn as_ref(&self) -> &VerifyingKey {
316 &self.verifying_key
317 }
318}
319
320impl Drop for SigningKey {
321 fn drop(&mut self) {
322 self.secret_key.zeroize();
323 }
324}
325
326impl KeypairRef for SigningKey {
327 type VerifyingKey = VerifyingKey;
328}
329
330impl ZeroizeOnDrop for SigningKey {}
331
332#[cfg(feature = "serde")]
333impl Serialize for SigningKey {
334 fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
335 where
336 S: ser::Serializer,
337 {
338 self.secret_key.serialize(serializer)
339 }
340}
341
342#[cfg(feature = "serde")]
343impl<'de> Deserialize<'de> for SigningKey {
344 fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
345 where
346 D: de::Deserializer<'de>,
347 {
348 Ok(SigningKey::from(NonZeroScalar::deserialize(deserializer)?))
349 }
350}