1use super::{oid, pkcs1v15_generate_prefix, sign, Signature, VerifyingKey};
2use crate::{dummy_rng::DummyRng, Result, RsaPrivateKey};
3use alloc::vec::Vec;
4use core::marker::PhantomData;
5use digest::Digest;
6use pkcs8::{
7 spki::{
8 der::AnyRef, AlgorithmIdentifierRef, AssociatedAlgorithmIdentifier,
9 SignatureAlgorithmIdentifier,
10 },
11 AssociatedOid, EncodePrivateKey, SecretDocument,
12};
13use rand_core::CryptoRngCore;
14use signature::{
15 hazmat::PrehashSigner, DigestSigner, Keypair, RandomizedDigestSigner, RandomizedSigner, Signer,
16};
17use zeroize::ZeroizeOnDrop;
18
19#[derive(Debug, Clone)]
23pub struct SigningKey<D>
24where
25 D: Digest,
26{
27 inner: RsaPrivateKey,
28 prefix: Vec<u8>,
29 phantom: PhantomData<D>,
30}
31
32impl<D> SigningKey<D>
33where
34 D: Digest + AssociatedOid,
35{
36 pub fn new(key: RsaPrivateKey) -> Self {
38 Self {
39 inner: key,
40 prefix: pkcs1v15_generate_prefix::<D>(),
41 phantom: Default::default(),
42 }
43 }
44
45 pub fn random<R: CryptoRngCore + ?Sized>(rng: &mut R, bit_size: usize) -> Result<Self> {
47 Ok(Self {
48 inner: RsaPrivateKey::new(rng, bit_size)?,
49 prefix: pkcs1v15_generate_prefix::<D>(),
50 phantom: Default::default(),
51 })
52 }
53
54 #[deprecated(since = "0.9.0", note = "use SigningKey::new instead")]
56 pub fn new_with_prefix(key: RsaPrivateKey) -> Self {
57 Self::new(key)
58 }
59
60 #[deprecated(since = "0.9.0", note = "use SigningKey::random instead")]
62 pub fn random_with_prefix<R: CryptoRngCore + ?Sized>(
63 rng: &mut R,
64 bit_size: usize,
65 ) -> Result<Self> {
66 Self::random(rng, bit_size)
67 }
68}
69
70impl<D> SigningKey<D>
71where
72 D: Digest,
73{
74 pub fn new_unprefixed(key: RsaPrivateKey) -> Self {
80 Self {
81 inner: key,
82 prefix: Vec::new(),
83 phantom: Default::default(),
84 }
85 }
86
87 pub fn random_unprefixed<R: CryptoRngCore + ?Sized>(
89 rng: &mut R,
90 bit_size: usize,
91 ) -> Result<Self> {
92 Ok(Self {
93 inner: RsaPrivateKey::new(rng, bit_size)?,
94 prefix: Vec::new(),
95 phantom: Default::default(),
96 })
97 }
98}
99
100impl<D> DigestSigner<D, Signature> for SigningKey<D>
105where
106 D: Digest,
107{
108 fn try_sign_digest(&self, digest: D) -> signature::Result<Signature> {
109 sign::<DummyRng>(None, &self.inner, &self.prefix, &digest.finalize())?
110 .as_slice()
111 .try_into()
112 }
113}
114
115impl<D> PrehashSigner<Signature> for SigningKey<D>
116where
117 D: Digest,
118{
119 fn sign_prehash(&self, prehash: &[u8]) -> signature::Result<Signature> {
120 sign::<DummyRng>(None, &self.inner, &self.prefix, prehash)?
121 .as_slice()
122 .try_into()
123 }
124}
125
126impl<D> RandomizedDigestSigner<D, Signature> for SigningKey<D>
127where
128 D: Digest,
129{
130 fn try_sign_digest_with_rng(
131 &self,
132 rng: &mut impl CryptoRngCore,
133 digest: D,
134 ) -> signature::Result<Signature> {
135 sign(Some(rng), &self.inner, &self.prefix, &digest.finalize())?
136 .as_slice()
137 .try_into()
138 }
139}
140
141impl<D> RandomizedSigner<Signature> for SigningKey<D>
142where
143 D: Digest,
144{
145 fn try_sign_with_rng(
146 &self,
147 rng: &mut impl CryptoRngCore,
148 msg: &[u8],
149 ) -> signature::Result<Signature> {
150 sign(Some(rng), &self.inner, &self.prefix, &D::digest(msg))?
151 .as_slice()
152 .try_into()
153 }
154}
155
156impl<D> Signer<Signature> for SigningKey<D>
157where
158 D: Digest,
159{
160 fn try_sign(&self, msg: &[u8]) -> signature::Result<Signature> {
161 sign::<DummyRng>(None, &self.inner, &self.prefix, &D::digest(msg))?
162 .as_slice()
163 .try_into()
164 }
165}
166
167impl<D> AsRef<RsaPrivateKey> for SigningKey<D>
172where
173 D: Digest,
174{
175 fn as_ref(&self) -> &RsaPrivateKey {
176 &self.inner
177 }
178}
179
180impl<D> AssociatedAlgorithmIdentifier for SigningKey<D>
181where
182 D: Digest,
183{
184 type Params = AnyRef<'static>;
185
186 const ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = pkcs1::ALGORITHM_ID;
187}
188
189impl<D> EncodePrivateKey for SigningKey<D>
190where
191 D: Digest,
192{
193 fn to_pkcs8_der(&self) -> pkcs8::Result<SecretDocument> {
194 self.inner.to_pkcs8_der()
195 }
196}
197
198impl<D> From<RsaPrivateKey> for SigningKey<D>
199where
200 D: Digest,
201{
202 fn from(key: RsaPrivateKey) -> Self {
203 Self::new_unprefixed(key)
204 }
205}
206
207impl<D> From<SigningKey<D>> for RsaPrivateKey
208where
209 D: Digest,
210{
211 fn from(key: SigningKey<D>) -> Self {
212 key.inner
213 }
214}
215
216impl<D> Keypair for SigningKey<D>
217where
218 D: Digest,
219{
220 type VerifyingKey = VerifyingKey<D>;
221
222 fn verifying_key(&self) -> Self::VerifyingKey {
223 VerifyingKey {
224 inner: self.inner.to_public_key(),
225 prefix: self.prefix.clone(),
226 phantom: Default::default(),
227 }
228 }
229}
230
231impl<D> SignatureAlgorithmIdentifier for SigningKey<D>
232where
233 D: Digest + oid::RsaSignatureAssociatedOid,
234{
235 type Params = AnyRef<'static>;
236
237 const SIGNATURE_ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> =
238 AlgorithmIdentifierRef {
239 oid: D::OID,
240 parameters: Some(AnyRef::NULL),
241 };
242}
243
244impl<D> TryFrom<pkcs8::PrivateKeyInfo<'_>> for SigningKey<D>
245where
246 D: Digest + AssociatedOid,
247{
248 type Error = pkcs8::Error;
249
250 fn try_from(private_key_info: pkcs8::PrivateKeyInfo<'_>) -> pkcs8::Result<Self> {
251 RsaPrivateKey::try_from(private_key_info).map(Self::new)
252 }
253}
254
255impl<D> ZeroizeOnDrop for SigningKey<D> where D: Digest {}