hpke-js
Version:
A Hybrid Public Key Encryption (HPKE) module for various JavaScript runtimes
194 lines (193 loc) • 8.34 kB
JavaScript
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "@hpke/core", "@hpke/chacha20poly1305", "@hpke/dhkem-x25519", "@hpke/dhkem-x448", "./kdfs/hkdfSha384.js", "./kems/dhkemP256.js", "./kems/dhkemP384.js", "./kems/dhkemP521.js"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CipherSuite = void 0;
const core_1 = require("@hpke/core");
const chacha20poly1305_1 = require("@hpke/chacha20poly1305");
const dhkem_x25519_1 = require("@hpke/dhkem-x25519");
const dhkem_x448_1 = require("@hpke/dhkem-x448");
const hkdfSha384_js_1 = require("./kdfs/hkdfSha384.js");
const dhkemP256_js_1 = require("./kems/dhkemP256.js");
const dhkemP384_js_1 = require("./kems/dhkemP384.js");
const dhkemP521_js_1 = require("./kems/dhkemP521.js");
/**
* The Hybrid Public Key Encryption (HPKE) ciphersuite,
* which supports all of the ciphersuites defined in
* {@link https://datatracker.ietf.org/doc/html/rfc9180 | RFC9180}.
*
* The class consists of the {@link https://jsr.io/@hpke/core/doc | @hpke/core},
* {@link https://jsr.io/@hpke/chacha20Poly1305/doc | @hpke/chcha20poly1305},
* {@link https://jsr.io/@hpke/dhkem-x25519/doc | @hpke/dhkem-x25519} and
* {@link https://jsr.io/@hpke/dhkem-x448/doc | @hpke/dhkem-x448} internally.
*
* This class provides following functions:
*
* - [DEPRECATED] Generates a key pair for the cipher suite.
* - [DEPRECATED] Derives a key pair for the cipher suite.
* - [DEPRECATED] Imports and converts a key to a CryptoKey.
* - Creates encryption contexts both for senders and recipients.
* - {@link createSenderContext}
* - {@link createRecipientContext}
* - Provides single-shot encryption API.
* - {@link seal}
* - {@link open}
*
* The calling of the constructor of this class is the starting
* point for HPKE operations for both senders and recipients.
*
* @example Use only ciphersuites supported internally.
*
* ```ts
* import { AeadId, CipherSuite, KdfId, KemId } from "@hpke/hpke-js";
*
* const suite = new CipherSuite({
* kem: KemId.DhkemP256HkdfSha256,
* kdf: KdfId.HkdfSha256,
* aead: AeadId.Aes128Gcm,
* });
* ```
*
* @example Use a ciphersuite consisting of an external module.
*
* ```ts
* import { AeadId, CipherSuite, KdfId } from "@hpke/hpke-js";
* // Use an extension module.
* import {
* HybridkemX25519Kyber768,
* } from "@hpke/hybridkem-x25519-kyber768";
*
* const suite = new CipherSuite({
* kem: new HybridkemX25519Kyber768(),
* kdf: KdfId.HkdfSha256,
* aead: AeadId.Aes128Gcm,
* });
* ```
*/
class CipherSuite extends core_1.CipherSuite {
/**
* @param params A set of parameters for building a cipher suite.
* @throws {@link InvalidParamError}
*/
constructor(params) {
// KEM
if (typeof params.kem === "number") {
switch (params.kem) {
case core_1.KemId.DhkemP256HkdfSha256:
params.kem = new dhkemP256_js_1.DhkemP256HkdfSha256();
break;
case core_1.KemId.DhkemP384HkdfSha384:
params.kem = new dhkemP384_js_1.DhkemP384HkdfSha384();
break;
case core_1.KemId.DhkemP521HkdfSha512:
params.kem = new dhkemP521_js_1.DhkemP521HkdfSha512();
break;
case core_1.KemId.DhkemX25519HkdfSha256:
params.kem = new dhkem_x25519_1.DhkemX25519HkdfSha256();
break;
case core_1.KemId.DhkemX448HkdfSha512:
params.kem = new dhkem_x448_1.DhkemX448HkdfSha512();
break;
default:
throw new core_1.InvalidParamError(`The KEM (${params.kem}) cannot be specified by KemId. Use submodule for the KEM`);
}
}
// KDF
if (typeof params.kdf === "number") {
switch (params.kdf) {
case core_1.KdfId.HkdfSha256:
params.kdf = new dhkem_x25519_1.HkdfSha256();
break;
case core_1.KdfId.HkdfSha384:
params.kdf = new hkdfSha384_js_1.HkdfSha384();
break;
default:
// case KdfId.HkdfSha512:
params.kdf = new dhkem_x448_1.HkdfSha512();
break;
}
}
// AEAD
if (typeof params.aead === "number") {
switch (params.aead) {
case core_1.AeadId.Aes128Gcm:
params.aead = new core_1.Aes128Gcm();
break;
case core_1.AeadId.Aes256Gcm:
params.aead = new core_1.Aes256Gcm();
break;
case core_1.AeadId.Chacha20Poly1305:
params.aead = new chacha20poly1305_1.Chacha20Poly1305();
break;
default:
// case AeadId.ExportOnly:
params.aead = new core_1.ExportOnly();
break;
}
}
super(params);
}
/**
* Generates a key pair for the cipher suite.
*
* If the error occurred, throws {@link NotSupportedError}.
*
* @deprecated Use {@link KemInterface.generateKeyPair} instead.
*
* @returns A key pair generated.
* @throws {@link NotSupportedError}
*/
async generateKeyPair() {
await this._setup();
return await this._kem.generateKeyPair();
}
/**
* Derives a key pair for the cipher suite in the manner
* defined in [RFC9180 Section 7.1.3](https://www.rfc-editor.org/rfc/rfc9180.html#section-7.1.3).
*
* If the error occurred, throws {@link DeriveKeyPairError}.
*
* @deprecated Use {@link KemInterface.deriveKeyPair} instead.
*
* @param ikm A byte string of input keying material. The maximum length is 128 bytes.
* @returns A key pair derived.
* @throws {@link DeriveKeyPairError}
*/
async deriveKeyPair(ikm) {
await this._setup();
return await this._kem.deriveKeyPair(ikm);
}
/**
* Imports a public or private key and converts to a {@link CryptoKey}.
*
* Since key parameters for {@link createSenderContext} or {@link createRecipientContext}
* are {@link CryptoKey} format, you have to use this function to convert provided keys
* to {@link CryptoKey}.
*
* Basically, this is a thin wrapper function of
* [SubtleCrypto.importKey](https://www.w3.org/TR/WebCryptoAPI/#dfn-SubtleCrypto-method-importKey).
*
* If the error occurred, throws {@link DeserializeError}.
*
* @deprecated Use {@link KemInterface.generateKeyPair} instead.
*
* @param format For now, `'raw'` and `'jwk'` are supported.
* @param key A byte string of a raw key or A {@link JsonWebKey} object.
* @param isPublic The indicator whether the provided key is a public key or not, which is used only for `'raw'` format.
* @returns A public or private CryptoKey.
* @throws {@link DeserializeError}
*/
async importKey(format, key, isPublic = true) {
await this._setup();
return await this._kem.importKey(format, key, isPublic);
}
}
exports.CipherSuite = CipherSuite;
});