rsa/pss/
blinded_signing_key.rs1use super::{get_pss_signature_algo_id, sign_digest, Signature, VerifyingKey};
2use crate::{Result, RsaPrivateKey};
3use const_oid::AssociatedOid;
4use core::marker::PhantomData;
5use digest::{Digest, FixedOutputReset};
6use pkcs8::{
7 spki::{
8 der::AnyRef, AlgorithmIdentifierOwned, AlgorithmIdentifierRef,
9 AssociatedAlgorithmIdentifier, DynSignatureAlgorithmIdentifier,
10 },
11 EncodePrivateKey, SecretDocument,
12};
13use rand_core::CryptoRngCore;
14use signature::{
15 hazmat::RandomizedPrehashSigner, Keypair, RandomizedDigestSigner, RandomizedSigner,
16};
17use zeroize::ZeroizeOnDrop;
18
19#[derive(Debug, Clone)]
22pub struct BlindedSigningKey<D>
23where
24 D: Digest,
25{
26 inner: RsaPrivateKey,
27 salt_len: usize,
28 phantom: PhantomData<D>,
29}
30
31impl<D> BlindedSigningKey<D>
32where
33 D: Digest,
34{
35 pub fn new(key: RsaPrivateKey) -> Self {
39 Self::new_with_salt_len(key, <D as Digest>::output_size())
40 }
41
42 pub fn new_with_salt_len(key: RsaPrivateKey, salt_len: usize) -> Self {
45 Self {
46 inner: key,
47 salt_len,
48 phantom: Default::default(),
49 }
50 }
51
52 pub fn random<R: CryptoRngCore + ?Sized>(rng: &mut R, bit_size: usize) -> Result<Self> {
56 Self::random_with_salt_len(rng, bit_size, <D as Digest>::output_size())
57 }
58
59 pub fn random_with_salt_len<R: CryptoRngCore + ?Sized>(
62 rng: &mut R,
63 bit_size: usize,
64 salt_len: usize,
65 ) -> Result<Self> {
66 Ok(Self {
67 inner: RsaPrivateKey::new(rng, bit_size)?,
68 salt_len,
69 phantom: Default::default(),
70 })
71 }
72
73 pub fn salt_len(&self) -> usize {
75 self.salt_len
76 }
77}
78
79impl<D> RandomizedSigner<Signature> for BlindedSigningKey<D>
84where
85 D: Digest + FixedOutputReset,
86{
87 fn try_sign_with_rng(
88 &self,
89 rng: &mut impl CryptoRngCore,
90 msg: &[u8],
91 ) -> signature::Result<Signature> {
92 sign_digest::<_, D>(rng, true, &self.inner, &D::digest(msg), self.salt_len)?
93 .as_slice()
94 .try_into()
95 }
96}
97
98impl<D> RandomizedDigestSigner<D, Signature> for BlindedSigningKey<D>
99where
100 D: Digest + FixedOutputReset,
101{
102 fn try_sign_digest_with_rng(
103 &self,
104 rng: &mut impl CryptoRngCore,
105 digest: D,
106 ) -> signature::Result<Signature> {
107 sign_digest::<_, D>(rng, true, &self.inner, &digest.finalize(), self.salt_len)?
108 .as_slice()
109 .try_into()
110 }
111}
112
113impl<D> RandomizedPrehashSigner<Signature> for BlindedSigningKey<D>
114where
115 D: Digest + FixedOutputReset,
116{
117 fn sign_prehash_with_rng(
118 &self,
119 rng: &mut impl CryptoRngCore,
120 prehash: &[u8],
121 ) -> signature::Result<Signature> {
122 sign_digest::<_, D>(rng, true, &self.inner, prehash, self.salt_len)?
123 .as_slice()
124 .try_into()
125 }
126}
127
128impl<D> AsRef<RsaPrivateKey> for BlindedSigningKey<D>
133where
134 D: Digest,
135{
136 fn as_ref(&self) -> &RsaPrivateKey {
137 &self.inner
138 }
139}
140
141impl<D> AssociatedAlgorithmIdentifier for BlindedSigningKey<D>
142where
143 D: Digest,
144{
145 type Params = AnyRef<'static>;
146
147 const ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = pkcs1::ALGORITHM_ID;
148}
149
150impl<D> DynSignatureAlgorithmIdentifier for BlindedSigningKey<D>
151where
152 D: Digest + AssociatedOid,
153{
154 fn signature_algorithm_identifier(&self) -> pkcs8::spki::Result<AlgorithmIdentifierOwned> {
155 get_pss_signature_algo_id::<D>(self.salt_len as u8)
156 }
157}
158
159impl<D> EncodePrivateKey for BlindedSigningKey<D>
160where
161 D: Digest,
162{
163 fn to_pkcs8_der(&self) -> pkcs8::Result<SecretDocument> {
164 self.inner.to_pkcs8_der()
165 }
166}
167
168impl<D> From<RsaPrivateKey> for BlindedSigningKey<D>
169where
170 D: Digest,
171{
172 fn from(key: RsaPrivateKey) -> Self {
173 Self::new(key)
174 }
175}
176
177impl<D> From<BlindedSigningKey<D>> for RsaPrivateKey
178where
179 D: Digest,
180{
181 fn from(key: BlindedSigningKey<D>) -> Self {
182 key.inner
183 }
184}
185
186impl<D> Keypair for BlindedSigningKey<D>
187where
188 D: Digest,
189{
190 type VerifyingKey = VerifyingKey<D>;
191 fn verifying_key(&self) -> Self::VerifyingKey {
192 VerifyingKey {
193 inner: self.inner.to_public_key(),
194 salt_len: self.salt_len,
195 phantom: Default::default(),
196 }
197 }
198}
199
200impl<D> ZeroizeOnDrop for BlindedSigningKey<D> where D: Digest {}