Python HPKE Implementation
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
- gotcha The PyHPKE library has not undergone a formal security audit. Users should perform their own risk assessment before deploying it in production environments, especially for sensitive data.
- breaking Support for Python 3.8 was dropped in PyHPKE version 0.6.0. Users on Python 3.8 or older must upgrade their Python environment or use an earlier PyHPKE version (e.g., <0.6.0).
- gotcha Cryptographic libraries require careful key management. Ensure private keys are stored securely, never hardcoded, and access is strictly controlled. Avoid nonce reuse for AEAD modes, as it can lead to severe security vulnerabilities.
Install
-
pip install pyhpke
Imports
- CipherSuite
from pyhpke import CipherSuite
- KEMKey
from pyhpke import KEMKey
- KEMId
from pyhpke import KEMId
- KDFId
from pyhpke import KDFId
- AEADId
from pyhpke import AEADId
Quickstart
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