1
$\begingroup$

When using openssl cms -encrypt -pwri_password, it follows the process described in RFC 3211, which passes the user-provided password into a KDF, but then, rather than using the output of that KDF to encrypt the content, it instead uses that key as a KEK to encrypt the actual content-encryption key (CEK), which is then bundled alongside the content:

SEQUENCE (2 elem)
  OBJECT IDENTIFIER 1.2.840.113549.1.7.3 envelopedData (PKCS #7)
  [0] (1 elem)
    SEQUENCE (3 elem)
      INTEGER 3
      SET (1 elem)
        [3] (4 elem)
          INTEGER 0
          [0] (2 elem)
            OBJECT IDENTIFIER 1.2.840.113549.1.5.12 pkcs5PBKDF2 (PKCS #5 v2.0)
            SEQUENCE (2 elem)
              OCTET STRING (8 byte) D81093AEE45462EE
              INTEGER 2048
          SEQUENCE (2 elem)
            OBJECT IDENTIFIER 1.2.840.113549.1.9.16.3.9 pwriKEK (S/MIME Algorithms)
            SEQUENCE (2 elem)
              OBJECT IDENTIFIER 1.2.840.113549.3.7 des-EDE3-CBC (RSADSI encryptionAlgorithm)
              OCTET STRING (8 byte) BB96EE7A71BA5792
          OCTET STRING (32 byte) 569E1E845BA33D24D4243ED28B265B0974C486B813E6B9582B014D7E53DD01B9
      SEQUENCE (3 elem)
        OBJECT IDENTIFIER 1.2.840.113549.1.7.1 data (PKCS #7)
        SEQUENCE (2 elem)
          OBJECT IDENTIFIER 1.2.840.113549.3.7 des-EDE3-CBC (RSADSI encryptionAlgorithm)
          OCTET STRING (8 byte) 05AD3B1BDCB767CC
        [0] (16 byte) 7FA32912ECCCD7C421D4F122FD1ED172

The specification states (emphasis added):

§1.2.1 Rationale

Password-based key wrapping is a two-stage process, a first stage in which a user-supplied password is converted into a KEK if required, and a second stage in which the KEK is used to encrypt a CEK.

But I'm unclear on why password-based CMS encryption is done via this two-stage process. Does it somehow protect against future to-be-discovered vulnerabilities in the KDF?

The KDF already has salt as-implemented, so its output is clearly already secure against e.g. rainbow tables— so what is the advantage behind this password-derived-KEK-with-bundled-encrypted-CEK model over simply using the output of the KDF directly as the CEK?

$\endgroup$
5
  • 2
    $\begingroup$ The main reason I could come up with is to encrypt the data encryption key multiple times, e.g. once using a password and once with a public key. Note that CMS also allows multiple signatures. $\endgroup$
    – Maarten Bodewes
    Commented Aug 6, 2021 at 11:43
  • 1
    $\begingroup$ I see: to allow a particular asymmetric recipient and also provide "passworded access"? That seems to be plausible, given that recipientInfos is a SET. $\endgroup$ Commented Aug 6, 2021 at 12:21
  • 2
    $\begingroup$ It also allows changing passwords without re-encrypting content. Only the CEK gets re-encrypted, which can bi much faster. $\endgroup$ Commented Aug 6, 2021 at 13:13
  • $\begingroup$ These speculations are excellent, though I have now sent the author of the RFC an e-mail asking after the historical fact of the rationale here. $\endgroup$ Commented May 29, 2022 at 23:33
  • $\begingroup$ I guess this lets an interactive CMS encryptor software designer start encrypting a large file in the background while waiting for the user to type the desired passphrase, and to continue to run the file encryption in parallel with the KDF on multicore CPUs $\endgroup$ Commented Sep 15, 2022 at 15:26

1 Answer 1

1
$\begingroup$

CMS is just following a standard design.

CMS allows a message to be encrypted for multiple recipients. The content encryption uses a randomly generated key, the CEK. The CMS object contains an EncryptedKey blob for each recipient. Each EncryptedKey blob contains the CEK encrypted with a method that can be different for each recipients.

This two-level mechanism is standard to encrypt messages with multiple recipients. There is a single content encryption key (CEK): if the content was encrypted separately for each recipient, this would multiple the size of the message, and the work done to encrypt, by the number of recipients. Every recipient has to be able to obtain the CEK somehow, but in general, different recipients have different sets of preestablished secrets (for example, they know different passwords, or they have different private keys). So a message with N recipients contains N blobs, each of which is readable by a different recipients.

Furthermore, this two-level mechanism is also standard whenever passwords are involved, even when there a single user is supposed to decrypt the data. Users often want to change passwords. If the CEK was derived from the password, a password change would require re-encrypting the data. So instead the password is only used to encrypt the CEK.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.