channel-key-derivation
v1.2.1
Published
CKD (Channel Key Derivation) - 轻量级、无状态、可逆的资源标识派生协议
Maintainers
Readme
channel-key-derivation — CKD JS SDK
CKD(Channel Key Derivation)的 JavaScript SDK。
对应 Go 版本:github.com/doc-war/ckd
对应 Rust 版本:github.com/doc-war/ckd-rust
概述
CKD(Channel Key Derivation)是一种轻量级、无状态、可逆的资源标识派生协议。
它允许从一个内部资源标识派生出多个不同用途的外部标识,并支持在不依赖映射表的情况下恢复原始资源标识。
目标
CKD 的核心目标:
- 一个内部资源 ID
- 派生多个用途隔离的外部 Key
- 无数据库映射
- 可逆恢复
- 不同用途之间不可互相推导
在数学上的具体表现为:
- C → A
- C → B
- A → C
- B → C
- A 无法推导 B
- B 无法推导 A
- 不需要存储 A→C 映射
- 不需要存储 B→C 映射
- 仅依赖平台密钥即可完成派生和反向解析
- 且无法使用已知的AB来反向破解密钥
价值
采用CKD的O(1)复杂度,相比库索引,在数值上的影响是直观的:
| 指标 | 查库 | CKD | | ------------ | -------- | ---------- | | 单次路由延迟 | 1~10ms | 0.01~0.1ms | | 单机QPS | 1万~5万 | 10万~50万 | | 横向扩容 | 受DB限制 | 近线性 | | Redis依赖 | 需要 | 不需要 | | MySQL依赖 | 需要 | 不需要 |
对于极纯粹的高并发技术设施,将系统从“状态驱动路由”变成“计算驱动路由”,减少两次查库,并发能力提升通常不是 2 倍、3 倍,而是一个数量级(10x)起步。
安装
npm install channel-key-derivation快速开始
import { CKD } from 'channel-key-derivation';
const secret = Buffer.from([
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
]);
const ckd = new CKD({
currentVersion: 1,
secretsByVersion: { 1: secret },
});
const channelId = Buffer.from('channel_12345');
const webhookKey = await ckd.derive(channelId, 'webhook');
const sseKey = await ckd.derive(channelId, 'sse');
const recovered = await ckd.parse(webhookKey, 'webhook');
console.log(recovered.toString()); // 'channel_12345'API
new CKD(config)
| 参数 | 类型 | 说明 |
|------|------|------|
| config.currentVersion | number | 当前生效的密钥版本号 [1, 15] |
| config.secretsByVersion | object | 多版本密钥映射表 { 1: secretBuffer } |
async ckd.derive(resourceId, purpose)
| 参数 | 类型 | 说明 |
|------|------|------|
| resourceId | Uint8Array | 内部资源标识 |
| purpose | string | 用途标识 [a-z0-9_-]{1,64} |
返回 Promise<string> base64url 编码的派生密钥。
async ckd.parse(derivedKey, purpose)
| 参数 | 类型 | 说明 |
|------|------|------|
| derivedKey | string | base64url 编码的派生密钥 |
| purpose | string | 用途标识 |
返回 Promise<Buffer> 原始资源 ID。
错误处理
import { CkdError, ErrInvalidPurpose, ErrInvalidDerivedKey } from 'channel-key-derivation';
try {
await ckd.parse('!!!', 'webhook');
} catch (err) {
if (err === ErrInvalidDerivedKey) {
// 格式错误 / 认证失败 / 版本不存在
}
}密钥轮换
const ckd = new CKD({
currentVersion: 2,
secretsByVersion: {
1: oldSecret, // 保留,用于解析旧 Key
2: newSecret, // 新派生使用此密钥
},
});
const newKey = await ckd.derive(channelId, 'webhook'); // 使用 v2
const recovered = await ckd.parse(oldKey, 'webhook'); // v1 仍可解析跨语言测试向量
| # | Secret | Purpose | Ver | ResourceID | K |
|---|--------|---------|-----|------------|---|
| 1 | 0001...1e1f (32B) | webhook | 1 | channel_12345 | AXnjdNQal5XDP66STw0pQbOzRi3AdGmiX1Xi5ZxO |
| 2 | 0001...1e1f (32B) | sse | 1 | user_67890 | Aez5p0zdhSjxmsgy92MfMhiMlhAbRxlldWcl |
| 3 | ffee...1100 (32B) | api_token | 2 | channel_12345 | ApUFLCCTYol1B57b459DrXW8SiQaJLaJRUx246YY |
Go、Rust、JS 三端产出完全一致。
测试
npm test许可
MIT
