Hybrid Encryption

The Hybrid Encryption primitive combines the efficiency of symmetric encryption with the convenience of public key (asymmetric) cryptography. Anyone can encrypt data using the public key, but only users with the private key can decrypt the data.

For Hybrid Encryption, the sender generates a fresh symmetric key to encrypt the plaintext of each message to produce a ciphertext. That symmetric key is encapsulated with the recipient's public key. For Hybrid Decryption, the symmetric key is decapsulated by the recipient and then used to decrypt the ciphertext to recover the original plaintext. See Tink Hybrid Encryption wire format for details on how to store or transmit the ciphertext along with the key encapsulation.

Hybrid Encryption has the following properties:

  • Secrecy: No one is able to get any information about the encrypted plaintext (except the length), unless they have access to the private key.
  • Asymmetry: Encrypting the ciphertext can be done with the public key, but for decryption, the private key is required.
  • Randomization: The encryption is randomized. Two messages with the same plaintext will not yield the same ciphertext. This prevents attackers from knowing which ciphertext corresponds to a given plaintext.

Hybrid Encryption is represented in Tink as a pair of primitives:

  • HybridEncrypt for encryption
  • HybridDecrypt for decryption

Context info parameter

In addition to the plaintext, Hybrid Encryption accepts an extra parameter, context_info, which is usually public data implicit from the context, but should be bound to the resulting ciphertext. This means that the ciphertext allows you to confirm the integrity of the context info but there are no guarantees for its secrecy or authenticity. The actual context info can be empty or null, but to ensure the correct decryption of the resulting ciphertext, the same context info value must be provided for decryption.

A concrete implementation of Hybrid Encryption can bind context info to the ciphertext in various ways, for example:

  • Use context_info as associated data input for AEAD symmetric encryption (cf. RFC 5116).
  • Use context_info as “CtxInfo" input for HKDF (if the implementation uses HKDF as key derivation function, cf. RFC 5869).

Choose a key type

We recommend using the DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM key type for most use cases. This key type implements the Hybrid Public Key Encryption (HPKE) standard as specified in RFC 9180. HPKE consists of a key encapsulation mechanism (KEM), a key derivation function (KDF), and an authenticated encryption with associated data (AEAD) algorithm.

DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM specifically employs:

  • KEM: Diffie–Hellman over Curve25519 with HKDF-SHA-256 to derive the shared secret.
  • KDF: HKDF-SHA-256 to derive the sender and receiver context.
  • AEAD: AES-256-GCM with 12-byte nonces generated according to the HPKE standard.

Other supported HPKE key types include, but are not limited to, the following:

  • DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM
  • DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305
  • DHKEM_P256_HKDF_SHA256_HKDF_SHA256_AES_128_GCM
  • DHKEM_P521_HKDF_SHA512_HKDF_SHA512_AES_256_GCM

See RFC 9180 for more details on the algorithm choices for the KEM, KDF, and AEAD.

Although no longer recommended, Tink also supports some variations of ECIES as described in Victor Shoup's ISO 18033-2 standard. Some supported ECIES key types are listed below:

  • ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM
  • ECIES_P256_COMPRESSED_HKDF_HMAC_SHA256_AES128_GCM
  • ECIES_P256_HKDF_HMAC_SHA256_AES128_CTR_HMAC_SHA256
  • ECIES_P256_COMPRESSED_HKDF_HMAC_SHA256_AES128_CTR_HMAC_SHA256

Minimal properties

  • Plaintext and context info can have arbitrary length (within the range 0..232 bytes)
  • Secure against adaptive chosen ciphertext attacks
  • 128-bit security for elliptic curve based schemes

Example use cases

See I want to exchange data.