Skip to main content

DecryptionKey

Trait DecryptionKey 

Source
pub trait DecryptionKey {
    // Required methods
    fn decrypt_cek(
        &self,
        encrypted_key: &[u8],
        algorithm: &KeyEncryptionAlgorithm,
    ) -> Result<Vec<u8>, SmimeError>;
    fn matches_recipient(&self, id: &RecipientIdentifier) -> bool;

    // Provided methods
    fn agree_ecdh(
        &self,
        ephemeral_public_key_bytes: &[u8],
        ukm: Option<&[u8]>,
        enc_cek: &[u8],
        alg: &KariAlgorithm,
    ) -> Result<Vec<u8>, SmimeError> { ... }
    fn supported_key_enc_algorithm(&self) -> Option<KeyEncryptionAlgorithm> { ... }
}
Expand description

Abstraction over a private key capable of decrypting an S/MIME message.

Implementors provide the key-unwrap step: given an encrypted CEK and the algorithm that was used to wrap it, return the raw CEK bytes.

Required Methods§

Source

fn decrypt_cek( &self, encrypted_key: &[u8], algorithm: &KeyEncryptionAlgorithm, ) -> Result<Vec<u8>, SmimeError>

Decrypt an encrypted content-encryption key.

Source

fn matches_recipient(&self, id: &RecipientIdentifier) -> bool

Returns true if this key matches the given RecipientIdentifier.

§Example

RecipientIdentifier is #[non_exhaustive], so your implementation must include a catch-all arm (_ => false) to remain forward-compatible with future identifier variants.

fn matches_recipient(&self, id: &RecipientIdentifier) -> bool {
    match id {
        RecipientIdentifier::IssuerAndSerialNumber { issuer_der, serial } => {
            // issuer_der: DER-encoded Name — compare against
            //   cert.tbs_certificate().issuer().to_der().unwrap_or_default()
            // serial: big-endian bytes — compare against
            //   cert.tbs_certificate().serial_number().as_bytes()
            self.cert_issuer_der() == issuer_der
                && self.cert_serial() == serial
        }
        RecipientIdentifier::SubjectKeyIdentifier(ski) => {
            // ski: raw bytes of the Subject Key Identifier extension value —
            //   obtain via cert.tbs_certificate()
            //       .get_extension::<SubjectKeyIdentifier>()
            self.cert_ski() == ski
        }
        _ => false, // required: RecipientIdentifier is #[non_exhaustive]
    }
}

Provided Methods§

Source

fn agree_ecdh( &self, ephemeral_public_key_bytes: &[u8], ukm: Option<&[u8]>, enc_cek: &[u8], alg: &KariAlgorithm, ) -> Result<Vec<u8>, SmimeError>

Perform ECDH key agreement and unwrap the content-encryption key.

Called when the EnvelopedData contains a KARI (KeyAgreeRecipientInfo) entry that matches this key (as determined by matches_recipient).

The implementor must:

  1. Perform ECDH using the recipient’s private key and ephemeral_public_key_bytes (SEC1 uncompressed EC point) to obtain the shared secret Z.
  2. Apply the X9.63 KDF (RFC 5753 §3.6.1): hash Z concatenated with a counter and the EccCmsSharedInfo structure to derive the key-encryption key (KEK). SharedInfo encodes alg.key_wrap OID in keyInfo and, when ukm is Some, the UKM bytes in entityUInfo [0] EXPLICIT. When ukm is None (which is always the case when this crate’s encrypt() produced the message, as this crate never generates UKM), omit entityUInfo.
  3. Unwrap enc_cek with AES-128-KW or AES-256-KW (per alg.key_wrap) using the derived KEK.
  4. Return the raw CEK bytes.
§Default — IMPORTANT for EC key implementors

Returns Err(SmimeError::UnsupportedAlgorithm(...)). EC key implementors MUST override this method or KARI-encrypted messages will silently fail to decrypt (the error is caught per-recipient and the next RecipientInfo is tried; if no other recipient matches, NoMatchingRecipient is returned with no indication that ECDH was attempted). RSA-only keys can leave the default.

Source

fn supported_key_enc_algorithm(&self) -> Option<KeyEncryptionAlgorithm>

Returns a hint about which key encryption algorithms this key supports.

This crate does not consult this hint internally — decrypt() always tries all recipients and lets decrypt_cek() / agree_ecdh() reject unsupported algorithms. This method is provided as an extension point for callers that want to pre-screen or log algorithm capabilities.

Default: returns None (no hint; let decrypt_cek() reject unsupported ones).

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§