PyHPKE - A Python implementation of HPKE
PyHPKE is a HPKE (Hybrid Public Key Encryption) implementation written in Python.
You can install PyHPKE with pip:
$ pip install pyhpke
And then, you can use it as follows:
from pyhpke import AEADId, CipherSuite, KDFId, KEMId, KEMKey
# The sender side:
suite_s = CipherSuite.new(
KEMId.DHKEM_P256_HKDF_SHA256, KDFId.HKDF_SHA256, AEADId.AES128_GCM
)
pkr = KEMKey.from_jwk( # from_pem is also available.
{
"kid": "01",
"kty": "EC",
"crv": "P-256",
"x": "Ze2loSV3wrroKUN_4zhwGhCqo3Xhu1td4QjeQ5wIVR0",
"y": "HlLtdXARY_f55A3fnzQbPcm6hgr34Mp8p-nuzQCE0Zw",
}
)
enc, sender = suite_s.create_sender_context(pkr)
ct = sender.seal(b"Hello world!")
# The recipient side:
suite_r = CipherSuite.new(
KEMId.DHKEM_P256_HKDF_SHA256, KDFId.HKDF_SHA256, AEADId.AES128_GCM
)
skr = KEMKey.from_jwk(
{
"kid": "01",
"kty": "EC",
"crv": "P-256",
"x": "Ze2loSV3wrroKUN_4zhwGhCqo3Xhu1td4QjeQ5wIVR0",
"y": "HlLtdXARY_f55A3fnzQbPcm6hgr34Mp8p-nuzQCE0Zw",
"d": "r_kHyZ-a06rmxM3yESK84r1otSg-aQcVStkRhA-iCM8",
}
)
recipient = suite_r.create_recipient_context(enc, skr)
pt = recipient.open(ct)
assert pt == b"Hello world!"
# deriving a KEMKeyPair
keypair = suite_s.kem.derive_key_pair(b"some_ikm_bytes_used_for_key_derivation")
Index
- Installation
- Supported HPKE Modes and Cipher Suites
- Warnings and Restrictions
- Usage
- API Reference
- Test
- Security
- Contributing
Installation
You can install PyHPKE with pip:
$ pip install pyhpke
Supported HPKE Modes and Cipher Suites
PyHPKE supports all of the HPKE modes and cipher suites defined in RFC9180 below.
- modes
- ✅ Base
- ✅ PSK
- ✅ Auth
- ✅ AuthPSK
- KEMs (Key Encapsulation Machanisms)
- ✅ DHKEM (P-256, HKDF-SHA256)
- ✅ DHKEM (P-384, HKDF-SHA384)
- ✅ DHKEM (P-521, HKDF-SHA512)
- ✅ DHKEM (X25519, HKDF-SHA256)
- ✅ DHKEM (X448, HKDF-SHA512)
- KDFs (Key Derivation Functions)
- ✅ HKDF-SHA256
- ✅ HKDF-SHA384
- ✅ HKDF-SHA512
- AEADs (Authenticated Encryption with Associated Data)
- ✅ AES-128-GCM
- ✅ AES-256-GCM
- ✅ ChaCha20Poly1305
- ✅ Export Only
Warnings and Restrictions
Although this library has been passed all of the following official test vectors, it has not been formally audited.
Usage
from pyhpke import AEADId, CipherSuite, KDFId, KEMId, KEMKey
# The sender side:
suite_s = CipherSuite.new(
KEMId.DHKEM_P256_HKDF_SHA256, KDFId.HKDF_SHA256, AEADId.AES128_GCM
)
pkr = KEMKey.from_jwk(
{
"kid": "01",
"kty": "EC",
"crv": "P-256",
"x": "Ze2loSV3wrroKUN_4zhwGhCqo3Xhu1td4QjeQ5wIVR0",
"y": "HlLtdXARY_f55A3fnzQbPcm6hgr34Mp8p-nuzQCE0Zw",
}
)
enc, sender = suite_s.create_sender_context(pkr)
ct = sender.seal(b"Hello world!")
# The recipient side:
suite_r = CipherSuite.new(
KEMId.DHKEM_P256_HKDF_SHA256, KDFId.HKDF_SHA256, AEADId.AES128_GCM
)
skr = KEMKey.from_jwk(
{
"kid": "01",
"kty": "EC",
"crv": "P-256",
"x": "Ze2loSV3wrroKUN_4zhwGhCqo3Xhu1td4QjeQ5wIVR0",
"y": "HlLtdXARY_f55A3fnzQbPcm6hgr34Mp8p-nuzQCE0Zw",
"d": "r_kHyZ-a06rmxM3yESK84r1otSg-aQcVStkRhA-iCM8",
}
)
recipient = suite_r.create_recipient_context(enc, skr)
pt = recipient.open(ct)
assert pt == b"Hello world!"
API Reference
See Documentation.
Test
You can run tests from the project root after cloning with:
$ tox
Security
If you discover a security issue, please report it via a GitHub issue and avoid disclosing exploit details publicly until we respond.
This project has not been formally audited; use it according to your risk assessment.
The Snyk badge reports results based on requirements.txt exported from uv.lock and reflects dependency scanning only.
See SECURITY.md for our security policy and reporting guidance.
Contributing
We welcome all kind of contributions, filing issues, suggesting new features or sending PRs.
Development environment
$ uv sync --frozen
$ uv run pre-commit install
Dependency updates
[tool.uv] in pyproject.toml pins exclude-newer = "2 days", so resolution only
considers packages uploaded more than two days ago. This gives newly published
releases a verification window before we depend on them, and it applies to every
uv command automatically — no extra flags needed.
After changing dependencies, re-export requirements.txt, which is what the
dependency scanners read:
$ uv add <package> # or: uv lock --upgrade
$ uv export --format requirements-txt --locked -o requirements.txt
Scanning
$ uv run pip-audit
$ uv run pip-licenses
$ trivy fs --severity HIGH,CRITICAL .
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyhpke-0.6.5.tar.gz.
File metadata
- Download URL: pyhpke-0.6.5.tar.gz
- Upload date:
- Size: 1.6 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8dac22eb143cd83b8066213b8ad0ecc9d5326ef41f930197197f3bbb5c99cb93
|
|
| MD5 |
722b2fb5c8f334bd4fe737564198cc5b
|
|
| BLAKE2b-256 |
bd81692a67c409e0a81423941791f875313e7ebcf1493180363eec8051acc767
|
Provenance
The following attestation bundles were made for pyhpke-0.6.5.tar.gz:
Publisher:
cd.yml on dajiaji/pyhpke
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyhpke-0.6.5.tar.gz -
Subject digest:
8dac22eb143cd83b8066213b8ad0ecc9d5326ef41f930197197f3bbb5c99cb93 - Sigstore transparency entry: 2179317441
- Sigstore integration time:
-
Permalink:
dajiaji/pyhpke@7f3c9cba66132295b62412459c3e037ac0e6063e -
Branch / Tag:
refs/tags/v0.6.5 - Owner: https://github.com/dajiaji
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
cd.yml@7f3c9cba66132295b62412459c3e037ac0e6063e -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyhpke-0.6.5-py3-none-any.whl.
File metadata
- Download URL: pyhpke-0.6.5-py3-none-any.whl
- Upload date:
- Size: 24.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e8d794724e43053fe04e8971be55033225d6da904effc748b303cece763a3f3c
|
|
| MD5 |
0721a61eaaaac12bcb37951907a13ac5
|
|
| BLAKE2b-256 |
04312a0edff785b15d700199fed77186b3d070724cafd02fccfffb187e450d83
|
Provenance
The following attestation bundles were made for pyhpke-0.6.5-py3-none-any.whl:
Publisher:
cd.yml on dajiaji/pyhpke
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyhpke-0.6.5-py3-none-any.whl -
Subject digest:
e8d794724e43053fe04e8971be55033225d6da904effc748b303cece763a3f3c - Sigstore transparency entry: 2179317473
- Sigstore integration time:
-
Permalink:
dajiaji/pyhpke@7f3c9cba66132295b62412459c3e037ac0e6063e -
Branch / Tag:
refs/tags/v0.6.5 - Owner: https://github.com/dajiaji
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
cd.yml@7f3c9cba66132295b62412459c3e037ac0e6063e -
Trigger Event:
release
-
Statement type: