capeprivacy / hybrid-pke

The Hybrid Public Key Encryption (HPKE) standard in Python

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Hybrid PKE

The Hybrid Public Key Encryption (HPKE) standard in Python.

hybrid_pke = hpke-rs PyO3

This library provides Python bindings to the hpke-rs crate, which supports primitives from either Rust Crypto or EverCrypt.

Table of Contents
  1. Usage
  2. Features
  3. Installation
  4. Development
  5. Related Projects

Usage

Basic

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!

Advanced

Sender & Receiver Contexts

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
Mode.AUTH: Authenticated Sender

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)
Mode.PSK: Pre-shared Key Authentication

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)
Mode.AUTH_PSK: Combining AUTH and PSK.

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,
)

(back to top)

Features

The features available match those supported by hpke-rs.

HPKE Modes
  • mode_base
  • mode_psk
  • mode_auth
  • mode_auth_psk
KEMs: (Diffie-Hellman) Key Encapsulation Mechanisms
  • 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 Additional Data functions
  • AES-128-GCM
  • AES-256-GCM
  • ChaCha20Poly1305
  • Export only

(back to top)

Installation

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.

(back to top)

Development

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.

Some useful tips
  • 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.
  • The -i/--interpreter flag for maturin can be used to swap out different Python interpreters, if you have multiple Python installations.

(back to top)

Related Projects

(back to top)

About

The Hybrid Public Key Encryption (HPKE) standard in Python

License:Apache License 2.0


Languages

Language:Rust 56.4%Language:Python 41.0%Language:Makefile 2.6%