Repository navigation
feat(cms): encrypt content to an RSA public key with RSAES-OAEP over SHA-256 - #285
Merged
Merged
Conversation
…SHA-256 The CMS envelope carries the protection of its content-encryption key and writes the recipient form that protection takes: a KEKRecipientInfo for AES key wrap, a KeyTransRecipientInfo for RSAES-OAEP over SHA-256, named by the SHA-256 of the key's SPKI as its subject key identifier. The OAEP parameters are encoded as OpenSSL writes them. encrypt_data reads recipient: in place of encryption_key: to seal content to an RSA-2048 or RSA-4096 public key held elsewhere. The content-encryption key's bytes come from the step's backend and are sealed on the host, with no backend key involved. expect_recipient checks the key received against a declared fingerprint, and the recipient is recorded in a wrap_recipient_recorded fact, as for wrap_key, so rite verify compares it with the identifier the container carries. wrap_key and encrypt_data share the recipient check, which runs before anything is recorded. decrypt_data takes the protection from the container and passes it to open_data_key, which opens an RSA-protected data key under an RSA key allowed to unwrap. It also reads a material's bytes as a container sealed outside the ceremony, such as one written by `openssl cms -encrypt`. A key transport recipient is matched by either name a public key goes by: the SHA-256 of its SPKI, or the SHA-1 of RFC 5280 method 1, which is what a certificate's subject key identifier usually holds. Reading a container is exact: - a KEKRecipientInfo must be version 4, a KeyTransRecipientInfo version 2 with a subject key identifier or version 0 with an issuer and serial number, and neither may carry bytes after its encrypted key; - describing an RSAES-OAEP recipient checks its parameters, and opening admits only OAEP over SHA-256 with MGF1 over SHA-256 and the empty label; - PKCS#1 v1.5 is refused by name, as is a key of the wrong kind or a content key that is not 32 bytes. Refs #202
…ey goes by An RSA public key supplied without the NULL algorithm parameters, which OpenSSL reads as the same key, had two fingerprints: the recipient fact hashed the bytes as supplied and the backend holding the private half reported the encoding OpenSSL exports. wrap_key then failed rite verify on an honest run, and decrypt_data refused content sealed with encrypt_data to such a key as addressed elsewhere. PublicKeyDer::new now writes absent RSA parameters as NULL, so every fingerprint is taken over one encoding. The fingerprint of a key supplied that way is now the one its holder's backend reports, and no longer the digest of the file as supplied. The names a key goes by get their own types in rite-sdk: - KeyFingerprint, the sha256: name over the SPKI. Only PublicKeyDer::fingerprint computes one, and the wrap_recipient_recorded fact, expect_recipient and the throwaway certificate's subject key identifier use it in place of five separate SHA-256 computations. - Rfc5280KeyId, the SHA-1 identifier X.509 tooling writes, which Rite only reads. - cms::RecipientIdentifier, the bytes a container names its recipient by. They are matched against a key or a recorded name and never read as one, so a refusal no longer guesses from their length whether they are a fingerprint or a check value, and shows them as plain hex. rite verify parses the names the transcript records and compares them with the container's identifier, instead of rendering the identifier as a string to compare. Each field is read as the kind of name it is called, and a name is compared only in the recipient form that carries that kind: a check value in a KEKRecipientInfo, a fingerprint in the public-key forms. The transcript format and both schemas are unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
encrypt_datareadsrecipient:in place ofencryption_key:to seal content to an RSA-2048 or RSA-4096 public key held elsewhere. The CMS container carries aKeyTransRecipientInfowritten by hand: the content-encryption key, drawn from the step's backend, is protected with RSAES-OAEP over SHA-256 and the recipient is named by the SHA-256 of its SPKI.expect_recipient:checks the key as onwrap_key, andrite verifymatches the container against the recorded recipient.decrypt_dataopens such a container throughopen_data_key, and also reads a CMS file sealed elsewhere and supplied as a material. Both directions are checked againstopenssl cmswith OAEP over SHA-256. PKCS#1 v1.5 and OAEP with other parameters are refused by name.It also fixes a fingerprint mismatch already in
wrap_key: an RSA public key supplied without the NULL algorithm parameters was recorded under one fingerprint and named in the container under another, sorite verifyfailed on an honest run.PublicKeyDernow keeps one canonical encoding, and the names a key goes by have their own types inrite-sdk:KeyFingerprint,Rfc5280KeyIdandcms::RecipientIdentifier.EC recipients (
kari) follow in a separate PR.Refs #202