1use std::ops::Deref;
2
3use digest::{const_oid::AssociatedOid, Digest};
4use md5::Md5;
5use num_bigint::traits::ModInverse;
6use num_bigint::BigUint;
7use rand::{CryptoRng, Rng};
8use ripemd::Ripemd160;
9use rsa::pkcs1v15::{Pkcs1v15Encrypt, Signature as RsaSignature, SigningKey, VerifyingKey};
10use rsa::{
11 traits::{PrivateKeyParts, PublicKeyParts},
12 RsaPrivateKey, RsaPublicKey,
13};
14use sha1_checked::Sha1; use sha2::{Sha224, Sha256, Sha384, Sha512};
16use sha3::{Sha3_256, Sha3_512};
17use signature::hazmat::{PrehashSigner, PrehashVerifier};
18use signature::SignatureEncoding;
19use zeroize::ZeroizeOnDrop;
20
21use crate::crypto::{hash::HashAlgorithm, Decryptor, KeyParams, Signer};
22use crate::errors::Result;
23use crate::types::{Mpi, PkeskBytes, PlainSecretParams, PublicParams};
24
25const MAX_KEY_SIZE: usize = 16384;
26
27#[derive(derive_more::Debug, ZeroizeOnDrop)]
29pub struct PrivateKey(#[debug("..")] RsaPrivateKey);
30
31impl Deref for PrivateKey {
32 type Target = RsaPrivateKey;
33
34 fn deref(&self) -> &Self::Target {
35 &self.0
36 }
37}
38
39impl KeyParams for PrivateKey {
40 type KeyParams = ();
41
42 #[allow(clippy::unused_unit)]
43 fn key_params(&self) -> Self::KeyParams {
44 ()
45 }
46}
47
48impl Decryptor for PrivateKey {
49 type EncryptionFields<'a> = &'a Mpi;
50
51 fn decrypt(&self, mpi: Self::EncryptionFields<'_>) -> Result<Vec<u8>> {
53 let m = self.0.decrypt(Pkcs1v15Encrypt, mpi.as_bytes())?;
54
55 Ok(m)
56 }
57}
58
59impl Signer for PrivateKey {
60 fn sign(
62 &self,
63 hash: HashAlgorithm,
64 digest: &[u8],
65 pub_params: &PublicParams,
66 ) -> Result<Vec<Vec<u8>>> {
67 ensure!(
68 matches!(pub_params, PublicParams::RSA { .. }),
69 "invalid public params"
70 );
71
72 let sig = match hash {
73 HashAlgorithm::None => return Err(format_err!("none")),
74 HashAlgorithm::MD5 => sign_int::<Md5>(self.0.clone(), digest),
75 HashAlgorithm::RIPEMD160 => sign_int::<Ripemd160>(self.0.clone(), digest),
76 HashAlgorithm::SHA1 => sign_int::<Sha1>(self.0.clone(), digest),
77 HashAlgorithm::SHA2_224 => sign_int::<Sha224>(self.0.clone(), digest),
78 HashAlgorithm::SHA2_256 => sign_int::<Sha256>(self.0.clone(), digest),
79 HashAlgorithm::SHA2_384 => sign_int::<Sha384>(self.0.clone(), digest),
80 HashAlgorithm::SHA2_512 => sign_int::<Sha512>(self.0.clone(), digest),
81 HashAlgorithm::SHA3_256 => sign_int::<Sha3_256>(self.0.clone(), digest),
82 HashAlgorithm::SHA3_512 => sign_int::<Sha3_512>(self.0.clone(), digest),
83 HashAlgorithm::Private10 => unsupported_err!("Private10 should not be used"),
84 HashAlgorithm::Other(o) => unsupported_err!("Hash algorithm {} is unsupported", o),
85 }?;
86
87 Ok(vec![sig.to_vec()])
88 }
89}
90
91impl From<RsaPrivateKey> for PrivateKey {
92 fn from(key: RsaPrivateKey) -> Self {
93 Self(key)
94 }
95}
96
97pub fn encrypt<R: CryptoRng + Rng>(
99 mut rng: R,
100 n: &[u8],
101 e: &[u8],
102 plaintext: &[u8],
103) -> Result<PkeskBytes> {
104 let key = RsaPublicKey::new_with_max_size(
105 BigUint::from_bytes_be(n),
106 BigUint::from_bytes_be(e),
107 MAX_KEY_SIZE,
108 )?;
109 let data = key.encrypt(&mut rng, Pkcs1v15Encrypt, plaintext)?;
110
111 Ok(PkeskBytes::Rsa {
112 mpi: Mpi::from_slice(&data[..]),
113 })
114}
115
116pub fn generate_key<R: Rng + CryptoRng>(
118 mut rng: R,
119 bit_size: usize,
120) -> Result<(PublicParams, PlainSecretParams)> {
121 let key = RsaPrivateKey::new(&mut rng, bit_size)?;
122
123 let p = &key.primes()[0];
124 let q = &key.primes()[1];
125 let u = p
126 .clone()
127 .mod_inverse(q)
128 .expect("invalid prime")
129 .to_biguint()
130 .expect("invalid prime");
131
132 Ok((
133 PublicParams::RSA {
134 n: key.n().into(),
135 e: key.e().into(),
136 },
137 PlainSecretParams::RSA {
138 d: key.d().into(),
139 p: p.into(),
140 q: q.into(),
141 u: u.into(),
142 },
143 ))
144}
145
146fn verify_int<D>(key: RsaPublicKey, hashed: &[u8], signature: &RsaSignature) -> Result<()>
147where
148 D: Digest + AssociatedOid,
149{
150 VerifyingKey::<D>::new(key)
151 .verify_prehash(hashed, signature)
152 .map_err(Into::into)
153}
154
155fn sign_int<D>(key: RsaPrivateKey, digest: &[u8]) -> Result<RsaSignature>
156where
157 D: Digest + AssociatedOid,
158{
159 SigningKey::<D>::new(key)
160 .sign_prehash(digest)
161 .map_err(Into::into)
162}
163
164pub fn verify(
166 n: &[u8],
167 e: &[u8],
168 hash: HashAlgorithm,
169 hashed: &[u8],
170 signature: &[u8],
171) -> Result<()> {
172 let key = RsaPublicKey::new_with_max_size(
173 BigUint::from_bytes_be(n),
174 BigUint::from_bytes_be(e),
175 MAX_KEY_SIZE,
176 )?;
177
178 let signature = if signature.len() < key.size() {
179 let mut signature_padded = vec![0u8; key.size()];
182 let diff = key.size() - signature.len();
183 signature_padded[diff..].copy_from_slice(signature);
184 RsaSignature::try_from(&signature_padded[..])?
185 } else {
186 RsaSignature::try_from(signature)?
187 };
188
189 match hash {
190 HashAlgorithm::None => Err(format_err!("none")),
191 HashAlgorithm::MD5 => verify_int::<Md5>(key, hashed, &signature),
192 HashAlgorithm::RIPEMD160 => verify_int::<Ripemd160>(key, hashed, &signature),
193 HashAlgorithm::SHA1 => verify_int::<Sha1>(key, hashed, &signature),
194 HashAlgorithm::SHA2_224 => verify_int::<Sha224>(key, hashed, &signature),
195 HashAlgorithm::SHA2_256 => verify_int::<Sha256>(key, hashed, &signature),
196 HashAlgorithm::SHA2_384 => verify_int::<Sha384>(key, hashed, &signature),
197 HashAlgorithm::SHA2_512 => verify_int::<Sha512>(key, hashed, &signature),
198 HashAlgorithm::SHA3_256 => verify_int::<Sha3_256>(key, hashed, &signature),
199 HashAlgorithm::SHA3_512 => verify_int::<Sha3_512>(key, hashed, &signature),
200 HashAlgorithm::Private10 => unsupported_err!("Private10 should not be used"),
201 HashAlgorithm::Other(o) => unsupported_err!("Hash algorithm {} is unsupported", o),
202 }
203 .map_err(Into::into)
204}