@tracer-kit/encryption-codec
v0.1.0
Published
AES-256-GCM and RSA-OAEP-SHA256 envelope encryption for browser diagnostics.
Maintainers
Readme
@tracer-kit/encryption-codec
npm install @tracer-kit/encryption-codec模块角色
Encryption Codec 位于 Tracer Domain 与持久化层之间。宿主端使用公钥把规范化日志编码为加密信封,DevTools 扩展使用私钥解码。Core Storage 只保存信封,不接触明文和密钥语义。
flowchart LR
Payload[规范化日志] --> AES[AES-256-GCM 加密]
SessionKey[AES 会话密钥] --> AES
PublicKey[RSA 公钥] --> Wrap[RSA-OAEP-SHA256 包装]
SessionKey --> Wrap
AES --> Envelope[EncryptedEnvelope]
Wrap --> Envelope
Envelope --> Storage[(Core Storage)]
Envelope --> Unwrap[扩展私钥解包]
PrivateKey[RSA 私钥] --> Unwrap
Unwrap --> Decrypt[AES-GCM 解密]
Envelope --> Decrypt
Decrypt --> Plaintext[日志明文]公共导出
createEncoder(publicJwk):导入 RSA 公钥并创建信封编码器。createDecoder(privateJwk, options?):导入 RSA 私钥并创建信封解码器。CRYPTO_SUITE:当前算法套件标识。CodecError:携带稳定code的可识别信封格式错误。- 类型:
EncryptedEnvelope、EnvelopeAuthenticationContext、EnvelopeEncoder、EnvelopeDecoder、CodecErrorCode。
内部的 Base64 和密钥导入辅助函数不从包入口导出。
信封格式
interface EncryptedEnvelopeV2 {
// v2 使用记录 id 和 occurredAt 作为 AES-GCM AAD。
formatVersion: 2;
authenticatedData: 'storage-record-v1';
// 固定算法套件:数据用 AES-GCM,加密数据密钥用 RSA-OAEP-SHA256。
cryptoSuite: 'AES-256-GCM+RSA-OAEP-SHA256';
// 被 RSA 公钥包装后的 AES 会话密钥,使用 Base64 编码。
encryptedDataKey: string;
// 每条记录独立生成的 12 字节 AES-GCM nonce,使用 Base64 编码。
nonce: string;
// AES-GCM 密文及认证标签,使用 Base64 编码。
ciphertext: string;
}import { createDecoder, createEncoder } from '@tracer-kit/encryption-codec';
// 宿主端只持有公钥,用于创建加密器。
const encoder = await createEncoder(publicJwk);
const context = { id: 'record-id', occurredAt: Date.now() };
const envelope = await encoder.encode(normalizedPayload, context);
// 私钥只允许存在于受控的 DevTools Service Worker 中。
const decoder = await createDecoder(privateJwk, {
// 最多缓存 64 个已解包的 AES key;设为 0 可关闭缓存。
cacheSize: 64,
});
const payload = await decoder.decode<LogPayload>(envelope, context);内部实现
编码器创建时生成一个 AES-256-GCM 会话密钥,再用 RSA-OAEP-SHA256 公钥包装 AES 密钥。每条记录生成独立 12 字节 nonce,并用 AES-GCM 加密 JSON 明文。v2 同时把记录 id 和 occurredAt 编码为附加认证数据,字段仍可查询但无法在不触发认证失败的情况下被篡改。这样大数据由对称加密处理,RSA 只处理固定长度密钥。
解码器先校验信封版本、算法套件、Base64 字段和 nonce 长度,再用私钥解包 AES 密钥。解包结果按 encryptedDataKey 缓存在有界 LRU 中,避免同一编码器产生的多条记录反复执行 RSA 解密。
sequenceDiagram
participant D as Decoder
participant C as AES Key LRU
participant R as RSA-OAEP
participant A as AES-GCM
D->>D: 校验版本、套件、Base64、nonce
D->>C: 查找 encryptedDataKey
alt 缓存未命中
D->>R: 私钥解包 AES key
R-->>D: raw AES key
D->>C: 写入并淘汰最旧项
else 缓存命中
C-->>D: AES key
D->>C: 移动到 LRU 队尾
end
D->>A: 认证解密 ciphertext
A-->>D: JSON 明文失败与安全边界
- 公钥可进入宿主构建;私钥只在扩展运行时导入到受控 Worker/Service Worker,不进入任何构建产物。
- 不支持的信封版本、非法 Base64 和 nonce 长度通过
CodecError的ENVELOPE_FORMAT_INVALID稳定标识;认证失败或错误密钥仍拒绝解码。 - 新写入使用 v2;Decoder 保留 v1 读取兼容,便于升级后读取历史记录。直接调用 Codec 时不传 context 仍会生成 v1,仅建议用于与持久化元数据无关的数据。
- nonce 每条记录随机生成,不得复用或改为可预测值。
测试与维护
test/codec.test.ts:加解密往返、随机 nonce 和错误信封。test/decoder-cache.test.ts:解码密钥 LRU 行为。
修改信封字段或算法套件时,必须同步本 README、两端调用者、测试以及 docs/modules/encryption-codec.md。
