Skip to main content

mail_auth/crypto/
aws_lc.rs

1/*
2 * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
3 *
4 * SPDX-License-Identifier: Apache-2.0 OR MIT
5 */
6
7//! Signing and verification keys backed by `aws-lc-rs`.
8
9use super::{
10    Algorithm, CryptoError, ED25519_PUBLIC_KEY_LEN, HashContext, HashImpl, HashOutput,
11    MLDSA44_MESSAGE_CAPACITY, Sha1, Sha256, Sha512, SigningKey, VerifyingKey,
12    aws_lc_mldsa::MlDsa44,
13    mldsa::{self, CONTEXT, SIGNATURE_LEN, Seed, library_error},
14    rsa_private_key_heap_size,
15};
16use crate::{
17    Error, Result,
18    dkim::Canonicalization,
19    headers::{Writable, Writer},
20};
21use aws_lc_rs::digest::{Context, SHA1_FOR_LEGACY_USE_ONLY, SHA256, SHA512};
22use aws_lc_rs::rand::SystemRandom;
23use aws_lc_rs::signature::{
24    ED25519, Ed25519KeyPair, KeyPair, RSA_PKCS1_1024_8192_SHA1_FOR_LEGACY_USE_ONLY,
25    RSA_PKCS1_1024_8192_SHA256_FOR_LEGACY_USE_ONLY, RSA_PKCS1_SHA256, RsaKeyPair,
26    UnparsedPublicKey,
27};
28use rustls_pki_types::{PrivateKeyDer, PrivatePkcs1KeyDer, PrivatePkcs8KeyDer, pem::PemObject};
29use std::marker::PhantomData;
30
31const ED25519_PRIVATE_KEY_HEAP_SIZE: usize = 112;
32const MLDSA44_PRIVATE_KEY_HEAP_SIZE: usize = 4096;
33const MLDSA44_PUBLIC_KEY_HEAP_SIZE: usize = 1600;
34
35/// An RSA private key for `rsa-sha256` signing (RFC 6376 Section 3.3.2).
36///
37/// `T` selects the hash function; only `RsaKey<Sha256>` implements
38/// [`SigningKey`]. Load a key with [`from_key_der`](Self::from_key_der).
39#[derive(Debug)]
40pub struct RsaKey<T> {
41    inner: RsaKeyPair,
42    rng: SystemRandom,
43    padding: PhantomData<T>,
44}
45
46impl<T: HashImpl> RsaKey<T> {
47    /// Loads an RSA private key from a PKCS #8 PEM string.
48    ///
49    /// # Errors
50    ///
51    /// Returns [`Error::Crypto`] with [`CryptoError::Library`] if the key
52    /// cannot be decoded.
53    #[deprecated(since = "0.7.4", note = "use `from_key_der()` instead")]
54    pub fn from_pkcs8_pem(pkcs8_pem: &str) -> Result<Self> {
55        Self::from_key_der(PrivateKeyDer::Pkcs8(
56            PrivatePkcs8KeyDer::from_pem_slice(pkcs8_pem.as_bytes())
57                .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))?,
58        ))
59    }
60
61    /// Loads an RSA private key from PKCS #8 DER bytes.
62    ///
63    /// # Errors
64    ///
65    /// Returns [`Error::Crypto`] with [`CryptoError::Library`] if the key
66    /// cannot be decoded.
67    #[deprecated(since = "0.7.4", note = "use `from_key_der()` instead")]
68    pub fn from_pkcs8_der(pkcs8_der: &[u8]) -> Result<Self> {
69        Self::from_key_der(PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(pkcs8_der)))
70    }
71
72    /// Loads an RSA private key from a PKCS #1 PEM string
73    /// (`BEGIN RSA PRIVATE KEY`).
74    ///
75    /// # Errors
76    ///
77    /// Returns [`Error::Crypto`] with [`CryptoError::Library`] if the key
78    /// cannot be decoded.
79    #[deprecated(since = "0.7.4", note = "use `from_key_der()` instead")]
80    pub fn from_rsa_pem(rsa_pem: &str) -> Result<Self> {
81        Self::from_key_der(PrivateKeyDer::Pkcs1(
82            PrivatePkcs1KeyDer::from_pem_slice(rsa_pem.as_bytes())
83                .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))?,
84        ))
85    }
86
87    /// Loads an RSA private key from PKCS #1 DER bytes.
88    ///
89    /// # Errors
90    ///
91    /// Returns [`Error::Crypto`] with [`CryptoError::Library`] if the key
92    /// cannot be decoded.
93    #[deprecated(since = "0.7.4", note = "use `from_key_der()` instead")]
94    pub fn from_der(der: &[u8]) -> Result<Self> {
95        Self::from_key_der(PrivateKeyDer::Pkcs1(PrivatePkcs1KeyDer::from(der)))
96    }
97
98    /// Loads an RSA private key from DER, in PKCS #1 (`RSAPrivateKey`) or
99    /// PKCS #8 (`PrivateKeyInfo`) form. Parse PEM input first with
100    /// [`PrivateKeyDer::from_pem_slice`](rustls_pki_types::pem::PemObject::from_pem_slice).
101    ///
102    /// # Errors
103    ///
104    /// Returns [`Error::Crypto`] with [`CryptoError::Library`] if the key is
105    /// in another format (such as SEC1) or cannot be decoded.
106    pub fn from_key_der(key_der: PrivateKeyDer<'_>) -> Result<Self> {
107        let inner = match key_der {
108            PrivateKeyDer::Pkcs1(der) => RsaKeyPair::from_der(der.secret_pkcs1_der())
109                .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))?,
110            PrivateKeyDer::Pkcs8(der) => RsaKeyPair::from_pkcs8(der.secret_pkcs8_der())
111                .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))?,
112            _ => {
113                return Err(Error::Crypto(CryptoError::Library(
114                    "Unsupported RSA key format".to_string(),
115                )));
116            }
117        };
118
119        Ok(Self {
120            inner,
121            rng: SystemRandom::new(),
122            padding: PhantomData,
123        })
124    }
125
126    /// Returns the public key of the RSA key pair, encoded as a DER PKCS #1
127    /// `RSAPublicKey`.
128    pub fn public_key(&self) -> Vec<u8> {
129        self.inner.public_key().as_ref().to_vec()
130    }
131}
132
133impl SigningKey for RsaKey<Sha256> {
134    type Hasher = Sha256;
135
136    fn sign(&self, input: impl Writable) -> Result<Vec<u8>> {
137        let mut data = Vec::with_capacity(256);
138        input.write(&mut data);
139
140        let mut signature = vec![0; self.inner.public_key().modulus_len()];
141        self.inner
142            .sign(&RSA_PKCS1_SHA256, &self.rng, &data, &mut signature)
143            .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))?;
144        Ok(signature)
145    }
146
147    fn algorithm(&self) -> Algorithm {
148        Algorithm::RsaSha256
149    }
150
151    fn heap_size(&self) -> usize {
152        rsa_private_key_heap_size(self.inner.public_key().modulus_len())
153    }
154}
155
156/// An Ed25519 private key for `ed25519-sha256` signing (RFC 8463).
157///
158/// The signature is computed over the SHA-256 hash of the signed data, as
159/// RFC 8463 Section 3 requires.
160pub struct Ed25519Key {
161    inner: Ed25519KeyPair,
162}
163
164impl Ed25519Key {
165    /// Generates a new random Ed25519 key pair and returns it as PKCS #8 DER
166    /// bytes, ready for [`from_pkcs8_der`](Self::from_pkcs8_der).
167    ///
168    /// # Errors
169    ///
170    /// Returns [`Error::Crypto`] with [`CryptoError::Library`] if key
171    /// generation or encoding fails.
172    pub fn generate_pkcs8() -> Result<Vec<u8>> {
173        Ok(Ed25519KeyPair::generate_pkcs8(&SystemRandom::new())
174            .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))?
175            .as_ref()
176            .to_vec())
177    }
178
179    /// Loads an Ed25519 key pair from PKCS #8 v2 DER bytes (RFC 5958), checking
180    /// that the embedded public key matches the private key. PKCS #8 v1
181    /// documents are rejected by `ring`; load them with
182    /// [`from_pkcs8_maybe_unchecked_der`](Self::from_pkcs8_maybe_unchecked_der).
183    ///
184    /// # Errors
185    ///
186    /// Returns [`Error::Crypto`] with [`CryptoError::Library`] if the key
187    /// cannot be decoded.
188    pub fn from_pkcs8_der(pkcs8_der: &[u8]) -> Result<Self> {
189        Ok(Self {
190            inner: Ed25519KeyPair::from_pkcs8(pkcs8_der)
191                .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))?,
192        })
193    }
194
195    /// Loads an Ed25519 key pair from PKCS #8 v1 or v2 DER bytes. A v1
196    /// document (as produced by `openssl genpkey -algorithm ED25519`) carries
197    /// no public key, so no consistency check is possible; v2 documents are
198    /// checked as in [`from_pkcs8_der`](Self::from_pkcs8_der).
199    ///
200    /// # Errors
201    ///
202    /// Returns [`Error::Crypto`] with [`CryptoError::Library`] if the key
203    /// cannot be decoded.
204    pub fn from_pkcs8_maybe_unchecked_der(pkcs8_der: &[u8]) -> Result<Self> {
205        Ok(Self {
206            inner: Ed25519KeyPair::from_pkcs8_maybe_unchecked(pkcs8_der)
207                .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))?,
208        })
209    }
210
211    /// Builds an Ed25519 key pair from its 32-byte seed (private key) and
212    /// 32-byte public key.
213    ///
214    /// # Errors
215    ///
216    /// Returns [`Error::Crypto`] with [`CryptoError::Library`] if either
217    /// value has the wrong length or the public key does not match the seed.
218    pub fn from_seed_and_public_key(seed: &[u8], public_key: &[u8]) -> Result<Self> {
219        Ok(Self {
220            inner: Ed25519KeyPair::from_seed_and_public_key(seed, public_key)
221                .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))?,
222        })
223    }
224
225    /// Returns the 32-byte raw Ed25519 public key, as published in the `p=`
226    /// tag of a DKIM key record.
227    pub fn public_key(&self) -> Vec<u8> {
228        self.inner.public_key().as_ref().to_vec()
229    }
230}
231
232impl SigningKey for Ed25519Key {
233    type Hasher = Sha256;
234
235    fn sign(&self, input: impl Writable) -> Result<Vec<u8>> {
236        let mut data = Sha256::hasher();
237        input.write(&mut data);
238        Ok(self.inner.sign(data.complete().as_ref()).as_ref().to_vec())
239    }
240
241    fn algorithm(&self) -> Algorithm {
242        Algorithm::Ed25519Sha256
243    }
244
245    fn heap_size(&self) -> usize {
246        ED25519_PRIVATE_KEY_HEAP_SIZE
247    }
248}
249
250pub(crate) struct RsaPublicKey {
251    key: Vec<u8>,
252}
253
254impl RsaPublicKey {
255    pub(crate) fn verifying_key_from_bytes(
256        bytes: &[u8],
257    ) -> Result<Box<dyn VerifyingKey + Send + Sync>> {
258        Ok(Box::new(Self {
259            key: try_strip_rsa_prefix(bytes).unwrap_or(bytes).to_vec(),
260        }))
261    }
262}
263
264/// Computes the RSA modulus size in bits from a DER-encoded RSAPublicKey
265fn rsa_modulus_bits(key: &[u8]) -> Option<usize> {
266    if *key.first()? != DER_SEQUENCE_TAG {
267        return None;
268    }
269    let (_, rest) = decode_multi_byte_len(&key[1..])?;
270    if *rest.first()? != DER_INTEGER_TAG {
271        return None;
272    }
273    let (len, after_len) = decode_multi_byte_len(&rest[1..])?;
274    after_len
275        .get(..len)?
276        .iter()
277        .position(|&b| b != 0)
278        .map(|leading_zeros| (len - leading_zeros) * 8)
279}
280
281/// Try to strip an ASN.1 DER-encoded RSA public key prefix
282///
283/// Returns the original slice if the prefix is not found.
284fn try_strip_rsa_prefix(bytes: &[u8]) -> Option<&[u8]> {
285    if *bytes.first()? != DER_SEQUENCE_TAG {
286        return None;
287    }
288
289    let (_, bytes) = decode_multi_byte_len(&bytes[1..])?;
290    if *bytes.first()? != DER_SEQUENCE_TAG {
291        return None;
292    }
293
294    let (byte_len, bytes) = decode_multi_byte_len(&bytes[1..])?;
295    if *bytes.first()? != DER_OBJECT_ID_TAG || byte_len != 13 {
296        return None;
297    }
298
299    let bytes = bytes.get(13..)?;
300    if *bytes.first()? != DER_BIT_STRING_TAG {
301        return None;
302    }
303
304    decode_multi_byte_len(&bytes[1..]).and_then(|(_, bytes)| bytes.get(1..))
305}
306
307fn decode_multi_byte_len(bytes: &[u8]) -> Option<(usize, &[u8])> {
308    if bytes.first()? & 0x80 == 0 {
309        return Some((bytes[0] as usize, &bytes[1..]));
310    }
311
312    let len_len = (bytes[0] & 0x7f) as usize;
313    if bytes.len() < len_len + 1 {
314        return None;
315    }
316
317    let mut len = 0;
318    for i in 0..len_len {
319        len = (len << 8) | bytes[1 + i] as usize;
320    }
321
322    Some((len, &bytes[len_len + 1..]))
323}
324
325const DER_OBJECT_ID_TAG: u8 = 0x06;
326const DER_BIT_STRING_TAG: u8 = 0x03;
327const DER_SEQUENCE_TAG: u8 = 0x30;
328const DER_INTEGER_TAG: u8 = 0x02;
329
330impl VerifyingKey for RsaPublicKey {
331    fn verify<'a>(
332        &self,
333        headers: &mut dyn Iterator<Item = (&'a [u8], &'a [u8])>,
334        signature: &[u8],
335        canonicalization: Canonicalization,
336        algorithm: Algorithm,
337    ) -> Result<()> {
338        let mut data = Vec::with_capacity(256);
339        canonicalization.canonicalize_headers(headers, &mut data);
340
341        match algorithm {
342            Algorithm::RsaSha256 => UnparsedPublicKey::new(
343                &RSA_PKCS1_1024_8192_SHA256_FOR_LEGACY_USE_ONLY,
344                self.key.as_slice(),
345            )
346            .verify(&data, signature)
347            .map_err(|_| Error::Crypto(CryptoError::FailedVerification)),
348            Algorithm::RsaSha1 => UnparsedPublicKey::new(
349                &RSA_PKCS1_1024_8192_SHA1_FOR_LEGACY_USE_ONLY,
350                self.key.as_slice(),
351            )
352            .verify(&data, signature)
353            .map_err(|_| Error::Crypto(CryptoError::FailedVerification)),
354            Algorithm::Ed25519Sha256 | Algorithm::MlDsa44 => {
355                Err(Error::Crypto(CryptoError::IncompatibleAlgorithms))
356            }
357        }
358    }
359
360    fn verify_bytes(&self, input: &[u8], signature: &[u8], algorithm: Algorithm) -> Result<()> {
361        match algorithm {
362            Algorithm::RsaSha256 => UnparsedPublicKey::new(
363                &RSA_PKCS1_1024_8192_SHA256_FOR_LEGACY_USE_ONLY,
364                self.key.as_slice(),
365            )
366            .verify(input, signature)
367            .map_err(|_| Error::Crypto(CryptoError::FailedVerification)),
368            Algorithm::RsaSha1 => UnparsedPublicKey::new(
369                &RSA_PKCS1_1024_8192_SHA1_FOR_LEGACY_USE_ONLY,
370                self.key.as_slice(),
371            )
372            .verify(input, signature)
373            .map_err(|_| Error::Crypto(CryptoError::FailedVerification)),
374            Algorithm::Ed25519Sha256 | Algorithm::MlDsa44 => {
375                Err(Error::Crypto(CryptoError::IncompatibleAlgorithms))
376            }
377        }
378    }
379
380    fn public_key_bits(&self) -> usize {
381        rsa_modulus_bits(&self.key).unwrap_or_default()
382    }
383
384    fn heap_size(&self) -> usize {
385        self.key.capacity()
386    }
387}
388
389pub(crate) struct Ed25519PublicKey {
390    inner: UnparsedPublicKey<[u8; ED25519_PUBLIC_KEY_LEN]>,
391}
392
393impl Ed25519PublicKey {
394    pub(crate) fn verifying_key_from_bytes(
395        bytes: &[u8],
396    ) -> Result<Box<dyn VerifyingKey + Send + Sync>> {
397        let key: [u8; ED25519_PUBLIC_KEY_LEN] = bytes
398            .try_into()
399            .map_err(|_| Error::Crypto(CryptoError::MalformedPublicKey))?;
400        Ok(Box::new(Self {
401            inner: UnparsedPublicKey::new(&ED25519, key),
402        }))
403    }
404}
405
406impl VerifyingKey for Ed25519PublicKey {
407    fn verify<'a>(
408        &self,
409        headers: &mut dyn Iterator<Item = (&'a [u8], &'a [u8])>,
410        signature: &[u8],
411        canonicalization: Canonicalization,
412        algorithm: Algorithm,
413    ) -> Result<()> {
414        if !matches!(algorithm, Algorithm::Ed25519Sha256) {
415            return Err(Error::Crypto(CryptoError::IncompatibleAlgorithms));
416        }
417
418        let mut hasher = Sha256::hasher();
419        canonicalization.canonicalize_headers(headers, &mut hasher);
420        self.inner
421            .verify(hasher.complete().as_ref(), signature)
422            .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))
423    }
424
425    fn verify_bytes(&self, input: &[u8], signature: &[u8], algorithm: Algorithm) -> Result<()> {
426        if !matches!(algorithm, Algorithm::Ed25519Sha256) {
427            return Err(Error::Crypto(CryptoError::IncompatibleAlgorithms));
428        }
429
430        let mut hasher = Sha256::hasher();
431        hasher.write(input);
432        self.inner
433            .verify(hasher.complete().as_ref(), signature)
434            .map_err(|_| Error::Crypto(CryptoError::FailedVerification))
435    }
436}
437
438/// An ML-DSA-44 private key for `mldsa44` signing (DKIM2 only,
439/// draft-ietf-dkim-dkim2-spec Section 3.4).
440///
441/// Signatures use "pure" ML-DSA-44 (FIPS 204) with the `DKIM2` context
442/// string. They are hedged (randomized), as the specification recommends, so
443/// signing the same input twice gives different signatures.
444pub struct MlDsa44Key {
445    inner: MlDsa44,
446}
447
448impl MlDsa44Key {
449    /// Generates a new random key and returns it as PKCS #8 DER bytes (the
450    /// RFC 9881 seed-only private key encoding), ready for
451    /// [`from_pkcs8_der`](Self::from_pkcs8_der).
452    ///
453    /// # Errors
454    ///
455    /// Returns [`Error::Crypto`] with [`CryptoError::Library`] if the system
456    /// random number generator fails.
457    pub fn generate_pkcs8() -> Result<Vec<u8>> {
458        let mut seed = Seed::default();
459        aws_lc_rs::rand::fill(&mut seed)
460            .map_err(|err| Error::Crypto(CryptoError::Library(err.to_string())))?;
461        Ok(mldsa::pkcs8_der(&seed))
462    }
463
464    /// Loads a key from PKCS #8 DER bytes holding an ML-DSA-44 private key in
465    /// the RFC 9881 seed-only or both (seed and expanded key) form. The key
466    /// is derived from the seed.
467    ///
468    /// # Errors
469    ///
470    /// Returns [`Error::Crypto`] with [`CryptoError::Library`] if the key
471    /// cannot be decoded or has no seed.
472    pub fn from_pkcs8_der(pkcs8_der: &[u8]) -> Result<Self> {
473        Self::from_seed(mldsa::seed_from_pkcs8_der(pkcs8_der)?)
474    }
475
476    /// Loads a key from its 32-byte seed.
477    ///
478    /// # Errors
479    ///
480    /// Returns [`Error::Crypto`] with [`CryptoError::Library`] if the seed
481    /// has the wrong length or cannot be expanded.
482    pub fn from_raw_private_key(raw: &[u8]) -> Result<Self> {
483        Self::from_seed(mldsa::seed_from_raw(raw)?)
484    }
485
486    fn from_seed(seed: &Seed) -> Result<Self> {
487        MlDsa44::from_seed(seed)
488            .map(|inner| Self { inner })
489            .ok_or_else(|| library_error("Invalid ML-DSA-44 seed"))
490    }
491
492    /// Returns the 1312-byte ML-DSA-44 public key, as published in the `p=`
493    /// tag of a `k=mldsa44` key record.
494    ///
495    /// # Errors
496    ///
497    /// Returns [`Error::Crypto`] with [`CryptoError::Library`] if the backend
498    /// cannot export the public key.
499    pub fn public_key(&self) -> Result<Vec<u8>> {
500        self.inner
501            .public_key()
502            .map(Vec::from)
503            .ok_or_else(|| library_error("Cannot export the ML-DSA-44 public key"))
504    }
505}
506
507impl SigningKey for MlDsa44Key {
508    type Hasher = Sha256;
509
510    fn sign(&self, input: impl Writable) -> Result<Vec<u8>> {
511        let mut message = Vec::with_capacity(MLDSA44_MESSAGE_CAPACITY);
512        input.write(&mut message);
513        self.inner
514            .sign(&message, CONTEXT)
515            .map(Vec::from)
516            .ok_or_else(|| library_error("ML-DSA-44 signing failed"))
517    }
518
519    fn algorithm(&self) -> Algorithm {
520        Algorithm::MlDsa44
521    }
522
523    fn heap_size(&self) -> usize {
524        MLDSA44_PRIVATE_KEY_HEAP_SIZE
525    }
526}
527
528pub(crate) struct MlDsa44PublicKey {
529    inner: MlDsa44,
530}
531
532impl MlDsa44PublicKey {
533    pub(crate) fn verifying_key_from_bytes(
534        bytes: &[u8],
535    ) -> Result<Box<dyn VerifyingKey + Send + Sync>> {
536        let key = mldsa::public_key_from_bytes(bytes)?;
537        Ok(Box::new(Self {
538            inner: MlDsa44::from_public_key(key)
539                .ok_or(Error::Crypto(CryptoError::MalformedPublicKey))?,
540        }))
541    }
542}
543
544impl VerifyingKey for MlDsa44PublicKey {
545    fn verify<'a>(
546        &self,
547        _: &mut dyn Iterator<Item = (&'a [u8], &'a [u8])>,
548        _: &[u8],
549        _: Canonicalization,
550        _: Algorithm,
551    ) -> Result<()> {
552        Err(Error::Crypto(CryptoError::IncompatibleAlgorithms))
553    }
554
555    fn verify_bytes(&self, input: &[u8], signature: &[u8], algorithm: Algorithm) -> Result<()> {
556        if !matches!(algorithm, Algorithm::MlDsa44) {
557            return Err(Error::Crypto(CryptoError::IncompatibleAlgorithms));
558        }
559        let signature: &[u8; SIGNATURE_LEN] = signature
560            .try_into()
561            .map_err(|_| Error::Crypto(CryptoError::FailedVerification))?;
562        if self.inner.verify(input, CONTEXT, signature) {
563            Ok(())
564        } else {
565            Err(Error::Crypto(CryptoError::FailedVerification))
566        }
567    }
568
569    fn heap_size(&self) -> usize {
570        MLDSA44_PUBLIC_KEY_HEAP_SIZE
571    }
572}
573
574impl HashImpl for Sha1 {
575    type Context = Context;
576
577    fn hasher() -> Self::Context {
578        Context::new(&SHA1_FOR_LEGACY_USE_ONLY)
579    }
580}
581
582impl HashImpl for Sha256 {
583    type Context = Context;
584
585    fn hasher() -> Self::Context {
586        Context::new(&SHA256)
587    }
588}
589
590impl HashImpl for Sha512 {
591    type Context = Context;
592
593    fn hasher() -> Self::Context {
594        Context::new(&SHA512)
595    }
596}
597
598impl HashContext for Context {
599    fn complete(self) -> HashOutput {
600        HashOutput::Digest(self.finish())
601    }
602}
603
604impl Writer for Context {
605    fn write(&mut self, data: &[u8]) {
606        self.update(data);
607    }
608}
609
610#[cfg(test)]
611mod tests {
612    use super::*;
613
614    #[test]
615    fn from_key_der_pkcs1() {
616        let key_der = PrivateKeyDer::from_pem_slice(PKCS1_PEM.as_bytes()).unwrap();
617        assert!(matches!(key_der, PrivateKeyDer::Pkcs1(_)));
618        RsaKey::<Sha256>::from_key_der(key_der).unwrap();
619    }
620
621    #[test]
622    fn from_key_der_pkcs8() {
623        let key_der = PrivateKeyDer::from_pem_slice(PKCS8_PEM.as_bytes()).unwrap();
624        assert!(matches!(key_der, PrivateKeyDer::Pkcs8(_)));
625        RsaKey::<Sha256>::from_key_der(key_der).unwrap();
626    }
627
628    const PKCS1_PEM: &str = r#"-----BEGIN RSA PRIVATE KEY-----
629MIIEoAIBAAKCAQEAplSshLNG7gYj7LckWBQ5Gg1mrFGj2soo3VuMKSbvfR6tMrnj
630khKUSl3TWQyKdkuOOf4EzAyxhJdq/hWGvMdwfwH2q4UzjjcaRHDP54oBH6WHxyAn
631UUkJTFfJo2i8jFE/um09igLr5sEaKMiHgjQIdUScuQRGqKhqS9e4tPpTnfP4ayvM
632zVvD1ptUnaV4O9+GkpEwx/vLVXItMO2KNXXKADYBuWcY9g+Dlpp637radmLJjnvj
633bCJipWjuVzUEQvIvf3x1dZ4b899Bycp4uScmdz5brfxkhLaA9vchnmr+F7aAuwwK
634N5X2Ep6n5d1M0XjA02Z9Zi2W4NkZiNBBmb/f6QIDAQABAoIBAAPzPANNGv4L98jx
635+C3o/F/YbyE1sXmV9lP8I1nr1+FbETvEleQSHGL1aPpIVbZ6/gugXdP3E4qFqmUS
636ik1hQtRFWJVuDPwk5ghiPHxwIYLd+cRFHiHsT96isWzNJTiDinWpN/5XKkE5QfTe
637KaJc4tGJebEG1LhsgtUTxbTImCPxYvKUItDlApOusVvhARjqCnXunNEu5iDiADHH
638Wsv3eSPdWkdF5Jjgt/bI4I9XmagX3e1z6ZQiGvdBwCc8ccwkU6yTswXgWCPqyw/t
639lbTFqE19lEoHGTYYElKaHUo9hCmI3HZS69ShYKG7dMT9dVLhzRlNx7AzZcYWh8Mx
640Ptc8OY0CgYEA1LJe5EpfJ/XvzbiVtNiq07CGhlQj62DAH+XpyqtWHHrUNgMbnBZS
64129had9h2NyfIFDIZAKPGWRuSB6PSyDR6w5Sugh5nRoXshzaFr1pAHmo18s+QELjj
642XyccwivxRXurwmdDL5Bx0YCKII4LJyE3CBlJzq0/wOxvi+iKDRG+TIUCgYEAyDG8
643DXk+E6f9Vd4phaN3sLVDd228U/NNuEr+K74AFHwomgEv//KdK2i/EjFq0zGf31jE
644QMoVbnTDmmzVPfKRDlD3tk5XIz2TDzgGxOYBIWJLUiOlkXxckbLVJBR3NxKn561n
645id7vMR8ik+hAhEp9yZishZr+QrS/4AyHR3ahBRUCgYBYgoGKboh6kJVh/lYOE7vC
646q8rPS2RHJtPMclh/xhznbRWyBEkRAxkn8zhydtl6ykswXEibQ4veuOJj24BzX6NW
647kCCudQh1CHYNLlsjRWM5ROl+SXGiA85aYmRNSQv15ijrlR0YRfuXOu4/7dwmRGQq
648MpvMLbxCBCHHDtWj6qZOIQKBgF+3F7hBbaKsQP2bGLMicwlzwOwK9W4V9+TTRi7X
649yuYAbtEjHDX9Y5Prot8p7W9IXK3GnR51AEYtYZAl1NancR8tKyJo1lStDfDK0sG1
650TnkNrAF7tZ+XnBK1NB7qAg28x7aHO+e5RRdxUXDyLFaT3wxSCLpgXoy6KrsOgmdy
651mo35An9pYQ3Ik9ghh3PJsQ0r/TywuKIzmSvLJZfI/cuBOFkPDoWCleQGdzyQcxuc
652PSCtw8eXUj/Oc09qo5dRWXQkt5uW8sJB0k5fNnfCDqNReUXavDNXOHq31J5USy5R
6538ts1bmtZtK0oRci6A8PcgWChUvSfFUT5IrQM/x4rxabn8qIK
654-----END RSA PRIVATE KEY-----
655"#;
656
657    const PKCS8_PEM: &str = r#"-----BEGIN PRIVATE KEY-----
658MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDXxo5+n7aZ0psn
659dNjs53za9Af657AuG3sVnvWEBf24OvwwWClJ5vN+cWA7V2yIuuVvd40RxX1N4HLX
660QewaUBVw+XlHanskcYA8WTVuMTI6XNY6hIAtU1ETSWAPke5sH6DyrAzxIoC2R+IH
661ejqwjtdWdQ0MNVudqY3BO6mAH+zYblRzytMmcols+aqYNgZeAYuEie+EiJiTT65v
662y0mG24k0ALF5XLPahxhoUK/xuhjjG/Y/InD8s6C4BksO29bStnyqhMToSGMtUyOT
663PTyh1XgrUB4dlfEnpfX9F/wU8a7ijrD38Qtg935c08Qg9YcwVXzpFHWRw/ZF/auq
664lcazbMaHAgMBAAECggEAOKmhncrfLsHJkLD0jjGz7eOLfO3+q/z3c5QMsSDJoemL
665dD6SiR+m7ZtkQ/EPRVCfE4h3eSU9ZIf+YFylXbuOBd7dZE2oDMfpfu+GQmuU3xKm
666BzPoXP62GbR5D12pGKetokxgEaqX1kZGKuSEKP05uzB9vqj8aAiwev/p4QWBMsw6
6672stumeWMuZortwL9PZpXgzpJPHXDnFdsn3OIINBMFYFdqda8RhL3rWWsbV5nL1oR
668Q2/SMPLc1dQ8ZQKdPmbVhdfnPitVKVEkn8xIiFPWNS3SfYIi+wQj0lWdJbvUUJ1i
6697BIXvnXeeVLyYhekTpE5ZnGeGI4A5lix4PN+GIao8QKBgQDtuPW8BaXWfPHb93Kl
670mWBQNHz0I71p8GL9/+xRpA9SMuUtYS0jJ1whNgcwoSI4cOKo1UsIMDPAPpTU47Ul
6710D+vXr/GyiONL6+IsXAf5xhaQnUWRWKs4G9obadyGkT8aH6y8W+ddKD1JWQKUf4t
672Bmpeim+Ck0I8POhDbNNfThTLwwKBgQDoXZ70Pb6HViZAbzf+rEznNycgG8IqtTSc
673V7YoSMZe17u0AQjE9XZizBrhpz47N6/JvyYTBIh6VPQe880FTnHdUjvbqn8bmLE7
674QEYwvgF5hmHVXlWXUsyKbfMH5Dp8Uy74FV2VTd1hJ7UMSke7LQT41Hgyaz32x7Lm
675r0P63fgh7QKBgQDMrnCGz6YWo8XrS4efJgxTgp4D57HzQVM6t9xV/xhiAghppj4j
676AoTE46wVJug8CJZgICZWiopEgJ3NH7KdOE1dRguBshIiQmi1HXIZRfUl4grGfj+T
6778jp6g8+k4xF68s4EbPVZcU4VRXh5mldrlRaJCFEy8HAbRaYGR/FHIget2QKBgGd/
678o9h4VBAmAD29DDzkdBCc0VGM66xoL/nfW6SP3cPK5bFksIpCJywUa3jNLHvl7ue2
679u3fHEh8jDeVnhI9zhGYnRcAvLhSVq4OPunPlffSqNZN7RDZ1y+Nw28pNDvvndUlN
680AvUIzK2EqTDDOTYW9Fr9EFisydnM01PLB0WLbwV1AoGAGmaWcbNfPyPnJU1nIHGG
681fPlEpGn+3Oxr1ja02FPwexk/bg6CRVIqP2x7RtR1cH9fOqiDOoIqyfKswuZkwVj3
682EMeos/WHHrw+UzXem+IswmwG9rnUBMlMRCkJ9GhXk98bqoWeJpMhlj1L+oBQ3Spj
683j8T1spkdY4jj3CvmzQ0ha0U=
684-----END PRIVATE KEY-----
685"#;
686}