hpke-js
A TypeScript Hybrid Public Key Encryption (HPKE)
implementation build on top of Web Cryptography API.
This library works on both web browsers and Node.js (currently, Deno is not supported).
Index
Supported Features
HPKE Modes
Modes | Browser | Node.js | Deno |
---|---|---|---|
Base | ✅ | ✅ | |
PSK | ✅ | ✅ | |
Auth | ✅ | ✅ | |
AuthPSK | ✅ | ✅ |
Key Encapsulation Machanisms (KEMs)
KEMs | Browser | Node.js | Deno |
---|---|---|---|
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 | Deno |
---|---|---|---|
HKDF-SHA256 | ✅ | ✅ | |
HKDF-SHA384 | ✅ | ✅ | |
HKDF-SHA512 | ✅ | ✅ |
Authenticated Encryption with Associated Data (AEAD) Functions
AEADs | Browser | Node.js | Deno |
---|---|---|---|
AES-128-GCM | ✅ | ✅ | |
AES-256-GCM | ✅ | ✅ | |
ChaCha20Poly1305 | |||
Export Only | ✅ | ✅ |
Installation
Install with npm:
npm install hpke-js
Usage
This section shows some typical usage examples.
Base mode
On Node.js:
const { Kem, Kdf, Aead, CipherSuite } = require("hpke-js");
async function doHpke() {
// setup
const suite = new CipherSuite({
kem: Kem.DhkemP256HkdfSha256,
kdf: Kdf.HkdfSha256,
aead: 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);
console.log("decrypted: ", new TextDecoder().decode(pt));
// decripted: my-secret-message
}
doHpke();
Base mode with Single-Shot APIs
On Node.js:
const { Kem, Kdf, Aead, CipherSuite } = require("hpke-js");
async function doHpke() {
// setup
const suite = new CipherSuite({
kem: Kem.DhkemP256HkdfSha256,
kdf: Kdf.HkdfSha256,
aead: Aead.Aes128Gcm
});
const rkp = await suite.generateKeyPair();
const pt = new TextEncoder().encode('my-secret-message'),
// encrypt
const { ct, enc } = await suite.seal({ recipientPublicKey: rkp.publicKey }, pt);
// decrypt
const pt = await suite.open({ recipientKey: rkp, enc: enc }, ct);
console.log("decrypted: ", new TextDecoder().decode(pt));
// decripted: my-secret-message
}
doHpke();
PSK mode
On Node.js:
const { Kem, Kdf, Aead, CipherSuite } = require("hpke-js");
async function doHpke() {
// setup
const suite = new CipherSuite({
kem: Kem.DhkemP256HkdfSha256,
kdf: Kdf.HkdfSha256,
aead: 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);
console.log("decrypted: ", new TextDecoder().decode(pt));
// decripted: my-secret-message
}
doHpke();
Auth mode
On Node.js:
const { Kem, Kdf, Aead, CipherSuite } = require("hpke-js");
async function doHpke() {
// setup
const suite = new CipherSuite({
kem: Kem.DhkemP256HkdfSha256,
kdf: Kdf.HkdfSha256,
aead: 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);
console.log("decrypted: ", new TextDecoder().decode(pt));
// decripted: my-secret-message
}
doHpke();
AuthPSK mode
On Node.js:
const { Kem, Kdf, Aead, CipherSuite } = require("hpke-js");
async function doHpke() {
// setup
const suite = new CipherSuite({
kem: Kem.DhkemP256HkdfSha256,
kdf: Kdf.HkdfSha256,
aead: 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);
console.log("decrypted: ", new TextDecoder().decode(pt));
// decripted: my-secret-message
}
doHpke();
Contributing
We welcome all kind of contributions, filing issues, suggesting new features or sending PRs.