LukaJCB/ts-mls
GitHub: LukaJCB/ts-mls
一个基于 TypeScript 的 MLS(RFC 9420)协议完整实现,支持多种密码套件和后量子算法,适用于浏览器、Node.js 和 Serverless 环境。
Stars: 91 | Forks: 16
# ts-mls:一个 TypeScript MLS (Messaging Layer Security - RFC 9420) 实现
[](https://github.com/LukaJCB/ts-mls/actions/workflows/ci.yml) [](https://badge.fury.io/js/ts-mls) [](https://coveralls.io/github/LukaJCB/ts-mls?branch=main)
Messaging Layer Security (RFC 9420, MLS) 的 TypeScript 实现。
本项目旨在完整实现 [RFC 9420](https://datatracker.ietf.org/doc/html/rfc9420),并侧重于不可变性和类型安全。它适用于浏览器、Node.js 或 Serverless 环境,并支持最近标准化的 Post Quantum 公钥算法 (FIPS-203, FIPS-204) 以及结合了 X25519 和 ML-KEM 的 X-Wing 混合 KEM。
## 安装
```
# npm
npm install ts-mls
# yarn
yarn add ts-mls
# pnpm
pnpm add ts-mls
```
本项目目前只有一个依赖项,即 `@hpke/core`。但是,为了支持不同的 Ciphersuite,您可能需要安装其他库。例如,要使用 `MLS_128_DHKEMP256_AES128GCM_SHA256_P256` Ciphersuite,您还必须安装 `@noble/curves`:
```
# npm
npm install @noble/curves
# yarn
yarn add @noble/curves
# pnpm
pnpm add @noble/curves
```
请参阅下表,了解每个 Ciphersuite 需要安装哪些额外的依赖项。
## 支持的 Ciphersuite
支持以下密码套件:
| KEM | AEAD | KDF | Hash | Signature | Name | ID | Dependencies |
| ------------------------ | ---------------- | ----------- | ------- | --------- | --------------------------------------------------- | ------ | ------------------------------------------------------- |
| DHKEM-X25519-HKDF-SHA256 | AES128GCM | HKDF-SHA256 | SHA-256 | Ed25519 | MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519 | 1 | |
| DHKEM-P256-HKDF-SHA256 | AES128GCM | HKDF-SHA256 | SHA-256 | P256 | MLS_128_DHKEMP256_AES128GCM_SHA256_P256 | 2 | @noble/curves |
| DHKEM-X25519-HKDF-SHA256 | CHACHA20POLY1305 | HKDF-SHA256 | SHA-256 | Ed25519 | MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519 | 3 | @hpke/chacha20poly1305 |
| DHKEM-X448-HKDF-SHA512 | AES256GCM | HKDF-SHA512 | SHA-512 | Ed448 | MLS_256_DHKEMX448_AES256GCM_SHA512_Ed448 | 4 | @noble/curves, @hpke/dhkem-x448 |
| DHKEM-P521-HKDF-SHA512 | AES256GCM | HKDF-SHA512 | SHA-512 | P521 | MLS_256_DHKEMP521_AES256GCM_SHA512_P521 | 5 | @noble/curves |
| DHKEM-X448-HKDF-SHA512 | CHACHA20POLY1305 | HKDF-SHA512 | SHA-512 | Ed448 | MLS_256_DHKEMX448_CHACHA20POLY1305_SHA512_Ed448 | 6 | @hpke/chacha20poly1305, @noble/curves, @hpke/dhkem-x448 |
| DHKEM-P384-HKDF-SHA384 | AES256GCM | HKDF-SHA384 | SHA-384 | P384 | MLS_256_DHKEMP384_AES256GCM_SHA384_P384 | 7 | @noble/curves |
| ML-KEM-512 | AES128GCM | HKDF-SHA256 | SHA-256 | Ed25519 | MLS_128_MLKEM512_AES128GCM_SHA256_Ed25519 | 0xf007 | @hpke/ml-kem |
| ML-KEM-512 | CHACHA20POLY1305 | HKDF-SHA256 | SHA-256 | Ed25519 | MLS_128_MLKEM512_CHACHA20POLY1305_SHA256_Ed25519 | 0xf008 | @hpke/ml-kem, @hpke/chacha20poly1305 |
| ML-KEM-768 | AES256GCM | HKDF-SHA384 | SHA-384 | Ed25519 | MLS_256_MLKEM768_AES256GCM_SHA384_Ed25519 | 0xf009 | @hpke/ml-kem |
| ML-KEM-768 | CHACHA20POLY1305 | HKDF-SHA384 | SHA-384 | Ed25519 | MLS_256_MLKEM768_CHACHA20POLY1305_SHA384_Ed25519 | 0xf00a | @hpke/ml-kem, @hpke/chacha20poly1305 |
| ML-KEM-1024 | AES256GCM | HKDF-SHA512 | SHA-512 | Ed25519 | MLS_256_MLKEM1024_AES256GCM_SHA512_Ed25519 | 0xf00b | @hpke/ml-kem |
| ML-KEM-1024 | CHACHA20POLY1305 | HKDF-SHA512 | SHA-512 | Ed25519 | MLS_256_MLKEM1024_CHACHA20POLY1305_SHA512_Ed25519 | 0xf00c | @hpke/ml-kem, @hpke/chacha20poly1305 |
| X-Wing | AES256GCM | HKDF-SHA512 | SHA-512 | Ed25519 | MLS_256_XWING_AES256GCM_SHA512_Ed25519 | 0xf00d | @hpke/ml-kem, @noble/curves |
| X-Wing | CHACHA20POLY1305 | HKDF-SHA512 | SHA-512 | Ed25519 | MLS_256_XWING_CHACHA20POLY1305_SHA512_Ed25519 | 0xf00e | @hpke/ml-kem, @hpke/chacha20poly1305, @noble/curves |
| ML-KEM-1024 | AES256GCM | HKDF-SHA512 | SHA-512 | ML-DSA-87 | MLS_256_MLKEM1024_AES256GCM_SHA512_MLDSA87 | 0xf00f | @hpke/ml-kem |
| ML-KEM-1024 | CHACHA20POLY1305 | HKDF-SHA512 | SHA-512 | ML-DSA-87 | MLS_256_MLKEM1024_CHACHA20POLY1305_SHA512_MLDSA87 | 0xf010 | @hpke/ml-kem, @hpke/chacha20poly1305 |
| X-Wing | AES256GCM | HKDF-SHA512 | SHA-512 | ML-DSA-87 | MLS_256_XWING_AES256GCM_SHA512_MLDSA87 | 0xf011 | @hpke/ml-kem, @noble/curves |
| X-Wing | CHACHA20POLY1305 | HKDF-SHA512 | SHA-512 | ML-DSA-87 | MLS_256_XWING_CHACHA20POLY1305_SHA512_MLDSA87 | 0xf012 | @hpke/ml-kem, @hpke/chacha20poly1305, @noble/curves |
## ⚠️ 安全免责声明
本库尚未经过正式的安全审计。尽管我们已经谨慎地实现正确且安全的 MLS 协议,但它可能包含未发现的漏洞。如果您计划在生产或安全关键型环境中使用本库,请谨慎行事,并考虑进行独立的安全审查。
## 基本用法
```
import {
createApplicationMessage,
createCommit,
createGroup,
defaultProposalTypes,
defaultCredentialTypes,
joinGroup,
processMessage,
getCiphersuiteImpl,
Credential,
defaultCapabilities,
defaultLifetime,
generateKeyPackage,
MlsContext,
encode,
decode,
mlsMessageEncoder,
mlsMessageDecoder,
protocolVersions,
unsafeTestingAuthenticationService,
wireformats,
Proposal,
zeroOutUint8Array,
} from "ts-mls"
const impl = await getCiphersuiteImpl("MLS_256_XWING_AES256GCM_SHA512_Ed25519")
const context: MlsContext = {
cipherSuite: impl,
authService: unsafeTestingAuthenticationService,
}
// alice generates her key package
const aliceCredential: Credential = {
credentialType: defaultCredentialTypes.basic,
identity: new TextEncoder().encode("alice"),
}
const alice = await generateKeyPackage({ credential: aliceCredential, cipherSuite: impl })
const groupId = new TextEncoder().encode("group1")
// alice creates a new group
let aliceGroup = await createGroup({
context,
groupId,
keyPackage: alice.publicPackage,
privateKeyPackage: alice.privatePackage,
})
// bob generates his key package
const bobCredential: Credential = {
credentialType: defaultCredentialTypes.basic,
identity: new TextEncoder().encode("bob"),
}
const bob = await generateKeyPackage({ credential: bobCredential, cipherSuite: impl })
// bob sends keyPackage to alice
const keyPackageMessage = encode(mlsMessageEncoder, {
keyPackage: bob.publicPackage,
wireformat: wireformats.mls_key_package,
version: protocolVersions.mls10,
})
// alice decodes bob's keyPackage
const decodedKeyPackage = decode(mlsMessageDecoder, keyPackageMessage)!
if (decodedKeyPackage.wireformat !== wireformats.mls_key_package) throw new Error("Expected key package")
// alice creates proposal to add bob
const addBobProposal: Proposal = {
proposalType: defaultProposalTypes.add,
add: {
keyPackage: decodedKeyPackage.keyPackage,
},
}
// alice commits
const commitResult = await createCommit({
context,
state: aliceGroup,
extraProposals: [addBobProposal],
})
aliceGroup = commitResult.newState
// alice deletes the keys used to encrypt the commit message
commitResult.consumed.forEach(zeroOutUint8Array)
// alice sends welcome message to bob
const encodedWelcome = encode(mlsMessageEncoder, commitResult.welcome!)
// bob decodes the welcome message
const decodedWelcome = decode(mlsMessageDecoder, encodedWelcome)!
if (decodedWelcome.wireformat !== wireformats.mls_welcome) throw new Error("Expected welcome")
// bob creates his own group state
let bobGroup = await joinGroup({
context,
welcome: decodedWelcome.welcome,
keyPackage: bob.publicPackage,
privateKeys: bob.privatePackage,
ratchetTree: aliceGroup.ratchetTree,
})
const messageToBob = new TextEncoder().encode("Hello bob!")
// alice creates a message to the group
const aliceCreateMessageResult = await createApplicationMessage({
context,
state: aliceGroup,
message: messageToBob,
})
aliceGroup = aliceCreateMessageResult.newState
// alice deletes the keys used to encrypt the application message
aliceCreateMessageResult.consumed.forEach(zeroOutUint8Array)
// alice sends the message to bob
const encodedPrivateMessageAlice = encode(mlsMessageEncoder, aliceCreateMessageResult.message)
// bob decodes the message
const decodedPrivateMessageAlice = decode(mlsMessageDecoder, encodedPrivateMessageAlice)!
if (decodedPrivateMessageAlice.wireformat !== wireformats.mls_private_message)
throw new Error("Expected private message")
// bob receives the message
const bobProcessMessageResult = await processMessage({
context,
state: bobGroup,
message: decodedPrivateMessageAlice,
})
bobGroup = bobProcessMessageResult.newState
if (bobProcessMessageResult.kind === "newState") throw new Error("Expected application message")
// bob deletes the keys used to decrypt the application message
bobProcessMessageResult.consumed.forEach(zeroOutUint8Array)
console.log(bobProcessMessageResult.message)
```
## 文档
请访问 [/docs 目录](docs#readme) 获取有关不同场景的更多文档。
## 贡献
我们欢迎您的贡献!请阅读我们的 [CONTRIBUTING.md](CONTRIBUTING.md),以获取有关如何设置您的环境、运行检查和提交更改的指南。
# 许可证
[MIT](LICENSE)
标签:E2EE, FIPS-203, FIPS-204, GNU通用公共许可证, HPKE, MITM代理, ML-KEM, MLS, Node.js, npm包, Post-Quantum, RFC 9420, Serverless, TypeScript, X25519, X-Wing混合KEM, 加密算法, 后端开发, 安全插件, 安全通信, 密码学, 手动系统调用, 抗量子密码学, 浏览器, 消息层安全, 端到端加密, 网络安全, 网络安全, 隐私保护, 隐私保护