1use std::fmt;
7
8use der::Decode;
9use der::oid::ObjectIdentifier;
10use rsa::pkcs1::DecodeRsaPrivateKey;
11use rsa::pkcs8::{DecodePrivateKey, DecodePublicKey, EncodePublicKey};
12use rsa::traits::PublicKeyParts;
13use rsa::{RsaPrivateKey, RsaPublicKey, pkcs1v15, pss};
14use sha1::Sha1;
15use sha2::{Digest, Sha256, Sha384, Sha512};
16use signature::hazmat::{PrehashSigner, PrehashVerifier};
17use signature::{SignatureEncoding, Signer, Verifier};
18use zeroize::Zeroizing;
19
20use super::{DigestAlgorithm, KeyError};
21use crate::digest::ContentDigest;
22
23const RSA_ENCRYPTION: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.1");
24const EC_PUBLIC_KEY: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.10045.2.1");
25const SECP256R1: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.10045.3.1.7");
26const SECP384R1: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.132.0.34");
27
28pub const MIN_RSA_SIGNING_BITS: u32 = 2048;
30
31#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
33pub enum KeyKind {
34 Rsa { bits: u32 },
35 EcP256,
36 EcP384,
37}
38
39impl fmt::Display for KeyKind {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 match self {
42 Self::Rsa { bits } => write!(f, "{bits}-bit RSA"),
43 Self::EcP256 => f.write_str("P-256 EC"),
44 Self::EcP384 => f.write_str("P-384 EC"),
45 }
46 }
47}
48
49#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
51#[non_exhaustive]
52pub enum SignatureAlgorithm {
53 RsaPssSha256,
54 RsaPssSha512,
55 RsaPkcs1Sha256,
56 RsaPkcs1Sha512,
57 EcdsaSha256,
58 EcdsaSha512,
59 DsaSha256,
60 VerityRsaPkcs1Sha256,
61 VerityEcdsaSha256,
62 VerityDsaSha256,
63}
64
65impl SignatureAlgorithm {
66 const ALL: [(Self, u32); 10] = [
67 (Self::RsaPssSha256, 0x0101),
68 (Self::RsaPssSha512, 0x0102),
69 (Self::RsaPkcs1Sha256, 0x0103),
70 (Self::RsaPkcs1Sha512, 0x0104),
71 (Self::EcdsaSha256, 0x0201),
72 (Self::EcdsaSha512, 0x0202),
73 (Self::DsaSha256, 0x0301),
74 (Self::VerityRsaPkcs1Sha256, 0x0421),
75 (Self::VerityEcdsaSha256, 0x0423),
76 (Self::VerityDsaSha256, 0x0425),
77 ];
78
79 pub fn id(self) -> u32 {
81 Self::ALL.iter().find(|(a, _)| *a == self).map(|(_, id)| *id).expect("every algorithm has an ID")
82 }
83
84 pub fn from_id(id: u32) -> Option<Self> {
85 Self::ALL.iter().find(|(_, i)| *i == id).map(|(a, _)| *a)
86 }
87
88 pub(crate) fn content_digest(self) -> Option<ContentDigest> {
91 match self {
92 Self::RsaPssSha256 | Self::RsaPkcs1Sha256 | Self::EcdsaSha256 | Self::DsaSha256 => {
93 Some(ContentDigest::ChunkedSha256)
94 }
95 Self::RsaPssSha512 | Self::RsaPkcs1Sha512 | Self::EcdsaSha512 => Some(ContentDigest::ChunkedSha512),
96 Self::VerityRsaPkcs1Sha256 | Self::VerityEcdsaSha256 | Self::VerityDsaSha256 => None,
97 }
98 }
99
100 pub(crate) fn strength(self) -> u8 {
103 match self {
104 Self::RsaPssSha512 | Self::RsaPkcs1Sha512 | Self::EcdsaSha512 => 3,
105 Self::VerityRsaPkcs1Sha256 | Self::VerityEcdsaSha256 | Self::VerityDsaSha256 => 2,
106 Self::RsaPssSha256 | Self::RsaPkcs1Sha256 | Self::EcdsaSha256 | Self::DsaSha256 => 1,
107 }
108 }
109
110 pub fn is_verifiable(self) -> bool {
112 !matches!(self, Self::DsaSha256 | Self::VerityRsaPkcs1Sha256 | Self::VerityEcdsaSha256 | Self::VerityDsaSha256)
113 }
114}
115
116impl fmt::Display for SignatureAlgorithm {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 write!(f, "{self:?} ({:#06x})", self.id())
119 }
120}
121
122#[derive(Clone)]
123enum Private {
124 Rsa(RsaPrivateKey),
125 P256(p256::ecdsa::SigningKey),
126 P384(p384::ecdsa::SigningKey),
127}
128
129#[derive(Clone)]
131pub struct PrivateKey(Private);
132
133impl fmt::Debug for PrivateKey {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 write!(f, "PrivateKey({})", self.kind())
136 }
137}
138
139impl PrivateKey {
140 pub fn from_pkcs8_der(der: &[u8]) -> Result<Self, KeyError> {
142 let info = pkcs8::PrivateKeyInfoRef::from_der(der).map_err(pkcs8::Error::from)?;
143 let algorithm = info.algorithm.oid;
144 let private = match algorithm {
145 RSA_ENCRYPTION => Private::Rsa(RsaPrivateKey::from_pkcs8_der(der)?),
146 EC_PUBLIC_KEY => match info.algorithm.parameters_oid().map_err(pkcs8::Error::from)? {
147 SECP256R1 => Private::P256(p256::ecdsa::SigningKey::from_pkcs8_der(der)?),
148 SECP384R1 => Private::P384(p384::ecdsa::SigningKey::from_pkcs8_der(der)?),
149 curve => return Err(KeyError::UnsupportedCurve { oid: curve }),
150 },
151 oid => return Err(KeyError::UnsupportedAlgorithm { oid }),
152 };
153 Self::checked(private)
154 }
155
156 pub fn from_pkcs1_der(der: &[u8]) -> Result<Self, KeyError> {
158 Self::checked(Private::Rsa(RsaPrivateKey::from_pkcs1_der(der)?))
159 }
160
161 pub fn from_sec1_der(der: &[u8]) -> Result<Self, KeyError> {
163 if let Ok(key) = p256::SecretKey::from_sec1_der(der) {
164 return Ok(Self(Private::P256(key.into())));
165 }
166 match p384::SecretKey::from_sec1_der(der) {
167 Ok(key) => Ok(Self(Private::P384(key.into()))),
168 Err(_) => Err(KeyError::InvalidEcKey),
169 }
170 }
171
172 fn checked(private: Private) -> Result<Self, KeyError> {
173 if let Private::Rsa(key) = &private {
174 key.validate()?;
175 let bits = key.n().bits_vartime();
176 if bits < MIN_RSA_SIGNING_BITS {
177 return Err(KeyError::RsaKeyTooSmall { bits, min: MIN_RSA_SIGNING_BITS });
178 }
179 }
180 Ok(Self(private))
181 }
182
183 pub fn kind(&self) -> KeyKind {
184 self.public_key().kind()
185 }
186
187 pub fn to_pkcs8_der(&self) -> Result<Zeroizing<Vec<u8>>, KeyError> {
190 use pkcs8::EncodePrivateKey;
191 let document = match &self.0 {
192 Private::Rsa(key) => key.to_pkcs8_der()?,
193 Private::P256(key) => key.to_pkcs8_der()?,
194 Private::P384(key) => key.to_pkcs8_der()?,
195 };
196 Ok(Zeroizing::new(document.as_bytes().to_vec()))
197 }
198
199 pub fn public_key(&self) -> PublicKey {
200 PublicKey(match &self.0 {
201 Private::Rsa(key) => Public::Rsa(key.to_public_key()),
202 Private::P256(key) => Public::P256(*key.verifying_key()),
203 Private::P384(key) => Public::P384(*key.verifying_key()),
204 })
205 }
206
207 pub fn signature_algorithm(&self) -> SignatureAlgorithm {
210 match self.kind() {
211 KeyKind::Rsa { bits } if bits <= 3072 => SignatureAlgorithm::RsaPkcs1Sha256,
212 KeyKind::Rsa { .. } => SignatureAlgorithm::RsaPkcs1Sha512,
213 KeyKind::EcP256 => SignatureAlgorithm::EcdsaSha256,
214 KeyKind::EcP384 => SignatureAlgorithm::EcdsaSha512,
215 }
216 }
217
218 pub(crate) fn sign(&self, algorithm: SignatureAlgorithm, message: &[u8]) -> Result<Vec<u8>, KeyError> {
220 let mismatch = || KeyError::AlgorithmMismatch { algorithm, key: self.kind() };
221 match (&self.0, algorithm) {
222 (Private::Rsa(key), SignatureAlgorithm::RsaPkcs1Sha256) => rsa_pkcs1::<Sha256>(key, message),
223 (Private::Rsa(key), SignatureAlgorithm::RsaPkcs1Sha512) => rsa_pkcs1::<Sha512>(key, message),
224 (Private::P256(key), SignatureAlgorithm::EcdsaSha256) => sign_p256::<Sha256>(key, message),
225 (Private::P256(key), SignatureAlgorithm::EcdsaSha512) => sign_p256::<Sha512>(key, message),
226 (Private::P384(key), SignatureAlgorithm::EcdsaSha256) => sign_p384::<Sha256>(key, message),
227 (Private::P384(key), SignatureAlgorithm::EcdsaSha512) => sign_p384::<Sha512>(key, message),
228 _ => Err(mismatch()),
229 }
230 }
231
232 pub(crate) fn sign_jar(&self, digest: DigestAlgorithm, message: &[u8]) -> Result<Vec<u8>, KeyError> {
234 match digest {
235 DigestAlgorithm::Sha1 => self.sign_jar_with::<Sha1>(message),
236 DigestAlgorithm::Sha256 => self.sign_jar_with::<Sha256>(message),
237 DigestAlgorithm::Sha384 => self.sign_jar_with::<Sha384>(message),
238 DigestAlgorithm::Sha512 => self.sign_jar_with::<Sha512>(message),
239 }
240 }
241
242 fn sign_jar_with<D: Digest + der::oid::AssociatedOid>(&self, message: &[u8]) -> Result<Vec<u8>, KeyError> {
243 match &self.0 {
244 Private::Rsa(key) => rsa_pkcs1::<D>(key, message),
245 Private::P256(key) => sign_p256::<D>(key, message),
246 Private::P384(key) => sign_p384::<D>(key, message),
247 }
248 }
249}
250
251fn rsa_pkcs1<D>(key: &RsaPrivateKey, message: &[u8]) -> Result<Vec<u8>, KeyError>
252where
253 D: Digest + der::oid::AssociatedOid,
254{
255 let signer = pkcs1v15::SigningKey::<D>::new(key.clone());
256 Ok(signer.try_sign(message).map_err(KeyError::Signing)?.to_vec())
257}
258
259macro_rules! ecdsa_curve {
263 ($curve:ident, $sign:ident, $verify:ident) => {
264 fn $sign<D: Digest>(key: &$curve::ecdsa::SigningKey, message: &[u8]) -> Result<Vec<u8>, KeyError> {
265 let signature: $curve::ecdsa::Signature =
266 key.sign_prehash(&D::digest(message)).map_err(KeyError::Signing)?;
267 Ok(signature.to_der().to_vec())
268 }
269
270 fn $verify<D: Digest>(
271 key: &$curve::ecdsa::VerifyingKey,
272 message: &[u8],
273 signature: &[u8],
274 ) -> Result<(), SignatureError> {
275 let signature = $curve::ecdsa::Signature::from_der(signature).map_err(|_| SignatureError::Malformed)?;
276 key.verify_prehash(&D::digest(message), &signature).map_err(|_| SignatureError::Invalid)
277 }
278 };
279}
280
281ecdsa_curve!(p256, sign_p256, verify_p256);
282ecdsa_curve!(p384, sign_p384, verify_p384);
283
284#[derive(Clone, Debug, Eq, PartialEq)]
285enum Public {
286 Rsa(RsaPublicKey),
287 P256(p256::ecdsa::VerifyingKey),
288 P384(p384::ecdsa::VerifyingKey),
289}
290
291#[derive(Clone, Debug, Eq, PartialEq)]
293pub struct PublicKey(Public);
294
295#[derive(Clone, Copy, Debug, Eq, PartialEq, thiserror::Error)]
297#[non_exhaustive]
298pub enum SignatureError {
299 #[error("{algorithm} cannot be verified with a {key} key")]
300 AlgorithmMismatch { algorithm: SignatureAlgorithm, key: KeyKind },
301 #[error("{algorithm} is not supported for verification")]
302 Unsupported { algorithm: SignatureAlgorithm },
303 #[error("signature is malformed")]
304 Malformed,
305 #[error("signature does not match")]
306 Invalid,
307}
308
309impl PublicKey {
310 pub fn from_spki_der(der: &[u8]) -> Result<Self, KeyError> {
312 let info = spki::SubjectPublicKeyInfoRef::from_der(der).map_err(spki::Error::from)?;
313 Ok(Self(match info.algorithm.oid {
314 RSA_ENCRYPTION => Public::Rsa(RsaPublicKey::from_public_key_der(der)?),
315 EC_PUBLIC_KEY => match info.algorithm.parameters_oid()? {
316 SECP256R1 => Public::P256(p256::ecdsa::VerifyingKey::from_public_key_der(der)?),
317 SECP384R1 => Public::P384(p384::ecdsa::VerifyingKey::from_public_key_der(der)?),
318 curve => return Err(KeyError::UnsupportedCurve { oid: curve }),
319 },
320 oid => return Err(KeyError::UnsupportedAlgorithm { oid }),
321 }))
322 }
323
324 pub fn to_spki_der(&self) -> Result<Vec<u8>, KeyError> {
326 let document = match &self.0 {
327 Public::Rsa(key) => key.to_public_key_der()?,
328 Public::P256(key) => key.to_public_key_der()?,
329 Public::P384(key) => key.to_public_key_der()?,
330 };
331 Ok(document.into_vec())
332 }
333
334 pub fn kind(&self) -> KeyKind {
335 match &self.0 {
336 Public::Rsa(key) => KeyKind::Rsa { bits: key.n().bits_vartime() },
337 Public::P256(_) => KeyKind::EcP256,
338 Public::P384(_) => KeyKind::EcP384,
339 }
340 }
341
342 pub fn verify(
344 &self,
345 algorithm: SignatureAlgorithm,
346 message: &[u8],
347 signature: &[u8],
348 ) -> Result<(), SignatureError> {
349 use SignatureAlgorithm as A;
350 let mismatch = SignatureError::AlgorithmMismatch { algorithm, key: self.kind() };
351 match (&self.0, algorithm) {
352 (Public::Rsa(key), A::RsaPkcs1Sha256) => verify_rsa_pkcs1::<Sha256>(key, message, signature),
353 (Public::Rsa(key), A::RsaPkcs1Sha512) => verify_rsa_pkcs1::<Sha512>(key, message, signature),
354 (Public::Rsa(key), A::RsaPssSha256) => verify_rsa_pss::<Sha256>(key, message, signature),
355 (Public::Rsa(key), A::RsaPssSha512) => verify_rsa_pss::<Sha512>(key, message, signature),
356 (Public::P256(key), A::EcdsaSha256) => verify_p256::<Sha256>(key, message, signature),
357 (Public::P256(key), A::EcdsaSha512) => verify_p256::<Sha512>(key, message, signature),
358 (Public::P384(key), A::EcdsaSha256) => verify_p384::<Sha256>(key, message, signature),
359 (Public::P384(key), A::EcdsaSha512) => verify_p384::<Sha512>(key, message, signature),
360 (_, algorithm) if !algorithm.is_verifiable() => Err(SignatureError::Unsupported { algorithm }),
361 _ => Err(mismatch),
362 }
363 }
364
365 pub(crate) fn verify_jar(
367 &self,
368 digest: DigestAlgorithm,
369 message: &[u8],
370 signature: &[u8],
371 ) -> Result<(), SignatureError> {
372 match digest {
373 DigestAlgorithm::Sha1 => self.verify_jar_with::<Sha1>(message, signature),
374 DigestAlgorithm::Sha256 => self.verify_jar_with::<Sha256>(message, signature),
375 DigestAlgorithm::Sha384 => self.verify_jar_with::<Sha384>(message, signature),
376 DigestAlgorithm::Sha512 => self.verify_jar_with::<Sha512>(message, signature),
377 }
378 }
379
380 fn verify_jar_with<D: Digest + der::oid::AssociatedOid>(
381 &self,
382 message: &[u8],
383 signature: &[u8],
384 ) -> Result<(), SignatureError> {
385 match &self.0 {
386 Public::Rsa(key) => verify_rsa_pkcs1::<D>(key, message, signature),
387 Public::P256(key) => verify_p256::<D>(key, message, signature),
388 Public::P384(key) => verify_p384::<D>(key, message, signature),
389 }
390 }
391}
392
393fn verify_rsa_pkcs1<D>(key: &RsaPublicKey, message: &[u8], signature: &[u8]) -> Result<(), SignatureError>
394where
395 D: Digest + der::oid::AssociatedOid,
396{
397 let signature = pkcs1v15::Signature::try_from(signature).map_err(|_| SignatureError::Malformed)?;
398 pkcs1v15::VerifyingKey::<D>::new(key.clone()).verify(message, &signature).map_err(|_| SignatureError::Invalid)
399}
400
401fn verify_rsa_pss<D>(key: &RsaPublicKey, message: &[u8], signature: &[u8]) -> Result<(), SignatureError>
402where
403 D: Digest + sha2::digest::FixedOutputReset,
404{
405 let signature = pss::Signature::try_from(signature).map_err(|_| SignatureError::Malformed)?;
406 pss::VerifyingKey::<D>::new(key.clone()).verify(message, &signature).map_err(|_| SignatureError::Invalid)
407}