1use crate::{
6 hazmat::{DigestPrimitive, FromDigest, SignPrimitive},
7 rfc6979, Error, Result, Signature, SignatureSize,
8};
9use core::{
10 convert::TryFrom,
11 fmt::{self, Debug},
12};
13use elliptic_curve_flow::{
14 generic_array::ArrayLength,
15 group::ff::PrimeField,
16 ops::Invert,
17 subtle::{Choice, ConstantTimeEq},
18 zeroize::Zeroize,
19 FieldBytes, FieldSize, NonZeroScalar, PrimeCurve, ProjectiveArithmetic, Scalar, SecretKey,
20};
21use signature_flow::{
22 digest::{BlockInput, Digest, FixedOutput, Reset, Update},
23 rand_core::{CryptoRng, RngCore},
24 DigestSigner, RandomizedDigestSigner, RandomizedSigner, Signer,
25};
26
27#[cfg(feature = "verify")]
28use {crate::verify::VerifyingKey, elliptic_curve_flow::PublicKey};
29
30#[cfg(feature = "pkcs8")]
31use crate::elliptic_curve_flow::{
32 consts::U1,
33 ops::Add,
34 pkcs8::{self, FromPrivateKey},
35 sec1::{FromEncodedPoint, ToEncodedPoint, UncompressedPointSize, UntaggedPointSize},
36 AffinePoint, AlgorithmParameters,
37};
38
39#[cfg(feature = "pem")]
40use core::str::FromStr;
41
42#[derive(Clone)]
47#[cfg_attr(docsrs, doc(cfg(feature = "sign")))]
48pub struct SigningKey<C>
49where
50 C: PrimeCurve + ProjectiveArithmetic,
51 Scalar<C>: FromDigest<C> + Invert<Output = Scalar<C>> + SignPrimitive<C>,
52 SignatureSize<C>: ArrayLength<u8>,
53{
54 inner: NonZeroScalar<C>,
55}
56
57impl<C> SigningKey<C>
58where
59 C: PrimeCurve + ProjectiveArithmetic,
60 Scalar<C>: FromDigest<C> + Invert<Output = Scalar<C>> + SignPrimitive<C>,
61 SignatureSize<C>: ArrayLength<u8>,
62{
63 pub fn random(rng: impl CryptoRng + RngCore) -> Self {
65 Self {
66 inner: NonZeroScalar::random(rng),
67 }
68 }
69
70 pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
72 let inner = SecretKey::from_be_bytes(bytes)
73 .map(|sk| sk.to_nonzero_scalar())
74 .map_err(|_| Error::new())?;
75
76 Ok(Self { inner })
77 }
78
79 #[cfg(feature = "verify")]
81 #[cfg_attr(docsrs, doc(cfg(feature = "verify")))]
82 pub fn verifying_key(&self) -> VerifyingKey<C> {
83 VerifyingKey {
84 inner: PublicKey::from_secret_scalar(&self.inner),
85 }
86 }
87
88 pub fn to_bytes(&self) -> FieldBytes<C> {
90 self.inner.to_repr()
91 }
92}
93
94impl<C> ConstantTimeEq for SigningKey<C>
95where
96 C: PrimeCurve + ProjectiveArithmetic,
97 Scalar<C>: FromDigest<C> + Invert<Output = Scalar<C>> + SignPrimitive<C>,
98 SignatureSize<C>: ArrayLength<u8>,
99{
100 fn ct_eq(&self, other: &Self) -> Choice {
101 self.inner.ct_eq(&other.inner)
102 }
103}
104
105impl<C> Debug for SigningKey<C>
106where
107 C: PrimeCurve + ProjectiveArithmetic,
108 Scalar<C>: FromDigest<C> + Invert<Output = Scalar<C>> + SignPrimitive<C>,
109 SignatureSize<C>: ArrayLength<u8>,
110{
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 f.debug_tuple("SigningKey").field(&"...").finish()
114 }
115}
116
117impl<C> Drop for SigningKey<C>
118where
119 C: PrimeCurve + ProjectiveArithmetic,
120 Scalar<C>: FromDigest<C> + Invert<Output = Scalar<C>> + SignPrimitive<C>,
121 SignatureSize<C>: ArrayLength<u8>,
122{
123 fn drop(&mut self) {
124 self.inner.zeroize();
125 }
126}
127
128impl<C> Eq for SigningKey<C>
129where
130 C: PrimeCurve + ProjectiveArithmetic,
131 Scalar<C>: FromDigest<C> + Invert<Output = Scalar<C>> + SignPrimitive<C>,
132 SignatureSize<C>: ArrayLength<u8>,
133{
134}
135
136impl<C> PartialEq for SigningKey<C>
137where
138 C: PrimeCurve + ProjectiveArithmetic,
139 Scalar<C>: FromDigest<C> + Invert<Output = Scalar<C>> + SignPrimitive<C>,
140 SignatureSize<C>: ArrayLength<u8>,
141{
142 fn eq(&self, other: &SigningKey<C>) -> bool {
143 self.ct_eq(other).into()
144 }
145}
146
147impl<C> From<SecretKey<C>> for SigningKey<C>
148where
149 C: PrimeCurve + ProjectiveArithmetic,
150 Scalar<C>: FromDigest<C> + Invert<Output = Scalar<C>> + SignPrimitive<C>,
151 SignatureSize<C>: ArrayLength<u8>,
152{
153 fn from(secret_key: SecretKey<C>) -> Self {
154 Self::from(&secret_key)
155 }
156}
157
158impl<C> From<&SecretKey<C>> for SigningKey<C>
159where
160 C: PrimeCurve + ProjectiveArithmetic,
161 Scalar<C>: FromDigest<C> + Invert<Output = Scalar<C>> + SignPrimitive<C>,
162 SignatureSize<C>: ArrayLength<u8>,
163{
164 fn from(secret_key: &SecretKey<C>) -> Self {
165 Self {
166 inner: secret_key.to_nonzero_scalar(),
167 }
168 }
169}
170
171impl<C, D> DigestSigner<D, Signature<C>> for SigningKey<C>
172where
173 C: PrimeCurve + ProjectiveArithmetic,
174 D: FixedOutput<OutputSize = FieldSize<C>> + BlockInput + Clone + Default + Reset + Update,
175 Scalar<C>: FromDigest<C> + Invert<Output = Scalar<C>> + SignPrimitive<C>,
176 SignatureSize<C>: ArrayLength<u8>,
177{
178 fn try_sign_digest(&self, digest: D) -> Result<Signature<C>> {
182 let k = rfc6979::generate_k(&self.inner, digest.clone(), &[]);
183 let msg_scalar = Scalar::<C>::from_digest(digest);
184 self.inner.try_sign_prehashed(&**k, &msg_scalar)
185 }
186}
187
188impl<C> Signer<Signature<C>> for SigningKey<C>
189where
190 Self: DigestSigner<C::Digest, Signature<C>>,
191 C: PrimeCurve + ProjectiveArithmetic + DigestPrimitive,
192 Scalar<C>: FromDigest<C> + Invert<Output = Scalar<C>> + SignPrimitive<C>,
193 SignatureSize<C>: ArrayLength<u8>,
194{
195 fn try_sign(&self, msg: &[u8]) -> Result<Signature<C>> {
196 self.try_sign_digest(C::Digest::new().chain(msg))
197 }
198}
199
200impl<C, D> RandomizedDigestSigner<D, Signature<C>> for SigningKey<C>
201where
202 C: PrimeCurve + ProjectiveArithmetic,
203 D: FixedOutput<OutputSize = FieldSize<C>> + BlockInput + Clone + Default + Reset + Update,
204 Scalar<C>: FromDigest<C> + Invert<Output = Scalar<C>> + SignPrimitive<C>,
205 SignatureSize<C>: ArrayLength<u8>,
206{
207 fn try_sign_digest_with_rng(
211 &self,
212 mut rng: impl CryptoRng + RngCore,
213 digest: D,
214 ) -> Result<Signature<C>> {
215 let mut added_entropy = FieldBytes::<C>::default();
216 rng.fill_bytes(&mut added_entropy);
217
218 let k = rfc6979::generate_k(&self.inner, digest.clone(), &added_entropy);
219 let msg_scalar = Scalar::<C>::from_digest(digest);
220 self.inner.try_sign_prehashed(&**k, &msg_scalar)
221 }
222}
223
224impl<C> RandomizedSigner<Signature<C>> for SigningKey<C>
225where
226 Self: RandomizedDigestSigner<C::Digest, Signature<C>>,
227 C: PrimeCurve + ProjectiveArithmetic + DigestPrimitive,
228 Scalar<C>: FromDigest<C> + Invert<Output = Scalar<C>> + SignPrimitive<C>,
229 SignatureSize<C>: ArrayLength<u8>,
230{
231 fn try_sign_with_rng(&self, rng: impl CryptoRng + RngCore, msg: &[u8]) -> Result<Signature<C>> {
232 self.try_sign_digest_with_rng(rng, C::Digest::new().chain(msg))
233 }
234}
235
236impl<C> From<NonZeroScalar<C>> for SigningKey<C>
237where
238 C: PrimeCurve + ProjectiveArithmetic,
239 Scalar<C>: FromDigest<C> + Invert<Output = Scalar<C>> + SignPrimitive<C>,
240 SignatureSize<C>: ArrayLength<u8>,
241{
242 fn from(secret_scalar: NonZeroScalar<C>) -> Self {
243 Self {
244 inner: secret_scalar,
245 }
246 }
247}
248
249impl<C> TryFrom<&[u8]> for SigningKey<C>
250where
251 C: PrimeCurve + ProjectiveArithmetic,
252 Scalar<C>: FromDigest<C> + Invert<Output = Scalar<C>> + SignPrimitive<C>,
253 SignatureSize<C>: ArrayLength<u8>,
254{
255 type Error = Error;
256
257 fn try_from(bytes: &[u8]) -> Result<Self> {
258 Self::from_bytes(bytes)
259 }
260}
261
262#[cfg(feature = "verify")]
263impl<C> From<&SigningKey<C>> for VerifyingKey<C>
264where
265 C: PrimeCurve + ProjectiveArithmetic,
266
267 Scalar<C>: FromDigest<C> + Invert<Output = Scalar<C>> + SignPrimitive<C>,
268 SignatureSize<C>: ArrayLength<u8>,
269{
270 fn from(signing_key: &SigningKey<C>) -> VerifyingKey<C> {
271 signing_key.verifying_key()
272 }
273}
274
275#[cfg(feature = "pkcs8")]
276#[cfg_attr(docsrs, doc(cfg(feature = "pkcs8")))]
277impl<C> FromPrivateKey for SigningKey<C>
278where
279 C: PrimeCurve + AlgorithmParameters + ProjectiveArithmetic,
280 AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
281 Scalar<C>: FromDigest<C> + Invert<Output = Scalar<C>> + SignPrimitive<C>,
282 SignatureSize<C>: ArrayLength<u8>,
283 UntaggedPointSize<C>: Add<U1> + ArrayLength<u8>,
284 UncompressedPointSize<C>: ArrayLength<u8>,
285{
286 fn from_pkcs8_private_key_info(
287 private_key_info: pkcs8::PrivateKeyInfo<'_>,
288 ) -> pkcs8::Result<Self> {
289 SecretKey::from_pkcs8_private_key_info(private_key_info).map(Into::into)
290 }
291}
292
293#[cfg(feature = "pem")]
294#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
295impl<C> FromStr for SigningKey<C>
296where
297 C: PrimeCurve + AlgorithmParameters + ProjectiveArithmetic,
298 AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
299 Scalar<C>: FromDigest<C> + Invert<Output = Scalar<C>> + SignPrimitive<C>,
300 SignatureSize<C>: ArrayLength<u8>,
301 UntaggedPointSize<C>: Add<U1> + ArrayLength<u8>,
302 UncompressedPointSize<C>: ArrayLength<u8>,
303{
304 type Err = Error;
305
306 fn from_str(s: &str) -> Result<Self> {
307 Self::from_pkcs8_pem(s).map_err(|_| Error::new())
308 }
309}