sovereignbase/cryptosuite
GitHub: sovereignbase/cryptosuite
一个跨 JS/TS 运行时、默认后量子安全的密码学工具包,通过声明式 API 提供加密通信、签名、密钥协商等核心能力。
Stars: 0 | Forks: 0
[](https://www.npmjs.com/package/@sovereignbase/cryptosuite)
[](https://github.com/sovereignbase/cryptosuite/actions/workflows/ci.yaml)
[](https://codecov.io/gh/sovereignbase/cryptosuite)
[](LICENSE)
# cryptosuite
JS/TS 运行时无关、量子安全且敏捷的密码学工具包,提供声明式 API,用于密码消息传递、消息认证、数字签名、密钥协商和标识符。
## 兼容性
- 运行时:已在浏览器、bun、deno、node、edge-runtimes 上经过测试。
- 模块格式:ESM 或 CJS
- 必需的全局变量/API:`crypto`、`crypto.subtle`、`crypto.getRandomValues`
- 类型:捆绑的 `.d.ts`
## 目标
- 跨现代 JavaScript 和 TypeScript 环境的运行时无关性
- 默认具备后量子安全性
- 密码敏捷性,随着建议的演进,留有添加或替换算法的空间,同时保持已颁发密钥的向后兼容性
- 表达清晰密码学意图的声明式 API 接口
## 当前算法
- 标识符:`SHA-384` 或 48 个随机字节,编码为固定长度的 base64url 字符串
- 密码消息传递:`AES-GCM-256`
- 消息认证:`HMAC-SHA-256`
- 密钥协商:`X25519-ML-KEM-768`
- 数字签名:`Ed25519-ML-DSA-65`
## 安装
```
npm install @sovereignbase/cryptosuite
# 或
pnpm add @sovereignbase/cryptosuite
# 或
yarn add @sovereignbase/cryptosuite
# 或
bun add @sovereignbase/cryptosuite
# 或
deno add jsr:@sovereignbase/cryptosuite
# 或
vlt install jsr:@sovereignbase/cryptosuite
```
## 使用方法
### 标识符
```
import { Cryptographic } from '@sovereignbase/cryptosuite'
import { Bytes } from '@sovereignbase/bytecodec'
const discoveryHook = Bytes.fromString('resource discovery hook') // Uint8Array
const newResourceId = await Cryptographic.identifier.generate() // "64xb64urlchars..."
const discoveryId = await Cryptographic.identifier.derive(discoveryHook) // "64xb64urlchars..."
const ingressId = Cryptographic.identifier.validate(discoveryId) // "64xb64urlchars..." | false
```
### 密码消息
```
import { Cryptographic } from '@sovereignbase/cryptosuite'
import { Bytes } from '@sovereignbase/bytecodec'
const messageBytes = Bytes.fromString('hello world') // Uint8Array
const cipherKey = await Cryptographic.cipherMessage.generateKey() // JsonWebKey
const sourceKeyMaterial = Bytes.fromString('deterministic key source') // Uint8Array
const salt = Bytes.fromString('deterministic salt source') // Uint8Array
const { cipherKey } = await Cryptographic.cipherMessage.deriveKey(
sourceKeyMaterial,
{ salt }
) // {cipherKey: JsonWebKey, salt: Uint8Array}
const cipherMessage = await Cryptographic.cipherMessage.encrypt(
cipherKey,
messageBytes
) // {ciphertext: ArrayBuffer, iv: Uint8Array}
const roundtrip = await Cryptographic.cipherMessage.decrypt(
cipherKey,
cipherMessage
) // Uint8Array
const plainMessage = Bytes.toString(roundtrip) // 'hello world'
```
### 消息认证
```
import { Cryptographic } from '@sovereignbase/cryptosuite'
import { Bytes } from '@sovereignbase/bytecodec'
const messageBytes = Bytes.fromString('authenticated payload') // Uint8Array
const generatedMessageAuthenticationKey =
await Cryptographic.messageAuthentication.generateKey() // JsonWebKey
const sourceKeyMaterial = Bytes.fromString('deterministic key source') // Uint8Array
const salt = Bytes.fromString('deterministic salt source') // Uint8Array
const { messageAuthenticationKey } =
await Cryptographic.messageAuthentication.deriveKey(sourceKeyMaterial, {
salt,
}) // {messageAuthenticationKey: JsonWebKey, salt: Uint8Array}
const tag = await Cryptographic.messageAuthentication.sign(
generatedMessageAuthenticationKey,
messageBytes
) // ArrayBuffer
const verified = await Cryptographic.messageAuthentication.verify(
generatedMessageAuthenticationKey,
messageBytes,
tag
) // boolean
```
### 密钥协商
```
import { Cryptographic } from '@sovereignbase/cryptosuite'
import { Bytes } from '@sovereignbase/bytecodec'
const sourceKeyMaterial = Bytes.fromString('k'.repeat(32)) // Uint8Array, exactly 32 bytes
const { encapsulateKey, decapsulateKey } =
await Cryptographic.keyAgreement.generateKeypair() // {encapsulateKey: JsonWebKey, decapsulateKey: JsonWebKey}
const deterministicKeypair =
await Cryptographic.keyAgreement.deriveKeypair(sourceKeyMaterial) // {encapsulateKey: JsonWebKey, decapsulateKey: JsonWebKey}
const { keyOffer, cipherKey: senderCipherKey } =
await Cryptographic.keyAgreement.encapsulate(encapsulateKey) // {keyOffer: {ciphertext: ArrayBuffer}, cipherKey: JsonWebKey}
const { cipherKey: receiverCipherKey } =
await Cryptographic.keyAgreement.decapsulate(keyOffer, decapsulateKey) // {cipherKey: JsonWebKey}
```
### 数字签名
```
import { Cryptographic } from '@sovereignbase/cryptosuite'
import { Bytes } from '@sovereignbase/bytecodec'
const sourceKeyMaterial = Bytes.fromString('s'.repeat(64)) // Uint8Array, exactly 64 bytes
const bytes = Bytes.fromString('signed payload') // Uint8Array
const { signKey, verifyKey } =
await Cryptographic.digitalSignature.generateKeypair() // {signKey: JsonWebKey, verifyKey: JsonWebKey}
const deterministicKeypair =
await Cryptographic.digitalSignature.deriveKeypair(sourceKeyMaterial) // {signKey: JsonWebKey, verifyKey: JsonWebKey}
const signature = await Cryptographic.digitalSignature.sign(signKey, bytes) // Uint8Array
const verified = await Cryptographic.digitalSignature.verify(
verifyKey,
bytes,
signature
) // boolean
```
## 运行时行为
- `identifier.generate()` 需要 `crypto.getRandomValues`
- 对称操作使用 WebCrypto
- 密钥协商和数字签名使用 `noble` 混合原语
- 不支持的密码原语会抛出类型化的 `CryptosuiteError` 错误码
## 安全提示
- `AES-GCM` 为每个密文提供机密性和消息完整性
- 在协议层验证对等方和会话设置
- 切勿重复使用 `(key, iv)` 对
- 将 JWK 和派生密钥材料视为机密
- 签名应为规范的字节表示,而不是结构松散的对象
## 测试
最新一次本地 `npm run test` 运行于 `2026-04-17`,Node 版本为 `v22.14.0 (win32 x64)`:
- `65/65` 项测试通过
- 语句、分支、函数和行的覆盖率达到了 `100%`
- 端到端运行时套件全部通过,包括:
- Node ESM
- Node CJS
- Bun ESM
- Bun CJS
- Deno ESM
- Edge Runtime ESM
- Cloudflare Workers ESM
- Chromium
- Firefox
- WebKit
- Mobile Chrome 仿真
- Mobile Safari 仿真
- 该运行时套件目前针对每个运行时执行了 `20/20` 个公共 API 场景:
- 1 项静态连接检查
- 19 个公共方法
## 基准测试
最新一次本地 `npm run bench` 运行于 `2026-04-17`,Node 版本为 `v22.14.0 (win32 x64)`。
| 基准测试名称 | 操作次数 | 总耗时 (ms) | 平均耗时 (ms/op) | 每秒操作数 (ops/sec) |
| ----------------------------------- | --: | ------: | ------: | --------: |
| `identifier.generate` | 100 | 2.91 | 0.0291 | 34389.08 |
| `identifier.derive` | 100 | 34.97 | 0.3497 | 2859.53 |
| `identifier.validate` | 100 | 0.41 | 0.0041 | 243961.94 |
| `cipherMessage.generateKey` | 100 | 48.77 | 0.4877 | 2050.38 |
| `cipherMessage.deriveKey` | 100 | 67.84 | 0.6784 | 1474.02 |
| `cipherMessage.encrypt` | 100 | 36.80 | 0.3680 | 2717.03 |
| `cipherMessage.decrypt` | 100 | 36.02 | 0.3602 | 2776.57 |
| `messageAuthentication.generateKey` | 100 | 44.84 | 0.4484 | 2230.24 |
| `messageAuthentication.deriveKey` | 100 | 75.64 | 0.7564 | 1322.07 |
| `messageAuthentication.sign` | 100 | 29.09 | 0.2909 | 3437.31 |
| `messageAuthentication.verify` | 100 | 25.33 | 0.2533 | 3947.69 |
| `keyAgreement.generateKeypair` | 100 | 827.02 | 8.2702 | 120.92 |
| `keyAgreement.deriveKeypair` | 100 | 842.11 | 8.4211 | 118.75 |
| `keyAgreement.encapsulate` | 100 | 1669.17 | 16.6917 | 59.91 |
| `keyAgreement.decapsulate` | 100 | 1240.95 | 12.4095 | 80.58 |
| `digitalSignature.generateKeypair` | 100 | 808.57 | 8.0857 | 123.67 |
| `digitalSignature.deriveKeypair` | 100 | 612.56 | 6.1256 | 163.25 |
| `digitalSignature.sign` | 100 | 3478.93 | 34.7893 | 28.74 |
| `digitalSignature.verify` | 100 | 2574.33 | 25.7433 | 38.85 |
结果因机器和 Node 版本而异。
## 致谢
后量子原语构建于 [noble](https://paulmillr.com/noble/) 之上。
感谢 Paul Miller 提供了这个异常清晰、工程出色且真正令人惊叹的项目。
## 许可证
Apache-2.0
标签:AES-GCM-256, Browser, Bun, CMS安全, CVE, Deno, Ed25519-ML-DSA-65, GNU通用公共许可证, HMAC-SHA-256, JavaScript, JSONLines, Node.js, NPM包, OSV-Scalibr, TypeScript, WebCrypto, X25519-ML-KEM-768, 前端加密, 加密工具包, 加密敏捷性, 加密消息传输, 后端加密, 后量子密码学, 哈希算法, 声明式API, 安全插件, 密码学, 密钥协商, 手动系统调用, 抗量子计算, 数字签名, 数据可视化, 本体建模, 消息认证, 端到端加密, 网络安全, 自定义脚本, 跨运行时, 防御绕过, 隐私保护, 零信任