Disclaimer: I first posted this question on security.stackexchange some minutes ago but deleted it, this is probably a better place for it.
My goal is to use JWE with hybrid encryption (ECDH+AES) for exchanging sensitive data with another party. However, the example code I can find for various Java libraries doesn't match my understanding of how ECDH or asymmetric encryption with EC works in general, which seems to be different to e.g. a hybrid approach with RSA+AES.
My understanding of typical hybrid encryption with RSA and AES:
Sender:
- create an AES content encryption key (CEK) / session key
- encrypt the message payload with the CEK
- encrypt the CEK with the recipient's public RSA key
- send both the encrypted CEK as well as the encrypted message to the recipient
Recipient:
- Decrypts the RSA-encrypted CEK with the recipient's private key
- Decrypts the AES-encrypted message with that CEK
So in theory, it's not even necessary for the sender to have its own key pair, as long as there is no signing involved.
My understanding of how the same is done when using ECDH and AES:
Sender:
- Derive the shared secret from the sender's EC private key and the recipient's EC public key
- use that shared secret directly as CEK for AES and encrypt the message (or generate a temporary CEK and encrypt it with the shared secret, a.k.a. keywrap)
- send the encrypted message to the sender (and optionally the encrypted CEK, in case of key-wrapping)
Recipient:
- Derive the shared secret from the sender's EC public key and the recipient's EC private key
- use the shared secret as CEK to AES-decrypt the message (or to decrypt the actual CEK when used with key-wrapping and decrypt the content afterward)
Regardless if it's about encryption or decryption, the derivation of the shared secret on both ends conceptually requires that there are 2 key pairs involved.
However, the code examples for common Java libraries (e.g. Nimbus JOSE) that I can find look like this:
ECKey pubKey = ECKey.parse("...");
JWEEncrypter encrypter = new ECDHEncrypter(pubKey);
JWEHeader header = new JWEHeader.Builder(JWEAlgorithm.ECDH_ES, EncryptionMethod.A256GCM).build();
String sensitive = "top secret message";
JWEObject jwe = new JWEObject(header, new Payload(sensitive));
jwe.encrypt(encrypter);
I'm not referring to the seemingly missing CEK/AES part, I suppose that's the library doing for me under the hood, but to the way, ECDH is used or not used. It's not just that there is no obvious association between two key pairs for obtaining the shared secret, but there is no second key pair involved altogether.
So either my understanding of ECDH is wrong, or I can't wrap my head around how ECDH is used in the context of JWEs.