耳朵标记( E)@fungi.computer/ear-tag(中文(简体) )
Ear Tag是TypeScript主机的一个独立,模块化的密钥服务器. 它的基地
输入点创建密码随机无记名密钥和SHA-256文摘,所以
主机可以在不发明的情况下发布像邀请码或API密钥这样的秘密
它自己的随机弦和散列逻辑. ./grants 构建一个已键入
提供能力的词汇,以及 ./keys 在顶上运行一个租户范围密钥店
* 发放、核查、比较和分享赠款编辑、撤销、,
可选过期、所有者暂停和每键利率限制。 老板决定
范围、储存和政策; 耳朵标记拥有机械.
安装或设置
npm install @fungi.computer/ear-tag
包船无害环境管理仅取决于 凯恩 页:1
标识符和随机字符串,以及 zod 为它的计谋。 哈兴使用
全球网络加密 API (G)crypto.subtle.digest),可在19+节点和
工人运行时间。 它有四个切入点: @fungi.computer/ear-tag (密码)
(原始内容存档于2018-10-21) (英语). primers,,,,, @fungi.computer/ear-tag/grants (赠款词汇),
@fungi.computer/ear-tag/keys (密钥存储, 不含任何特定节点类型)
财务报告和审定财务报表 @fungi.computer/ear-tag/keys/node (单位:千美元) node:sqlite 适配器,所以一个工人
消费者 ./keys 永远不需要 @types/node 键入检查.
快开始
此帮助创建了前缀的密钥, 存储其文摘, 然后将普通文本交给 给主机授权的交付功能。 东道方提供这两项业务; 密钥和文摘都没有记录:
import { generateKeyAndHash } from "@fungi.computer/ear-tag";
export async function issueInvite(
storeDigest: (digest: string) => Promise<void>,
deliverKey: (key: string) => Promise<void>,
): Promise<void> {
const { key, digest } = await generateKeyAndHash({ prefix: "invite" });
await storeDigest(digest);
await deliverKey(key);
}
现有的测试可验证生成的文摘是否与 Plaintext 密钥相匹配
test/crypto.test.ts。 。 。 .
核心概念
generateKey(options) 返回随机无记名字符串。 添加可选前缀
<prefix>_ 在随机部分之前. length 控制随机部分
长度. hashKey(key) 返回其 SHA-256 文摘为小写十六进制.
generateKeyAndHash(options) 创建值和返回 { key, digest }。 。 。 .
赠款和钥匙库
./grants 声明一个宿主的能力词汇,并返回计划
关闭了它:
import { defineGrants } from "@fungi.computer/ear-tag/grants";
const vocabulary = defineGrants({
capabilities: ["files.read", "files.write"] as const,
});
./keys 在一个租户范围 的密钥店里运行着这个词汇. sql 这是
exec(statement, ...bindings) -> { toArray() } 形状 Cloudflare 持久对象
SQLite 已经提供了 ; ./keys/node是因为 fromNodeSqlite 调整一个 node:sqlite
在持久对象之外运行的主机的数据库 :
import { createKeyStore } from "@fungi.computer/ear-tag/keys";
import { fromNodeSqlite } from "@fungi.computer/ear-tag/keys/node";
import { DatabaseSync } from "node:sqlite";
const store = createKeyStore({
sql: fromNodeSqlite(new DatabaseSync(":memory:")),
commit: (body) => Promise.resolve(body()),
vocabulary,
prefix: "demo",
authorizeIssuer: async () => ({ kind: "unrestricted" }),
});
const issued = await store.issue("owner-1", {
name: "ci bot",
grants: [{ capability: "files.read", targets: { kind: "all" } }],
});
每个操作返回 a KeyOutcome数字 : { kind: "ok", value } 或者说
{ kind: "error", error: { code, retryAfterSeconds? } },与 code 一个
invalid (呼叫者自己的请求失败验证), denied (结构良好)
但因案情而被拒绝, conflict, (中文(简体) ), expired, (中文(简体) ), rate_limited 或者说
unavailable (商店自身的状态不能被读回;总是被登录). 一个
商店实例是一个租户; 租户之间的名称间隔是东道主自己的
表格或存储边界.
authorizeIssuer是因为 "bounded" 仅允许演员分配的狭义
结束 issue 或者说 updateGrants。它并不缩小行为者可能
list, (中文(简体) ), revoke 或编辑:它解决给非 null 权限的任何角色可能
管理租户的每把钥匙,包括另外发行的钥匙。 这个
匹配 Hub 的自定义 authorizeManage。 。 。 . implies 是一个深层,不是
中转; 两者均 grantsAllow 财务报告和审定财务报表 grantsList 尊重它而不扩大
选定的赠款目标.
主机可允许使用 delegation: { manage }。通过 a
父本金为 issue 或者说 updateGrants 需要钥匙才能活下来,
由同一人拥有,拥有管理能力,并支付每笔赠款
被分配。 在发放时,孩子不能超过父母。 撤销
父母后来不撤销已经发放的子女的国籍
两者均适用.
live({ keyId, grantVersion? }) 重新检查人类发行商和耐用密钥
排行不花一个速率档。 一个版本的指针拒绝一个陈旧的赠款套.
current(principal) 用于主机资源交易的同步;
它检查行和版本,而不是同步的人类成员.
verify(secret) 消耗一个速率槽; admitUse 重新检查现场权威和
记录确切的使用收据。 元数据从不选择摘要.
可选 epoch: { begin, finish, abort } 栅栏允许编辑和取消
对一个外来的入住者。 每种方法都得到相同的裁定id.
本地持久收据可以区分中止承诺和丢失承诺
承认; 精确的重复完成承诺的决定而不发生变异
再来一次 中止的决定是终端: 重试中止的请求不会
重新打开它。 中止后恢复需要新的 requestId,该名称为新
划时代的决定。 承诺请求的完成失败, 而是与
原文 requestId 并且只完成这个决定. onAuthorityChange 运行
地方内部承诺并进行过渡 kind 财务报告和审定财务报表
throughGrantVersion: 赠款编辑的替换版本, 当前
用于撤销、暂停或关闭的版本.
close(closedAt) 是同步的,并在主机自己的交易中运行。 这个
永久关闭租户并吊销其钥匙; 重新开店不会
允许以后发行或授权编辑。 主机必须先检查结果
进行附带交易.
keyWire(vocabulary) 提供共享 issue, (中文(简体) ), updateGrants 财务报告和审定财务报表 revoke
请求解码器加 toSummary(record)概述载有赠款和
生命周期元数据, 从来没有一个摘要 或人类所有者的身份。 东道主保留他们的名字,
(c) 身份、期满、费率政策和运输许可规则.
API 参考
参见生成的 API 引用 原始密码, (中文(简体) ),
./grants, (中文(简体) ), ./keys 财务报告和审定财务报表
./keys/node,或从
索引。 。 。 .
实例和检查
密码测试覆盖了散列,前缀生成,以及密钥/最深的对.
赠款和钥匙库测试包括发放、核查、比较和扫描
授予编辑和重播、改变权力的栅栏、被俘虏的坚固本金,
撤销、可选过期、所有者暂停、每键利率限制、限定
次级发放和限值赠款编辑,以及 admitUse 过期或中止
键,对两个后端进行完全相同的断言:
云花长对象pnpm run test:cloudflare真实 state.storage.sql
财务报告和审定财务报表 transactionSync而不是一个适合他们的适配器) 和包裹的
拥有 node:sqlite 适配器( e)pnpm run test:node) (中文(简体) ). 运行一切与:
pnpm --filter @fungi.computer/ear-tag test
限制和错误
无记名钥匙是一个秘密:任何人获得它,都可以将其呈送给系统 接受这个事实 不日志或坚持纯文本密钥。 保留摘要和 仅将简洁文本发送给预定的收件人.
hashKey 需要网络加密 crypto.subtle.digest键长
凯恩是生的 nanoid 缩小行为范围。 呼叫者应提供限定范围
非负整数而不是不信任的大小输入.
密钥存储的速率限制在内存中计算, 而不是持续; 如果
主机重新创建商店(例如从驱逐中醒来的持久对象)。 A 类
KeyPrincipal 返回时间 verify 是一个平坦、未封存的数据对象: current
财务报告和审定财务报表 admitUse 接受一个回 以便宜的恢复会话,但他们重新阅读
每一次通话时都会有按键的现场直播 和其赠送版本,所以一个虚构的或僵化的
本金被拒绝而不是信任.
贡献和许可证
耳朵标记是麻省理工学院的许可。 见 LICENSE。 。 。 .