ts-mls
Version:
[](https://github.com/LukaJCB/ts-mls/actions/workflows/ci.yml) [](https://badge.fury.io/js/ts-mls) [ => [msg.groupId, msg.epoch, msg.contentType, msg.authenticatedData, msg.encryptedSenderData, msg.ciphertext]);
export const decodePrivateMessage = mapDecoders([decodeVarLenData, decodeUint64, decodeContentType, decodeVarLenData, decodeVarLenData, decodeVarLenData], (groupId, epoch, contentType, authenticatedData, encryptedSenderData, ciphertext) => ({
groupId,
epoch,
contentType,
authenticatedData,
encryptedSenderData,
ciphertext,
}));
export const encodePrivateContentAAD = contramapEncoders([encodeVarLenData, encodeUint64, encodeContentType, encodeVarLenData], (aad) => [aad.groupId, aad.epoch, aad.contentType, aad.authenticatedData]);
export const decodePrivateContentAAD = mapDecoders([decodeVarLenData, decodeUint64, decodeContentType, decodeVarLenData], (groupId, epoch, contentType, authenticatedData) => ({
groupId,
epoch,
contentType,
authenticatedData,
}));
export function decodePrivateMessageContent(contentType) {
switch (contentType) {
case "application":
return decoderWithPadding(mapDecoders([decodeVarLenData, decodeVarLenData], (applicationData, signature) => ({
contentType,
applicationData,
auth: { contentType, signature },
})));
case "proposal":
return decoderWithPadding(mapDecoders([decodeProposal, decodeVarLenData], (proposal, signature) => ({
contentType,
proposal,
auth: { contentType, signature },
})));
case "commit":
return decoderWithPadding(mapDecoders([decodeCommit, decodeVarLenData, decodeFramedContentAuthDataCommit], (commit, signature, auth) => ({
contentType,
commit,
auth: { ...auth, signature, contentType },
})));
}
}
export function encodePrivateMessageContent(config) {
return (msg) => {
switch (msg.contentType) {
case "application":
return encoderWithPadding(contramapEncoders([encodeVarLenData, encodeFramedContentAuthData], (m) => [m.applicationData, m.auth]), config)(msg);
case "proposal":
return encoderWithPadding(contramapEncoders([encodeProposal, encodeFramedContentAuthData], (m) => [m.proposal, m.auth]), config)(msg);
case "commit":
return encoderWithPadding(contramapEncoders([encodeCommit, encodeFramedContentAuthData], (m) => [m.commit, m.auth]), config)(msg);
}
};
}
export async function decryptSenderData(msg, senderDataSecret, cs) {
const key = await expandSenderDataKey(cs, senderDataSecret, msg.ciphertext);
const nonce = await expandSenderDataNonce(cs, senderDataSecret, msg.ciphertext);
const aad = {
groupId: msg.groupId,
epoch: msg.epoch,
contentType: msg.contentType,
};
const decrypted = await cs.hpke.decryptAead(key, nonce, encodeSenderDataAAD(aad), msg.encryptedSenderData);
return decodeSenderData(decrypted, 0)?.[0];
}
export async function encryptSenderData(senderDataSecret, senderData, aad, ciphertext, cs) {
const key = await expandSenderDataKey(cs, senderDataSecret, ciphertext);
const nonce = await expandSenderDataNonce(cs, senderDataSecret, ciphertext);
return await cs.hpke.encryptAead(key, nonce, encodeSenderDataAAD(aad), encodeSenderData(senderData));
}
export function toAuthenticatedContent(content, msg, senderLeafIndex) {
return {
wireformat: "mls_private_message",
content: {
groupId: msg.groupId,
epoch: msg.epoch,
sender: {
senderType: "member",
leafIndex: senderLeafIndex,
},
authenticatedData: msg.authenticatedData,
...content,
},
auth: content.auth,
};
}
function encoderWithPadding(encoder, config) {
return (t) => {
const encoded = encoder(t);
const result = new Uint8Array(encoded.length + byteLengthToPad(encoded.length, config));
result.set(encoded, 0);
return result;
};
}
function decoderWithPadding(decoder) {
return (bytes, offset) => {
const result = decoder(bytes, offset);
if (result === undefined)
return undefined;
const [decoded, innerOffset] = result;
const paddingBytes = bytes.subarray(offset + innerOffset, bytes.length);
const allZeroes = paddingBytes.every((byte) => byte === 0);
if (!allZeroes)
return undefined;
return [decoded, bytes.length];
};
}
//# sourceMappingURL=privateMessage.js.map