The Hybrid Public Key Encryption (HPKE) standard in Python

Overview

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)

Comments
  • Add RFC Test Vectors Suite

    Add RFC Test Vectors Suite

    CAPE-835

    Ensures comprehensive testing of correctness against the HPKE RFC's Test Vectors.

    api changes:

    • breaking: renames hybrid_pke.default_config -> hybrid_pke.default
    • refactors Hpke.key_schedule to pass default kwargs of None for psk & psk_id params

    internal/dev stuff:

    • decomposes the existing hybrid_pke_test.py into several different files in the tests/ module
    • adds a bit of work to stop copying Hpke everytime we implicitly use it from PyHpke
    • adds a requirements-dev file to specify dev dependencies, update the Makefile targets accordingly
    opened by jvmncs 0
  • Add HPKE Context and related context export methods

    Add HPKE Context and related context export methods

    CAPE-815

    allows us to do repeated encryption/decryption with an HPKE encryption, like so:

    encap, sender_context = hpke.setup_sender(pkR, info)
    receiver_context = hpke.setup_receiver(encap, skR, info)
    for _ in range(17):
        ctxt = sender_context.seal(aad, ptxt)
        ptxt_onetrip = receiver_context.open(aad, ctxt)
        assert ptxt == ptxt_onetrip
    

    also adds support for export contexts via Hpke.send_export, Hpke.receiver_export, Hpke.key_schedule, and Context.export

    opened by jvmncs 0
  • Swap out hpke-spec for hpke-rs

    Swap out hpke-spec for hpke-rs

    CAPE-820

    • rewrites all of the existing functionality to use hpke-rs as our rust backend.
    • breaking change: rename the python library to hybrid_pke
    • breaking change: renames hpke_open -> open and hpke_seal -> seal
    • breaking change: hpke-rs puts the functions generate_key_pair, open, and seal directly on the Hpke configuration struct, so in Python-land these are no longer pure functions but rather instance methods on the python class binding to Hpke
    • breaking change: expands the signatures of open/seal to include info, aad, and optional psk, psk_id, and pk_s/sk_r
    • exposes the underlying hpke_rs::HpkeError enum as a set of custom python Exceptions through PyO3, which significantly improves the experience of handling Rust errors from Python
    opened by jvmncs 0
  • Add gh action for multi-platform CI

    Add gh action for multi-platform CI

    CI checks installation and tests the python binding for python3.{8,9,10} on {manylinux x86_64, windows x86, macos x86_64, macos universal2}. also uploads wheels to be used in a later PR for releases

    opened by jvmncs 0
  • Make HpkeCrypto implementation configurable in Python package

    Make HpkeCrypto implementation configurable in Python package

    Currently, the HpkeCrypto implementation is fixed to Rust Crypto (e.g. here). It would be better if we could make this configurable (at least when building from source)

    opened by jvmncs 0
  • Dis-allow `borrow_deref_ref` with new PyO3 release

    Dis-allow `borrow_deref_ref` with new PyO3 release

    Per the following issues, there is a problem with PyO3's pyfunction macro triggering a faulty warning in clippy:

    • https://github.com/rust-lang/rust-clippy/issues/8971
    • https://github.com/PyO3/pyo3/pull/2503

    In #21 we force allow-ed the faulty warning. The PyO3 PR merges a fix, but it has not yet made it's way into a release. Once a new version of PyO3 has been published, we should revert the lint change we did in #21 by dis-allowing the lint warning for borrow_deref_ref.

    opened by jvmncs 0
Releases(v1.0.0)
Owner
Cape Privacy
Confidential Computing by Default
Cape Privacy
Rust encryption library for practical time-lock encryption.

tlock_age: Hybrid Timelock Encryption/Decryption in Rust tlock_age is a library to encrypt and decrypt age filekey using tlock scheme. It provides an

Thibault 5 Mar 29, 2023
Dfinity's fungible token standard. Any PRs and comments are welcome,collaborate with us to build this standard

Dfinity's fungible token standard. Any PRs and comments are welcome,collaborate with us to build this standard

Deland Labs 46 Nov 7, 2022
Manage secret values in-repo via public key cryptography

amber Manage secret values in-repo via public key cryptography. See the announcement blog post for more motivation. Amber provides the ability to secu

FP Complete 82 Nov 10, 2022
Project Masterpass is a deterministic databaseless key management algorithm, aimed to help those who cannot protect their encryption keys in storage

Project Masterpass (working title) Attention! This project is still under heavy development, and SHOULD NOT be used in practice, as the algorithms cou

Gyorgy Wang 2 Sep 11, 2022
The Nervos CKB is a public permissionless blockchain, and the layer 1 of Nervos network.

Nervos CKB - The Common Knowledge Base master develop About CKB CKB is the layer 1 of Nervos Network, a public/permissionless blockchain. CKB uses Pro

Nervos Network 1k Dec 30, 2022
The public source and documentation for Xenon iOS tweak.

THE GUIDE HAS BEEN MOVED TO THE WIKI This is the public source for the Xenon iOS tweak. The full version is available for $1.99 on Chariz. Differences

aspen 1 Dec 28, 2022
Zei is a library that provide tools to create and verify public transaction with confidential data.

#Zei: Findora's Cryptographic Library Zei is a library that provide tools to create and verify public transaction with confidential data. Support: Bas

Findora Foundation 0 Oct 23, 2022
Composable proof transcripts for public-coin arguments of knowledge

Merlin: composable proof transcripts for public-coin arguments of knowledge Merlin is a STROBE-based transcript construction for zero-knowledge proofs

dalek cryptography 99 Dec 22, 2022
Rust crate to retrieve public IP address and geolocation data. πŸ¦€

?? Public IP Address Lookup and Geolocation Information public-ip-address is a simple Rust library for performing public IP lookups from over a dozen

Tomash Ghz 6 Apr 25, 2024
rabe is an Attribute Based Encryption library, written in Rust

Rabe rabe is a rust library implementing several Attribute Based Encryption (ABE) schemes using a modified version of the bn library of zcash (type-3

Fraunhofer AISEC 52 Dec 15, 2022
WebAssembly wrapper of the rage encryption library

rage-wasm: WebAssembly wrapper of rage rage is a simple, modern, and secure file encryption tool, using the age format. It features small explicit key

Kan-Ru Chen 35 Dec 16, 2022
A Rust library for lattice-based additive homomorphic encryption.

Cupcake Cupcake is an efficient Rust library for the (additive version of) Fan-Vercauteren homomorphic encryption scheme, offering capabilities to enc

Facebook Research 365 Dec 11, 2022
A Rust binary for file encryption to multiple participants.

Kaspa-miner A Rust binary for file encryption to multiple participants. Installation From Sources With Rust's package manager cargo, you can install k

Elichai Turkel 31 Dec 30, 2022
End-to-end encryption and mutual authentication for distributed applications.

✨ Hands-on Introduction: Build end-to-end encrypted, mutually-authenticated, secure messaging in Rust ✨ Rust and Elixir libraries for end-to-end encry

Ockam | Trust for Data-in-Motion 2.8k Jan 2, 2023
Meta-repository for Miscreant: misuse-resistant symmetric encryption library with AES-SIV (RFC 5297) and AES-PMAC-SIV support

The best crypto you've never heard of, brought to you by Phil Rogaway A misuse resistant symmetric encryption library designed to support authenticate

miscreant. 480 Dec 8, 2022
A Rust Library of China's Standards of Encryption Algorithms (SM2/3/4)

Libsm Libsm is an open source pure rust library of China Cryptographic Algorithm Standards. It is completed by a collaborative effort between the Cryp

CITAHub 149 Dec 23, 2022
In addition to encryption library, pure RUST implementation of SSH-2.0 client protocol

In addition to encryption library, pure RUST implementation of SSH-2.0 client protocol

ι™ˆεΉ΄ζ—§δΊ‹γ€‚ 73 Jan 1, 2023
A secure file encryption utility, written in rust.

Dexios Dexios What is it? Building notes Checksums Performance Output file sizes Environment Variables Key Inputs Usage Examples To Do What is it? Dex

brxken 156 Dec 22, 2022
DexiosGUI - Simple cross-platform drag-and-drop Dexios file encryption

DexiosGUI Simple cross-platform drag-and-drop Dexios file encryption. Latest Windows x64 release is here. DexiosGUI is a Qt/C++ app for encrypt and de

Fabrice Corraire 4 Jul 25, 2022