Skip to main content
Deno 2 is finally here πŸŽ‰οΈ
Learn more

hpke-js

Stable Release

A TypeScript Hybrid Public Key Encryption (HPKE) implementation build on top of Web Cryptography API. This library works for both browser-based applications and node.js based applications.

Index

Supported Features

HPKE Modes

Modes Browser Node.js
Base βœ… βœ…
PSK βœ… βœ…
Auth βœ… βœ…
AuthPSK

Key Encapsulation Machanisms (KEMs)

KEMs Browser Node.js
DHKEM (P-256, HKDF-SHA256) βœ… βœ…
DHKEM (P-384, HKDF-SHA384) βœ… βœ…
DHKEM (P-521, HKDF-SHA512) βœ… βœ…
DHKEM (X25519, HKDF-SHA256)
DHKEM (X448, HKDF-SHA512)

Key Derivation Functions (KDFs)

KDFs Browser Node.js
HKDF-SHA256 βœ… βœ…
HKDF-SHA384 βœ… βœ…
HKDF-SHA512 βœ… βœ…

Authenticated Encryption with Associated Data (AEAD) Functions

AEADs Browser Node.js
AES-128-GCM βœ… βœ…
AES-256-GCM βœ… βœ…
ChaCha20Poly1305
Export Only βœ… βœ…

Installation

Install with npm:

npm install hpke

Usage

This section shows some typical usage examples. See API Documentation for details.

Base mode

On browser:

// The global name is "hpke".

// setup
const suite = new hpke.CipherSuite({
  kem: hpke.Kem.DhkemP256HkdfSha256,
  kdf: hpke.Kdf.HkdfSha256,
  aead: hpke.Aead.Aes128Gcm
});

const rkp = await suite.generateKeyPair();

const sender = await suite.createSenderContext({
  recipientPublicKey: rkp.publicKey
});

const recipient = await suite.createRecipientContext({
  recipientKey: rkp,
  enc: sender.enc,
});

// encrypt
const ct = await sender.seal(new TextEncoder().encode("my-secret-message"));

// decrypt
const pt = await recipient.open(ct);

// new TextDecoder().decode(pt) === "my-secret-message"

PSK mode

On browser:

// The global name is "hpke".

// setup
const suite = new hpke.CipherSuite({
  kem: hpke.Kem.DhkemP256HkdfSha256,
  kdf: hpke.Kdf.HkdfSha256,
  aead: hpke.Aead.Aes128Gcm
});

const rkp = await suite.generateKeyPair();

const sender = await suite.createSenderContext({
  recipientPublicKey: rkp.publicKey,
  psk: {
    id: new TextEncoder().encode("our-pre-shared-key-id"),
    key: new TextEncoder().encode("our-pre-shared-key"),
  }
});

const recipient = await suite.createRecipientContext({
  recipientKey: rkp,
  enc: sender.enc,
  psk: {
    id: new TextEncoder().encode("our-pre-shared-key-id"),
    key: new TextEncoder().encode("our-pre-shared-key"),
  }
});

// encrypt
const ct = await sender.seal(new TextEncoder().encode("my-secret-message"));

// decrypt
const pt = await recipient.open(ct);

// new TextDecoder().decode(pt) === "my-secret-message"

Auth mode

On browser:

// The global name is "hpke".

// setup
const suite = new hpke.CipherSuite({
  kem: hpke.Kem.DhkemP256HkdfSha256,
  kdf: hpke.Kdf.HkdfSha256,
  aead: hpke.Aead.Aes128Gcm
});

const rkp = await suite.generateKeyPair();
const skp = await suite.generateKeyPair();

const sender = await suite.createSenderContext({
  recipientPublicKey: rkp.publicKey,
  senderKey: skp
});

const recipient = await suite.createRecipientContext({
  recipientKey: rkp,
  enc: sender.enc,
  senderPublicKey: skp.publicKey
});

// encrypt
const ct = await sender.seal(new TextEncoder().encode("my-secret-message"));

// decrypt
const pt = await recipient.open(ct);

// new TextDecoder().decode(pt) === "my-secret-message"

AuthPSK mode

On browser:

// The global name is "hpke".

// setup
const suite = new hpke.CipherSuite({
  kem: hpke.Kem.DhkemP256HkdfSha256,
  kdf: hpke.Kdf.HkdfSha256,
  aead: hpke.Aead.Aes128Gcm
});

const rkp = await suite.generateKeyPair();
const skp = await suite.generateKeyPair();

const sender = await suite.createSenderContext({
  recipientPublicKey: rkp.publicKey,
  senderKey: skp,
  psk: {
    id: new TextEncoder().encode("our-pre-shared-key-id"),
    key: new TextEncoder().encode("our-pre-shared-key"),
  }
});

const recipient = await suite.createRecipientContext({
  recipientKey: rkp,
  enc: sender.enc,
  senderPublicKey: skp.publicKey,
  psk: {
    id: new TextEncoder().encode("our-pre-shared-key-id"),
    key: new TextEncoder().encode("our-pre-shared-key"),
  }
});

// encrypt
const ct = await sender.seal(new TextEncoder().encode("my-secret-message"));

// decrypt
const pt = await recipient.open(ct);

// new TextDecoder().decode(pt) === "my-secret-message"

Contributing

We welcome all kind of contributions, filing issues, suggesting new features or sending PRs.

References