Score:3

How does JOSE/JWE make use of ECDH when encrypting/decrypting messages?

bg flag

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.

Maarten Bodewes avatar
in flag
Yes, this is about the usage of algorithms and as such it should be a better fit here. Of course there will be plenty of people on [security.se] that can answer, but in general this kind of question belongs here.
Score:2
in flag

You are talking about IES or ECIES in the context of Elliptic Curves. The way it works is that there is a static key pair of the receiver, for which the public key first needs to be trusted by the sender. The sender then creates it's own ephemeral key pair, which is used to perform the key agreement that underlies the protocol.

As the key pair is ephemeral the private key is only used once during the call to encrypt, after which it is destroyed. The way that this is normally programmed is that the private key is a field of the JWEEncrypter instance. It doesn't need to be exported as it only needs to exist until the data encryption key is calculated. As such it is hidden from the user.

That leaves the public key. Normally the user of the library would have to handle that as programmer by attaching it to the encrypted message. However, JWE is a container format. So it doesn't produce just a ciphertext, it wraps it into a structure from which the ephemeral public key can be retrieved. You can find the header specification that contains that key in the RFC. So it is hidden from the user as well.

As the receiver does keep the static private key, it can derive the same symmetric key using the public key that is in the container format. Once the same symmetric data key is derived the contents within the container can be decrypted.


It may be surprising, but key encapsulation using RSA-OAEP and key agreement using ECIES can use the exact same number of messages. Of course there are differences: the encapsulated key must be sent for RSA-OAEP instead of sending the ephemeral public key in case of ECIES, but for a high level API, all things may well look the same.

ceaaj avatar
bg flag
Thanks, things are clearer now. "As the sender does keep the static private key" - I think you meant receiver? Btw. I assume the ephemeral key pair of the sender is for increased security because no static key pair has to be maintained. On the other hand, for systems with high throughput of single messages, it sounds quite expensive for the sender having to create a key pair (plus optionally generate another symmetric key when used with key-wrap) for every single message. Do you know of any other commonly used container formats that support ecc with a static key pair on the sender's side?
ceaaj avatar
bg flag
(It's meant for end-to-end encryption of messages between two parties. The communication protocol is HTTPS, however, the whole route is longer than just the request, so TLS alone is not enough.)
Maarten Bodewes avatar
in flag
Yes, that was a brainfart, sorry, adjusted the private key sender to receiver. RSA has very long key generation times, but for EC with a known curve, the creation of a private key is basically generation of a random secret of the key size, and a point multiplication (which you would also do for e.g. signing) or key agreement.
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.