Python HPKE Implementation

0.6.4 · active · verified Sat Apr 11

PyHPKE is a Python implementation of HPKE (Hybrid Public Key Encryption), providing mechanisms for authenticated encryption with associated data. It supports all HPKE modes and cipher suites defined in RFC9180. The library is currently at version 0.6.4 and maintains a regular release cadence with frequent minor updates and dependency bumps.

Warnings

Install

Imports

Quickstart

This example demonstrates a basic HPKE 'Base' mode encryption and decryption flow. A sender creates a context using the recipient's public key, encapsulates a symmetric key, and seals a plaintext message. The recipient uses the encapsulated key and their private key to open the ciphertext.

from pyhpke import CipherSuite, KEMKey, KEMId, KDFId, AEADId

# --- Sender Side ---
# Define the HPKE cipher suite
suite_s = CipherSuite.new(
    KEMId.DHKEM_X25519_HKDF_SHA256,
    KDFId.HKDF_SHA256,
    AEADId.AES128_GCM
)

# Recipient's public key (example PEM format)
public_key_pem = b"""-----BEGIN PUBLIC KEY-----
MCowBQYDK2VuAyEAoMfvlI5DN08JRFP2fhWvZ6vBEl28yFeS9O9YQUjNyCY=
-----END PUBLIC KEY-----"""
pkr = KEMKey.from_pem(public_key_pem)

# Create sender context and encapsulate key
enc, sender = suite_s.create_sender_context(pkr)

# Seal the message
plaintext = b"Hello world!"
ciphertext = sender.seal(plaintext)

print(f"Encapsulated Key: {enc.hex()}")
print(f"Ciphertext: {ciphertext.hex()}")

# --- Recipient Side ---
# Define the same HPKE cipher suite
suite_r = CipherSuite.new(
    KEMId.DHKEM_X25519_HKDF_SHA256,
    KDFId.HKDF_SHA256,
    AEADId.AES128_GCM
)

# Recipient's private key (example PEM format, corresponding to public_key_pem)
private_key_pem = b"""-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VuBCIEIMAXvyHjAeXy9x4MXF6rwGbDKw7crgDriFTFXO+XsS1F
-----END PRIVATE KEY-----"""
skr = KEMKey.from_pem(private_key_pem)

# Create recipient context and decapsulate key (using 'enc' from sender)
recipient = suite_r.create_recipient_context(enc, skr)

# Open the message
decrypted_text = recipient.open(ciphertext)

print(f"Decrypted Text: {decrypted_text.decode()}")
assert decrypted_text == plaintext

view raw JSON →