Skip to main content

k256/schnorr/
signing.rs

1//! Taproot Schnorr signing key.
2
3use 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
28/// Number of bytes of auxiliary randomness.
29const AUX_RAND_BYTES: usize = 32;
30
31/// Taproot Schnorr signing key.
32#[derive(Clone)]
33pub struct SigningKey {
34    /// Secret key material
35    secret_key: NonZeroScalar,
36
37    /// Verifying key
38    verifying_key: VerifyingKey,
39}
40
41impl SigningKey {
42    /// Parse signing key from big endian-encoded bytes.
43    ///
44    /// # Errors
45    /// Returns [`Error`] in the event the provided bytes overflow the curve order `n`.
46    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    /// Parse signing key from big endian-encoded byte slice.
54    ///
55    /// # Errors
56    /// Returns [`Error`] if `bytes` is not 32-bytes long, or if it overflows the curve order `n`.
57    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    /// Serialize as bytes.
63    #[must_use]
64    pub fn to_bytes(&self) -> FieldBytes {
65        self.secret_key.to_bytes()
66    }
67
68    /// Get the [`VerifyingKey`] that corresponds to this signing key.
69    #[must_use]
70    pub fn verifying_key(&self) -> &VerifyingKey {
71        &self.verifying_key
72    }
73
74    /// Borrow the secret [`NonZeroScalar`] value for this key.
75    ///
76    /// <div class="warning">
77    /// <b>Security Warning<b>
78    ///
79    /// This value is key material. Please treat it with the care it deserves!
80    /// </div>
81    #[must_use]
82    pub fn as_nonzero_scalar(&self) -> &NonZeroScalar {
83        &self.secret_key
84    }
85
86    /// Compute Schnorr signature.
87    ///
88    /// This is a low-level interface intended only for use cases that need to explicitly pass
89    /// `aux_rand` rather than deriving it from an RNG.
90    ///
91    /// Prefer higher-level APIs like `Signer`, `RandomizedSigner`, or `(Randomized)PrehashSigner`
92    /// instead whenever possible.
93    ///
94    /// # Errors
95    /// Returns an error if the generated signature would be invalid (i.e. if derived `k` were `0`).
96    #[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        // Compute R = k*G using precomputed tables, convert to affine once, and ensure R has an
115        // even y-coordinate (BIP340 requirement).
116        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: Generate a cryptographically random [`SigningKey`].
140    #[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        // Compute the public key point once using precomputed generator tables,
150        // then conditionally negate to ensure even y.
151        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
207//
208// `*Signer` trait impls
209//
210
211impl<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        // Handle `k = 0` by retrying signature with different `aux_rand`. The chances of this
225        // occurring are infinitesimal and a single retry should be sufficient.
226        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
310//
311// Other trait impls
312//
313
314impl 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}