frost_core/
signing_key.rs

1//! Schnorr signature signing keys
2
3use alloc::vec::Vec;
4
5use rand_core::{CryptoRng, RngCore};
6
7use crate::{
8    random_nonzero, serialization::SerializableScalar, Challenge, Ciphersuite, Error, Field, Group,
9    Scalar, Signature, VerifyingKey,
10};
11
12/// A signing key for a Schnorr signature on a FROST [`Ciphersuite::Group`].
13#[derive(Copy, Clone, PartialEq, Eq)]
14pub struct SigningKey<C>
15where
16    C: Ciphersuite,
17{
18    pub(crate) scalar: Scalar<C>,
19}
20
21impl<C> SigningKey<C>
22where
23    C: Ciphersuite,
24{
25    /// Generate a new signing key.
26    pub fn new<R: RngCore + CryptoRng>(rng: &mut R) -> SigningKey<C> {
27        let scalar = random_nonzero::<C, R>(rng);
28
29        SigningKey { scalar }
30    }
31
32    /// Deserialize from bytes
33    pub fn deserialize(bytes: &[u8]) -> Result<SigningKey<C>, Error<C>> {
34        Self::from_scalar(SerializableScalar::deserialize(bytes)?.0)
35    }
36
37    /// Serialize `SigningKey` to bytes
38    pub fn serialize(&self) -> Vec<u8> {
39        SerializableScalar::<C>(self.scalar).serialize()
40    }
41
42    /// Create a signature `msg` using this `SigningKey`.
43    pub fn sign<R: RngCore + CryptoRng>(&self, rng: R, message: &[u8]) -> Signature<C> {
44        <C>::single_sign(self, rng, message)
45    }
46
47    /// Create a signature `msg` using this `SigningKey` using the default
48    /// signing.
49    #[cfg_attr(feature = "internals", visibility::make(pub))]
50    pub(crate) fn default_sign<R: RngCore + CryptoRng>(
51        &self,
52        mut rng: R,
53        message: &[u8],
54    ) -> Signature<C> {
55        let public = VerifyingKey::<C>::from(*self);
56
57        let (k, R) = <C>::generate_nonce(&mut rng);
58
59        // Generate Schnorr challenge
60        let c: Challenge<C> = <C>::challenge(&R, &public, message).expect("should not return error since that happens only if one of the inputs is the identity. R is not since k is nonzero. The verifying_key is not because signing keys are not allowed to be zero.");
61
62        let z = k + (c.0 * self.scalar);
63
64        Signature { R, z }
65    }
66
67    /// Creates a SigningKey from a scalar. Returns an error if the scalar is zero.
68    pub fn from_scalar(
69        scalar: <<<C as Ciphersuite>::Group as Group>::Field as Field>::Scalar,
70    ) -> Result<Self, Error<C>> {
71        if scalar == <<C::Group as Group>::Field as Field>::zero() {
72            return Err(Error::MalformedSigningKey);
73        }
74        Ok(Self { scalar })
75    }
76
77    /// Return the underlying scalar.
78    pub fn to_scalar(self) -> <<<C as Ciphersuite>::Group as Group>::Field as Field>::Scalar {
79        self.scalar
80    }
81}
82
83impl<C> core::fmt::Debug for SigningKey<C>
84where
85    C: Ciphersuite,
86{
87    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
88        f.debug_tuple("SigningKey").field(&"<redacted>").finish()
89    }
90}
91
92impl<C> From<&SigningKey<C>> for VerifyingKey<C>
93where
94    C: Ciphersuite,
95{
96    fn from(signing_key: &SigningKey<C>) -> Self {
97        VerifyingKey::new(C::Group::generator() * signing_key.scalar)
98    }
99}
100
101impl<C> From<SigningKey<C>> for VerifyingKey<C>
102where
103    C: Ciphersuite,
104{
105    fn from(signing_key: SigningKey<C>) -> Self {
106        VerifyingKey::<C>::from(&signing_key)
107    }
108}