Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
The Hybrid Public Key Encryption (HPKE) standard in Python.
hybrid_pke
= hpke-rs
:heavy_plus_sign: PyO3
This library provides Python bindings to the hpke-rs
crate, which supports primitives from either Rust Crypto or EverCrypt.
The single-shot API is intended for single message encryption/decryption. The default HPKE configuration uses the unauthenticated Base mode, an X25519 DH key encapsulation mechanism, a SHA256 key derivation mechanism, and a ChaCha20Poly1305 AEAD function.
import hybrid_pke
hpke = hybrid_pke.default()
info = b"" # shared metadata, correspondance-level
aad = b"" # shared metadata, message-level
secret_key_r, public_key_r = hpke.generate_key_pair() # receiver keys, pre-generated
# ============== Sender ==============
message = b"hello from the other side!"
encap, ciphertext = hpke.seal(public_key_r, info, aad, message)
# ============= Receiver =============
plaintext = hpke.open(encap, secret_key_r, info, aad, ciphertext)
print(plaintext.decode("utf-8"))
# >> hello from the other side!
The Sender Context and Receiver Context APIs allow for setting up a context for repeated encryptions and decryptions. It's recommended whenever you intend to perform several encryptions or decryptions in quick succession.
info = b"quotes from your favorite aphorists"
aads = [
b"Szasz",
b"Nietzsche",
b"Morandotti",
b"Brudzinski",
b"Hubbard",
]
# ============== Sender ==============
messages = [
b"Two wrongs don't make a right, but they make a good excuse.",
b"Become who you are!",
b"Only those who aren't hungry are able to judge the quality of a meal.",
b"Under certain circumstances a wanted poster is a letter of recommendation.",
b"Nobody ever forgets where he buried the hatchet.",
]
encap, sender_context = hpke.setup_sender(public_key_r, info)
ciphertexts = []
for aad, msg in zip(aads, messages):
ciphertext = sender_context.seal(aad, msg)
ciphertexts.append(ciphertext)
# ============= Receiver =============
receiver_context = hpke.setup_receiver(encap, secret_key_r, info)
plaintexts = []
for aad, ctxt in zip(aads, ciphertexts):
plaintext = receiver_context.open(aad, ctxt)
plaintexts.append(plaintext)
print(f"\"{plaintexts[0].decode()}\" - {aad[0].decode()}")
print(f"\"{plaintexts[1].decode()}\" - {aad[1].decode()}")
# >> "Two wrongs don't make a right, but they make a good excuse." - Szasz
# >> "Become who you are!" - Nietzsche
Auth mode allows for signing and verifying encryptions with a previously authenticated sender key-pair.
hpke = hybrid_pke.default(mode=hybrid_pke.Mode.AUTH)
secret_key_r, public_key_r = hpke.generate_key_pair() # receiver keys
secret_key_s, public_key_s = hpke.generate_key_pair() # sender keys, pre-authenticated
# ============== Sender ==============
# sign with sender's secret key
encap, ciphertext = hpke.seal(public_key_r, info, aad, message, sk_s=secret_key_s)
# ============= Receiver =============
# verify with sender's public key
plaintext = hpke.open(encap, secret_key_r, info, aad, ciphertext, pk_s=public_key_s)
PSK mode allows for signing and verifying encryptions with a previously shared key held by both the sender and recipient.
hpke = hybrid_pke.default(mode=hybrid_pke.Mode.PSK)
# pre-shared key + ID
psk = bytes.fromhex("0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82")
psk_id = bytes.fromhex("456e6e796e20447572696e206172616e204d6f726961")
# ============== Sender ==============
# sign with pre-shared key
encap, ciphertext = hpke.seal(public_key_r, info, aad, message, psk=psk, psk_id=psk_id)
# ============= Receiver =============
# verify with pre-shared key
plaintext = hpke.open(encap, secret_key_r, info, aad, ciphertext, psk=psk, psk_id=psk_id)
PSK mode allows for signing and verifying encryptions with a previously shared key held by both the sender and recipient.
hpke = hybrid_pke.default(mode=hybrid_pke.Mode.PSK)
secret_key_r, public_key_r = hpke.generate_key_pair() # receiver keys
secret_key_s, public_key_s = hpke.generate_key_pair() # sender keys, pre-authenticated
# pre-shared key + ID
psk = bytes.fromhex("0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82")
psk_id = bytes.fromhex("456e6e796e20447572696e206172616e204d6f726961")
# ============== Sender ==============
# sign with both pre-shared key and sender's secret key
encap, ciphertext = hpke.seal(
public_key_r, info, aad, message,
psk=psk, psk_id=psk_id, sk_s=secret_key_s,
)
# ============= Receiver =============
# verify with both pre-shared key and sender's public key
plaintext = hpke.open(
encap, secret_key_r, info, aad, ciphertext,
psk=psk, psk_id=psk_id, pk_s=public_key_s,
)
The features available match those supported by hpke-rs
.
Wheels for various platforms and architectures can be found on PyPI or in the wheelhouse.zip
archive from the latest Github release.
The library can also be installed from source with maturin
-- see below.
We use maturin
to build and distribute the PyO3 extension module as a Python wheel.
For users of cmake
, we provide a Makefile
that includes some helpful development commands.
maturin develop
builds & installs the Python package into your Python environment (venv
or conda
recommended)pytest .
tests the resulting Python package.pytest -n auto .
runs the full test suite in parallel.maturin build --release -o dist --sdist
builds the extension module in release-mode and produces a wheel for your environment's OS and architecture.-i
/--interpreter
flag for maturin
can be used to swap out different Python interpreters, if you have multiple Python installations.We use cargo-release
to manage release commits and git tags. Our versioning follows SemVer, and after every release we immediately bump to a prerelease version with the -dev0
suffix.
$ git checkout main
$ cargo release patch --execute
Upgrading hybrid_pke from X.X.X-dev0 to X.X.X
Replacing in pyproject.toml
--- pyproject.toml original
+++ pyproject.toml replaced
@@ -8 +8 @@
-version = "X.X.X-dev0" # NOTE: auto-updated during release
+version = "X.X.X" # NOTE: auto-updated during release
$ cargo release X.X.Y-dev0 --no-tag
Upgrading hybrid_pke from X.X.X to X.X.Y-dev0
Replacing in pyproject.toml
--- pyproject.toml original
+++ pyproject.toml replaced
@@ -8 +8 @@
-version = "X.X.X" # NOTE: auto-updated during release
+version = "X.X.Y-dev0" # NOTE: auto-updated during release
$ git push origin main
$ git push origin vX.X.X # triggers automatic release steps in CI
FAQs
The Hybrid Public Key Encryption (HPKE) standard in Python
We found that hybrid-pke demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.