npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lib-q/hpke

v0.0.6

Published

Post-quantum HPKE (RFC 9180) for Node.js

Readme

lib-q-hpke

RFC 9180–aligned Hybrid Public Key Encryption using post-quantum-only primitives (ML-KEM family for the HPKE KEM role in the default provider path; no classical KEM or classical signatures in that path).

Overview

lib-q-hpke implements HPKE for the lib-q stack: protocol logic and types in this crate, with KEM/AEAD/hash work delegated through lib-q-kem, lib-q-aead, and lib-q-hash. The high-level HpkeContext holds a lib_q_core::CryptoProvider for KemContext and an Arc<dyn HpkeCryptoProvider + Send + Sync> (default PostQuantumProvider) for encapsulation, KDF, AEAD, and exporter operations. Use HpkeContext::with_hpke_crypto to swap the HPKE backend; with_provider only replaces the inner KemContext crypto. Today the default provider wires ML-KEM only for HPKE KEM (other PQ KEMs may exist in the workspace but are not in the HpkeKem catalog yet).

Interoperability

Profiles, a mode×suite matrix, and fixture provenance are documented under the workspace interoperability.md and hpke-architecture.md. For code, see lib_q_hpke::interop. Run the integrator-oriented example (requires std):

cargo run -p lib-q-hpke --example hpke_interop_negotiation --features std

Supported Algorithms

Key Encapsulation Mechanisms (KEM)

  • ML-KEM-512 (Level 1 security)
  • ML-KEM-768 (Level 3 security)
  • ML-KEM-1024 (Level 5 security)

Key Derivation Functions (KDF)

  • HKDF-SHAKE128
  • HKDF-SHAKE256
  • HKDF-SHA3-256
  • HKDF-SHA3-512

Authenticated Encryption (AEAD)

  • Saturnin-256 (32-byte key, 16-byte nonce, 32-byte tag)
  • SHAKE256-based AEAD (16-byte tag)
  • Keccak duplex-sponge AEAD via lib-q-aead — enable Cargo feature duplex-sponge-aead on this crate (when using the umbrella lib-q crate, enable hpke-duplex-aead)
  • Export-only mode (HpkeAead::Export) for exporter-secret usage without message encryption

Quick Start

use lib_q_core::{Algorithm, KemContext, KemPublicKey, KemSecretKey};
use lib_q_hpke::HpkeContext;
use libq::LibQCryptoProvider;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create HPKE context (umbrella `lib-q` crate, Rust name `libq`)
    let provider = Box::new(LibQCryptoProvider::new()?);
    let mut hpke_ctx = HpkeContext::with_provider(provider);
    
    // Generate key pair
    let mut kem_ctx = KemContext::with_provider(Box::new(LibQCryptoProvider::new()?));
    let keypair = kem_ctx.generate_keypair(Algorithm::MlKem512)?;
    let recipient_pk = KemPublicKey::new(keypair.public_key().as_bytes().to_vec());
    let recipient_sk = KemSecretKey::new(keypair.secret_key().as_bytes().to_vec());
    
    // Encrypt message
    let message = b"Hello, HPKE!";
    let (encapsulated_key, ciphertext) = hpke_ctx.seal(
        &recipient_pk,
        b"application-info",
        b"additional-data",
        message,
    )?;
    
    // Decrypt message
    let decrypted = hpke_ctx.open(
        &encapsulated_key,
        &recipient_sk,
        b"application-info",
        b"additional-data",
        &ciphertext,
    )?;
    
    assert_eq!(decrypted, message);
    Ok(())
}

HPKE Modes

Base Mode

Standard HPKE without additional authentication.

let mut sender_ctx = hpke_ctx.setup_sender(&recipient_pk, b"session-info")?;
let ciphertext = sender_ctx.seal(b"aad", message)?;

PSK Mode

Pre-shared key authentication.

let psk = b"shared-secret-key";
let psk_id = b"psk-identifier";
let mut sender_ctx = hpke_ctx.setup_sender_psk(
    &recipient_pk,
    b"session-info",
    psk,
    psk_id,
)?;

Auth Mode

Sender authentication using asymmetric keys.

let mut sender_ctx = hpke_ctx.setup_sender_auth(
    &recipient_pk,
    b"session-info",
    &sender_sk,
    &sender_pk,
)?;

AuthPSK Mode

Combined PSK and sender authentication.

let mut sender_ctx = hpke_ctx.setup_sender_auth_psk(
    &recipient_pk,
    b"session-info",
    psk,
    psk_id,
    &sender_sk,
    &sender_pk,
)?;

PSK / AuthPSK wire format

For PSK and AuthPSK modes, the default is HpkePskWireFormat::Rfc9180 (RFC 9180 on-the-wire layout). Both peers may set HpkePskWireFormat::LibQCommitmentSuffix with HpkeContext::set_psk_wire_format to reject wrong (psk, psk_id) or a mismatched primary KEM ciphertext before decapsulation; that suffix is not interoperable with strict third-party RFC 9180 implementations.

Cargo features (summary)

| Feature | Purpose | |---------|---------| | std | Standard library support | | alloc | Required for normal operation (enforced by the crate) | | ml-kem | ML-KEM through lib-q-kem (default) | | hash | HKDF hash backends via lib-q-hash (default) | | saturnin / shake256 | AEAD algorithms (defaults) | | duplex-sponge-aead | Duplex-sponge AEAD in HpkeAead::DuplexSpongeAead | | wasm | wasm32 bindings and helpers | | secure-rng | OS-backed RNG where applicable (default) |

See Cargo.toml for the full feature matrix and optional dev dependencies.

Documentation

Testing

The implementation includes comprehensive test coverage:

# Run all tests
cargo test

# Run specific test suites
cargo test --test psk_mode_comprehensive_tests
cargo test --test authpsk_mode_comprehensive_tests
cargo test --test security_validation_comprehensive_tests

Wire sizes (KEM)

Public key and encapsulated ciphertext lengths match HpkeKem (public_key_len / enc_len):

| KEM | NIST category (approx.) | Public key | Encapsulated ciphertext | |-----|-------------------------|------------|-------------------------| | ML-KEM-512 | 1 | 800 B | 768 B | | ML-KEM-768 | 3 | 1184 B | 1088 B | | ML-KEM-1024 | 5 | 1568 B | 1568 B |

AEAD ciphertext expansion is plaintext length plus the AEAD tag (e.g. 32 bytes for Saturnin-256); see HpkeAead::tag_len in src/types.rs.

Dependencies

  • lib-q-core - Core cryptographic types and interfaces
  • lib-q-kem - Key encapsulation mechanism implementations
  • lib-q-hash - Hash function implementations
  • lib-q-aead - Authenticated encryption implementations
  • lib-q (Rust import libq) — LibQCryptoProvider for demos; production integrations may use narrower providers

License

This project is licensed under the same terms as the lib-q project.

Subresource integrity (SHA-384)

Paths in integrity-manifest.json are relative to the package root (including web/ and nodejs/ when both ship).