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

46 lines 3.36 kB
import { mapDecoders } from "./codec/tlsDecoder.js"; import { contramapEncoders } from "./codec/tlsEncoder.js"; import { decodeVarLenData, decodeVarLenType, encodeVarLenData, encodeVarLenType } from "./codec/variableLength.js"; import { decodeCiphersuite, encodeCiphersuite } from "./crypto/ciphersuite.js"; import { encryptWithLabel, decryptWithLabel } from "./crypto/hpke.js"; import { expandWithLabel } from "./crypto/kdf.js"; import { decodeGroupInfo, encodeGroupInfo, extractWelcomeSecret } from "./groupInfo.js"; import { decodeGroupSecrets, encodeGroupSecrets } from "./groupSecrets.js"; import { encodeHpkeCiphertext, decodeHpkeCiphertext } from "./hpkeCiphertext.js"; import { ValidationError } from "./mlsError.js"; import { constantTimeEqual } from "./util/constantTimeCompare.js"; export const encodeEncryptedGroupSecrets = contramapEncoders([encodeVarLenData, encodeHpkeCiphertext], (egs) => [egs.newMember, egs.encryptedGroupSecrets]); export const decodeEncryptedGroupSecrets = mapDecoders([decodeVarLenData, decodeHpkeCiphertext], (newMember, encryptedGroupSecrets) => ({ newMember, encryptedGroupSecrets })); export const encodeWelcome = contramapEncoders([encodeCiphersuite, encodeVarLenType(encodeEncryptedGroupSecrets), encodeVarLenData], (welcome) => [welcome.cipherSuite, welcome.secrets, welcome.encryptedGroupInfo]); export const decodeWelcome = mapDecoders([decodeCiphersuite, decodeVarLenType(decodeEncryptedGroupSecrets), decodeVarLenData], (cipherSuite, secrets, encryptedGroupInfo) => ({ cipherSuite, secrets, encryptedGroupInfo })); export function welcomeNonce(welcomeSecret, cs) { return expandWithLabel(welcomeSecret, "nonce", new Uint8Array(), cs.hpke.nonceLength, cs.kdf); } export function welcomeKey(welcomeSecret, cs) { return expandWithLabel(welcomeSecret, "key", new Uint8Array(), cs.hpke.keyLength, cs.kdf); } export async function encryptGroupInfo(groupInfo, welcomeSecret, cs) { const key = await welcomeKey(welcomeSecret, cs); const nonce = await welcomeNonce(welcomeSecret, cs); const encrypted = await cs.hpke.encryptAead(key, nonce, undefined, encodeGroupInfo(groupInfo)); return encrypted; } export async function decryptGroupInfo(w, joinerSecret, pskSecret, cs) { const welcomeSecret = await extractWelcomeSecret(joinerSecret, pskSecret, cs.kdf); const key = await welcomeKey(welcomeSecret, cs); const nonce = await welcomeNonce(welcomeSecret, cs); const decrypted = await cs.hpke.decryptAead(key, nonce, undefined, w.encryptedGroupInfo); const decoded = decodeGroupInfo(decrypted, 0); return decoded?.[0]; } export function encryptGroupSecrets(initKey, encryptedGroupInfo, groupSecrets, hpke) { return encryptWithLabel(initKey, "Welcome", encryptedGroupInfo, encodeGroupSecrets(groupSecrets), hpke); } export async function decryptGroupSecrets(initPrivateKey, keyPackageRef, welcome, hpke) { const secret = welcome.secrets.find((s) => constantTimeEqual(s.newMember, keyPackageRef)); if (secret === undefined) throw new ValidationError("No matching secret found"); const decrypted = await decryptWithLabel(initPrivateKey, "Welcome", welcome.encryptedGroupInfo, secret.encryptedGroupSecrets.kemOutput, secret.encryptedGroupSecrets.ciphertext, hpke); return decodeGroupSecrets(decrypted, 0)?.[0]; } //# sourceMappingURL=welcome.js.map