hpke-js
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.