@byokit/seal

中文文档
0.3.2发布于 2026/10/25Apache-2.0TypeScriptES Module构建来源已验证近 30 天下载 9658

TypeScript套件让人们通过他们已经支付的人工智能计划,在网络,电话和桌面上登录到你的应用程序.

中文使用文档
文档目录11 节
  1. 安装
  2. 快速启动
  3. API 一览
  4. 原始密钥、经认证的盒子和通知
  5. 在 iOS 通知服务扩展中打开通知
  6. 格式
  7. 随机和密钥
  8. 依赖关系
  9. 测试
  10. 链接
  11. 许可证

@ byokit/ seal

npm CI Apache 2.0 Node 22+ | browsers | React Native

手提箱,密箱和Ed25519签名.
Box, secretbox和Ed25519 节点22+,浏览器/PWAs和React Industrial的签名,没有本地模块,也没有 节点运行时间导入 。 对于存储或发送小秘密的应用程序, 需要字节相同的封装箱到处 (参见兼容向量的API表和测试).

安装

npm install @byokit/seal

npm • 妇女 最近发布 • 妇女 所有释放

快速启动

npm install @byokit/seal

在本地反应时安装 crypto.getRandomValues 使用前多填充( 例如 react-native-get-random-values) (中文(简体) ).

封住并打开一个盒子,将JSON值保存在密箱中,并签名和验证一个消息:

import {
  boxKeyPair, boxPublicKey, boxKeyPairFromSeed, sealBox, openBox, openBoxFromSeed,
  box, openAuthBox, sealNotice, openNotice,
  sealJson, openJson,
  signingKeyPairFromSeed, signDetached, verifyDetached,
} from '@byokit/seal';

const text = new TextEncoder().encode('hello from the phone');

// Box: anyone with the recipient's public key can seal; only the secret opens.
const recipientSeed = crypto.getRandomValues(new Uint8Array(32));
const recipient = boxKeyPairFromSeed(recipientSeed);
const bundle = sealBox(text, recipient.publicKey);
console.log('box bytes:', bundle.length);
console.log('opened:', new TextDecoder().decode(openBox(bundle, recipient.secretKey)!));
console.log('wrong key:', openBox(bundle, crypto.getRandomValues(new Uint8Array(32))));

// Secretbox JSON: one 32-byte key seals and opens data at rest.
const key = crypto.getRandomValues(new Uint8Array(32));
const stored = sealJson({ machines: ['desk'] }, key);
console.log('json:', openJson(stored, key));
stored[stored.length - 1] ^= 1;
console.log('tampered json:', openJson(stored, key));

// Ed25519 detached signatures.
const signing = signingKeyPairFromSeed(crypto.getRandomValues(new Uint8Array(32)));
const signature = signDetached(text, signing.secretKey);
console.log('signature bytes:', signature.length, 'secret key bytes:', signing.secretKey.length);
console.log('verified:', verifyDetached(text, signature, signing.publicKey));
console.log('other message:', verifyDetached(new TextEncoder().encode('changed'), signature, signing.publicKey));

运行 TypeScript 文件的输出 node (节点22.18+):

box bytes: 92
opened: hello from the phone
wrong key: null
json: { machines: [ 'desk' ] }
tampered json: null
signature bytes: 64 secret key bytes: 64
verified: true
other message: false

92字节盒为32(ephemeral public key)+24(nonce)+16(MAC)+20(信息).

API 一览

导出它会做什么
boxKeyPair(rng?)新鲜出品的32字节X25519秘密及其公用钥匙
boxPublicKey(secret)X25519 原始32字节密钥
boxKeyPairFromSeed(seed)X25519 从32字节种子取出;与libsodium相同 crypto_box_seed_keypair
sealBox(bytes, recipientPublicKey, rng?)将字节刻入有新电子键的公钥
openBox(bundle, recipientSecret)打开一个原始的秘密; Uint8Array 或者说 null
openBoxFromSeed(bundle, recipientSeed)以种子打开, 如原始 API
box(bytes, theirPublic, mySecret, rng?)已知的认证框
openAuthBox(bundle, theirPublic, mySecret)打开已知的发送框; Uint8Array 或者说 null
sealNotice(value, boxPublicKey, rng?)JSON在匿名盒子里; { v: 1, sealed: string }
openNotice(data, secret)以原始秘密打开通知; unknown 或者说 null
sealSecretBox(bytes, key, rng?)带有 32 字节密钥的密封字节
openSecretBox(bundle, key)打开密箱; Uint8Array 或者说 null
sealJson(value, key, rng?)JSON.stringify, UTF-8, 然后是密箱
openJson(bundle, key)打开和剖析; 值或 null
signingKeyPairFromSeed(seed)来自32字节种子的 Ed25519 密钥对; 微博nacl-style 64-字节密钥
signDetached(bytes, secretKey)64字节脱节签名
verifyDetached(bytes, signature, publicKey)true 或者说 false
RandomBytes (类型)(length: number) => Uint8Array,封条函数的可选 RNG

每个电话在一个地方:

import {
  boxKeyPair, boxPublicKey, boxKeyPairFromSeed, sealBox, openBox, openBoxFromSeed,
  box, openAuthBox, sealNotice, openNotice,
  sealSecretBox, openSecretBox, sealJson, openJson,
  signingKeyPairFromSeed, signDetached, verifyDetached,
} from '@byokit/seal';

const recipient = boxKeyPairFromSeed(recipientSeed); // 32-byte seed; same as libsodium crypto_box_seed_keypair
const bundle = sealBox(plaintext, recipient.publicKey);
const opened = openBox(bundle, recipient.secretKey); // Uint8Array | null
const sealed = sealSecretBox(plaintext, secretboxKey); // 32-byte key
const unsealed = openSecretBox(sealed, secretboxKey); // Uint8Array | null
const stored = sealJson({ machines: [] }, secretboxKey);
const catalog = openJson(stored, secretboxKey); // unknown | null
const signing = signingKeyPairFromSeed(signingSeed); // 32-byte seed
const signature = signDetached(plaintext, signing.secretKey); // 64-byte signature
verifyDetached(plaintext, signature, signing.publicKey); // boolean

原始密钥、经认证的盒子和通知

const sender = boxKeyPair();
const device = boxKeyPair();
const authenticated = box(text, device.publicKey, sender.secretKey);
const opened = openAuthBox(authenticated, sender.publicKey, device.secretKey);
const notice = sealNotice({ kind: 'completed', job: 'build' }, device.publicKey);
const event = openNotice(notice, device.secretKey);

openBox 现在拿一个生X25519秘密。 对于所储存的种子,保留 boxKeyPairFromSeed(seed) 并通过它的 secretKey,或替换旧的 openBox(bundle, seed) 调用 openBoxFromSeed(bundle, seed)。 。 。 . 所储存的密码和种子衍生物不变。 一个原始的秘密和一个种子是不同的投入.

已知的发报框需要端点信任的公钥;两个端点都可以生成其密码文本,所以是 非签名 。 匿名信箱和通知无法识别发送者。 验证解密的通知值 在他们面前行动之前的应用 贾森 null 无法区分打开失败; 未定义的值, 循环对象和BigInts不能被封为JSON.

在 iOS 通知服务扩展中打开通知

没有JavaScript在iOS通知服务扩展中运行,因此包还装有Swift开关器, ios/Sources/ByokitSeal/ByokitSeal.swift (只有CryptoKit,iOS 13+). 将该文件添加到扩展目标中 。 与 @byokit/relay是因为 mutableContent: true,iOS在提醒显示前运行扩展,即使应用程序不是 运行中,扩展可以以通知取代通用文本 :

import UserNotifications

final class NotificationService: UNNotificationServiceExtension {
  override func didReceive(_ request: UNNotificationRequest, withContentHandler done: @escaping (UNNotificationContent) -> Void) {
    let content = request.content.mutableCopy() as! UNMutableNotificationContent
    if let secret = ByokitSeal.keychainSecret(service: "app:no-auth", account: "notice-secret", accessGroup: "TEAMID.com.example.shared"),
       let notice = ByokitSeal.openNotice(userInfo: request.content.userInfo, secret: secret) as? [String: Any],
       let title = notice["title"] as? String, let body = notice["body"] as? String {
      content.title = title // validate before showing; the notice's sender is not authenticated
      content.body = body
    }
    done(content) // on any failure the generic alert shows unchanged
  }
}

应用程序拥有通知密钥: 它使用 boxKeyPair(),将公钥给主机,只保存 32字节秘密作为密钥链访问组中未添加的碱基64url字符串,与其扩展共享,可在 第一个解锁( 带有 expo- security- store :) setItemAsync('notice-secret', secret, { accessGroup, keychainAccessible: AFTER_FIRST_UNLOCK }),哪些存储服务 app:no-auth) (中文(简体) ). keychainSecret 完全读取此项目; 扩展 从不读取其他密钥链项,也从不登录该密钥或通知. openNotice(envelope, secret:) 打开一个 信封来自任何地方。 它与 TypeScript 打开器的字节对等由检查 ios/Tests/ByokitSealTests 针对矢量 此包的测试 制取并打开 libsodium (swift test 在此 目录). 一个区别是无法避免的: Swift 字符串不能持有一个未发售的 UTF-16 代孕,所以通知 其 JSON 包含一个(例如文本切入 slice 通过emoji)在TypeScript中打开,但在斯威夫特为零, 和一般警报显示。 密封成文的文字(String.prototype.toWellFormed) (中文(简体) ).

格式

  • sealBox x25519公用钥匙的发售(32个) crypto_box_easy 密码文本 (16字节MAC先行).
  • box (24个) crypto_box_easy 密码文本 (16字节MAC先行).
  • sealNotice 发射 { v: 1, sealed }时 sealed 未添加基数64url = sealBox UTF-8 JSON 字节.
  • sealSecretBox (24个) crypto_secretbox_easy 密码文.
  • sealJson 用途 JSON.stringify 然后是UTF-8; openJson 解析 UTF-8并返回 null 失败.
  • openBox, (中文(简体) ), openAuthBox 财务报告和审定财务报表 openSecretBox 返回时 null 短,被篡改,或错误的钥匙捆.
  • 无效的密钥长度传递给封存/ 签名抛出 .

随机和密钥

每个印章接受一个可选的最终 (length: number) => Uint8Array 用于确定性试验的RNG 默认为 crypto.getRandomValues。 。 。 .

import { sealSecretBox, type RandomBytes } from '@byokit/seal';

// Tests only: a fixed RNG makes the output repeatable. Never in production.
const fixed: RandomBytes = (length) => new Uint8Array(length).fill(7);
const key = new Uint8Array(32).fill(1);
const a = sealSecretBox(new Uint8Array([1, 2, 3]), key, fixed);

在生产中绝不再重复使用带有相同钥匙或可替代确定性RNG的密箱。 保守秘密 隐藏秘密 平台安全存储; 此库不管理存储或密钥.

依赖关系

固定用途 @noble/curves, (中文(简体) ), @noble/ciphers 财务报告和审定财务报表 @noble/hashes。没有本地模块或节点运行时间导入.

测试

套房检查固定的 libsodium/tweetnacl 向量和与互操作性的双向 sodium-native, (中文(简体) ), 包括篡改和错误的密钥案件。 运行 npm run build && npm run check && npm test 在寄存器根处.

  • 字节,存储器根
  • 变动情况
  • 警卫
  • examples/expo: iOS和Android上的盒子、密箱和签名,带有 crypto.getRandomValues 多元填充( e)expo-crypto(单位:千美元) polyfills.ts

许可证

阿帕奇2.0 (英语). 见 自由主义 财务报告和审定财务报表 通知。 。 。 .

版本与发布记录

@byokit/seal 共发布 5 个版本,首次发布于 2026/09/26;过去 12 个月发布了 5 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.3.2latest2026/10/2514 天前
0.3.12026/10/1822 天前
0.3.02026/10/031 个月前
0.2.02026/09/301 个月前
0.1.02026/09/261 个月前

关于 @byokit/seal 的常见问题

@byokit/seal 是什么?

TypeScript套件让人们通过他们已经支付的人工智能计划,在网络,电话和桌面上登录到你的应用程序.

如何安装 @byokit/seal?

在项目目录运行 npm install @byokit/seal,或使用 pnpm add / yarn add / bun add。

@byokit/seal 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@byokit/seal 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@byokit/seal 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22.18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@byokit/seal 可以商用吗?

@byokit/seal 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@byokit/seal 的下载量有多少?

根据 npm 官方下载统计,@byokit/seal 在 2026/10/09 – 2026/11/07 这 30 天内被下载 9,658 次,日均约 322 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@byokit/seal 还在维护吗?

最新版本 0.3.2 发布于 2026/10/25(14 天前);至今共发布 5 个版本,其中过去 12 个月发布了 5 个;首次发布于 2026/09/26。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。