UNPKG

ts-mls

Version:

[![CI](https://github.com/LukaJCB/ts-mls/actions/workflows/ci.yml/badge.svg)](https://github.com/LukaJCB/ts-mls/actions/workflows/ci.yml) [![npm version](https://badge.fury.io/js/ts-mls.svg)](https://badge.fury.io/js/ts-mls) [![Coverage Status](https://co

109 lines 4.83 kB
import { CipherSuite } from "@hpke/core"; import { makeAead } from "./aead"; import { makeKdf } from "./kdf"; import { makeDhKem } from "./kem"; import { encodeVarLenData } from "../codec/variableLength"; import { bytesToBuffer } from "../util/byteArray"; import { CryptoError } from "../mlsError"; export function encryptWithLabel(publicKey, label, context, plaintext, hpke) { return hpke.seal(publicKey, plaintext, new Uint8Array([...encodeVarLenData(new TextEncoder().encode(`MLS 1.0 ${label}`)), ...encodeVarLenData(context)]), new Uint8Array()); } export function decryptWithLabel(privateKey, label, context, kemOutput, ciphertext, hpke) { return hpke.open(privateKey, kemOutput, ciphertext, new Uint8Array([...encodeVarLenData(new TextEncoder().encode(`MLS 1.0 ${label}`)), ...encodeVarLenData(context)])); } export async function makeHpke(hpkealg) { const aead = await makeAead(hpkealg.aead); const cs = new CipherSuite({ kem: await makeDhKem(hpkealg.kem), kdf: makeKdf(hpkealg.kdf), aead: aead.hpkeInterface(), }); return { async open(privateKey, kemOutput, ciphertext, info, aad) { try { const result = await cs.open({ recipientKey: privateKey, enc: bytesToBuffer(kemOutput), info: bytesToBuffer(info) }, bytesToBuffer(ciphertext), aad ? bytesToBuffer(aad) : new ArrayBuffer()); return new Uint8Array(result); } catch (e) { throw new CryptoError(`${e}`); } }, async seal(publicKey, plaintext, info, aad) { const result = await cs.seal({ recipientPublicKey: publicKey, info: bytesToBuffer(info) }, bytesToBuffer(plaintext), aad ? bytesToBuffer(aad) : new ArrayBuffer()); return { ct: new Uint8Array(result.ct), enc: new Uint8Array(result.enc), }; }, async exportSecret(publicKey, exporterContext, length, info) { const context = await cs.createSenderContext({ recipientPublicKey: publicKey, info: bytesToBuffer(info) }); return { enc: new Uint8Array(context.enc), secret: new Uint8Array(await context.export(bytesToBuffer(exporterContext), length)), }; }, async importSecret(privateKey, exporterContext, kemOutput, length, info) { try { const context = await cs.createRecipientContext({ recipientKey: privateKey, info: bytesToBuffer(info), enc: bytesToBuffer(kemOutput), }); return new Uint8Array(await context.export(bytesToBuffer(exporterContext), length)); } catch (e) { throw new CryptoError(`${e}`); } }, async importPrivateKey(k) { try { // See https://github.com/mlswg/mls-implementations/issues/176#issuecomment-1817043142 const key = hpkealg.kem === "DHKEM-P521-HKDF-SHA512" ? prepadPrivateKeyP521(k) : k; return (await cs.kem.deserializePrivateKey(bytesToBuffer(key))); } catch (e) { throw new CryptoError(`${e}`); } }, async importPublicKey(k) { try { return (await cs.kem.deserializePublicKey(bytesToBuffer(k))); } catch (e) { throw new CryptoError(`${e}`); } }, async exportPublicKey(k) { return new Uint8Array(await cs.kem.serializePublicKey(k)); }, async exportPrivateKey(k) { return new Uint8Array(await cs.kem.serializePrivateKey(k)); }, async encryptAead(key, nonce, aad, plaintext) { return aead.encrypt(key, nonce, aad ? aad : new Uint8Array(), plaintext); }, async decryptAead(key, nonce, aad, ciphertext) { try { return await aead.decrypt(key, nonce, aad ? aad : new Uint8Array(), ciphertext); } catch (e) { throw new CryptoError(`${e}`); } }, async deriveKeyPair(ikm) { const kp = await cs.kem.deriveKeyPair(bytesToBuffer(ikm)); return { privateKey: kp.privateKey, publicKey: kp.publicKey }; }, async generateKeyPair() { const kp = await cs.kem.generateKeyPair(); return { privateKey: kp.privateKey, publicKey: kp.publicKey }; }, keyLength: cs.aead.keySize, nonceLength: cs.aead.nonceSize, }; } function prepadPrivateKeyP521(k) { const lengthDifference = 66 - k.byteLength; return new Uint8Array([...new Uint8Array(lengthDifference), ...k]); } //# sourceMappingURL=hpke.js.map