Add ML-KEM (FIPS 203) post-quantum key transport support - #652
Conversation
Adds ML-KEM-512/768/1024 key transport via the W3C "XML Security: Generic Hybrid Cipher" structure, on both the DOM and STAX encryption paths. Part of the post-quantum work tracked under SANTUARIO-634 (originally proposed in SANTUARIO-633 / apache#645), split out here as the encryption-only half per community request. Adds negative-test coverage on both the DOM and STAX paths: decryption with the wrong recipient's ML-KEM private key fails cleanly, and a truncated EncryptedKey CipherValue is rejected via the existing length check in KeyUtils#kemDecapsulate. Added per Arpan0995's review feedback on apache#645.
| KeyUtils.KemDecapsulation kemResult = KeyUtils.kemDecapsulate( | ||
| (PrivateKey) wrapKeyToken, kemAlgorithm, encryptedBytes, kdp); | ||
| String jceWrapId = JCEMapper.translateURItoJCEID(dataEncapsulationAlgorithm); | ||
| Cipher cipher = Cipher.getInstance(jceWrapId); |
| KeyUtils.KemDecapsulation kemResult = KeyUtils.kemDecapsulate( | ||
| (PrivateKey) wrapKeyToken, kemAlgorithm, encryptedBytes, kdp); | ||
| String jceWrapId = JCEMapper.translateURItoJCEID(dataEncapsulationAlgorithm); | ||
| Cipher cipher = Cipher.getInstance(jceWrapId); |
| KeyUtils.KemEncapsulation kemResult = KeyUtils.kemEncapsulate(pubKey, kemAlgorithm, kdfParams); | ||
| try { | ||
| String jceWrapId = JCEMapper.translateURItoJCEID(dataEncapsulationAlgorithm); | ||
| Cipher wrapCipher = Cipher.getInstance(jceWrapId); |
| KeyUtils.KemEncapsulation kemResult = KeyUtils.kemEncapsulate(pubKey, kemAlgorithm, kdfParams); | ||
| try { | ||
| String jceWrapId = JCEMapper.translateURItoJCEID(dataEncapsulationAlgorithm); | ||
| Cipher wrapCipher = Cipher.getInstance(jceWrapId); |
…r sets Converts the wrong-recipient-key and truncated-encapsulation rejection tests on both the DOM and StAX paths from single hardcoded ML-KEM-768 cases to @ParameterizedTest/@CsvSource across ML-KEM-512/768/1024, matching the style of the existing encrypt-decrypt tests. The encryptToRecipient helpers take the key encapsulation algorithm as a parameter instead of hardcoding ML-KEM-768.
Parameterize the negative encryption tests across all ML-KEM parameter sets
|
While looking further at the StAX side after the rebase, I noticed a coverage seam in the negative tests, including the two I just parameterized, and verified the actual inbound behavior locally on this branch. The StAX negative tests do not exercise the StAX inbound handler. The two paths reject differently. I ran both failure cases through the real inbound path (
I assume the fake-key fallback is deliberate, since it mirrors the existing RSA key-transport behavior in the same handler and gives uniform timing. Two thoughts on it:
Either way, it seems worth pinning the inbound behavior with negative tests so a future refactor cannot silently turn "wrong key" into "successful decrypt". Happy to contribute those in the same parameterized shape as the merged ones: wrong-key and truncated-ciphertext driven through The signature split has the same seam (its StAX tests verify through the DOM engine rather than |
Hi @Arpan0995 , Yes, please add tests in terms of this. Thanks!
|
Adds ML-KEM-512/768/1024 key transport via the W3C "XML Security: Generic Hybrid Cipher" structure, on both the DOM and STAX encryption paths. Part of the post-quantum work tracked under SANTUARIO-634 (originally proposed in SANTUARIO-633 / #645), split out here as the encryption-only half per community request.
Adds negative-test coverage on both the DOM and STAX paths: decryption with the wrong recipient's ML-KEM private key fails cleanly, and a truncated EncryptedKey CipherValue is rejected via the existing length check in KeyUtils#kemDecapsulate. Added per Arpan0995's review feedback on #645.