@atlasauth/pca (英语)
证明机构(PCA)核心:授权AI代理,每起行动都有自己的证据. 主要标志是 根意向赠款 一次 一次吗 那探员呢 附上一个签名的自定义 PC Actn 个人电脑 用于每个动作,而资源服务器将它验证为离线: 是被授予的权力内部的行动, 是签字链的完整, 是承诺计划的一个节点, 难道还有信托预算可以做吗?
这包装有Canonical hashing, Ed25519和后量子签名, 默克勒计划承诺,
可扩展的能力链、硬件验证员、PCActn验证员和资源服务器
警卫requirePCA) (中文(简体) ). 资料来源和问题: https://github.com/阿特拉斯-Authorization/pca 页面存档备份,存于互联网档案馆。 。 。 .
principal --grant--> agent --PCActn (per action)--> resource server
(signs envelope, (holds a capability, (verifies offline: chain, plan,
policy, budget) emits a proof) signature, audience, budget)
安装
npm i @atlasauth/pca
节点20分 FN -DSA的量子后套房使用 @atlasauth/pca-fndsa-wasm,已安装
自动作为依赖。 可选的依赖关系( E)@xmldom/xmldom, (中文(简体) ), asn1js, (中文(简体) ), pkijs, (中文(简体) ), snarkjs, (中文(简体) ),
xml-crypto)仅被一些证明和零知识特性所使用.
使用量
代理方:每起行动都要铸造一笔赠款并签署PCAFN.
import { agent, generateKeyPair, pcaHeaders } from '@atlasauth/pca';
const AUD = 'ins_acme'; // the resource server this grant is for
const a = agent({
principal: generateKeyPair(), // the human's key; roots the grant
goal: 'reconcile October refunds',
permissions: { stripe: ['refund'] },
limits: { refund: '$500/day' },
aud: AUD,
});
const params = { amount: 42, currency: 'usd' };
const { encoded } = a.act('stripe.refund', 'charge:ch_123', params);
// Send it with the request: fetch(url, { headers: pcaHeaders(encoded), ... })
资源服务器:验证每个入站动作. requirePCA 是框架中和默认密度:需要
选中此项不会被强制拒绝 。 (对于快件、快件、Hono、Next和取取,请使用中间软件包)
@atlasauth/pca-express, (中文(简体) ), -fastify, (中文(简体) ), -hono, (中文(简体) ), -next, (中文(简体) ), -fetch. ) (中文(简体) )
import { requirePCA, memoryPcaStore } from '@atlasauth/pca';
const guard = requirePCA({
audience: AUD, // a PCActn signed for another audience is denied
resolveGrant: async (ref) => (ref === a.grant.id ? a.grant : null), // your grant store
budgetStore: memoryPcaStore(), // replay counter + trust budget (use a durable store in production)
hooks: { revocation: () => ({ enforced: true, ok: true }) }, // plug your revocation check
context: (_req, p) => ({
params, // the plaintext params the RS saw; must hash to action.params_digest
// The plan and its authorization must come from YOUR authoritative source. Echoing the plan
// from the proof itself, as this demo does, proves nothing about authorization.
plan: [{ id: 'n0', verb: p.action.verb, resource: p.action.resource,
params_digest: p.action.params_digest, reversibility_class: p.action.reversibility_class }],
planAuthorized: true,
risk: { reversibility: 1, blastRadius: 0.1, confidence: 1, semanticDistance: 0, taint: 0 },
budget: a.budget,
}),
});
const result = await guard({ headers: new Headers(pcaHeaders(encoded)) });
if (result.ok) {
// result.verdict.allow === true; result.pcactn is the verified action
} else {
// result.status is 401 or 403; result.wwwAuthenticate holds the challenge
}
再次发送同名PCActn作为回放(计数器必须增加)被拒绝.
核查
资源服务器只有在PCActn通过时才接受动作,顺序为: 有线(收缩犬形), 版本,受众,有效性窗口,能力链(hash链接,每个hop签名,根植于赠款), 计划包含、叶子签名和计数器(反重放)。 可选钩子增加了证明、吊销和 新鲜度、活性灯塔、齿口、门槛(卫士或人)共同标志和零知识 遵约。 授权只能缩小权限:警告只作为附件。 自主行动需要信任 预算,它约束着一种物剂在人类共同标志之间所能做的事情.
验证人
硬件验证被暴露为名位验证器,可以插入验证钩并成为
结合一项管理政策: attestAmdSnp (AMD SEV-SNP与米兰/热诺阿/都灵根针),
attestIntelDcap 财务报告和审定财务报表 attestIntelCollateral (英特尔TDX引文和PCS抵押品), attestAzureMaa
(Azure证物), attestGcpConfidentialSpace, (中文(简体) ), attestNvidiaSpdm 与 attestNvidiaRim 财务报告和审定财务报表
attestNvidiaOcsp (NVIDIA GPU 保密计算),加 attestPqSoftware 财务报告和审定财务报表 attestPuf. 核查
离线对接被绑的根;大多数硬件根是古典(ECDSA或RSA).
量子后套房
已签名的表面 alg 从套房登记簿: ed25519 (违约), ml-dsa-65, (中文(简体) ), ml-dsa-87, (中文(简体) ),
slh-dsa-sha2-128f, (中文(简体) ), slh-dsa-sha2-256s, (中文(简体) ), fn-dsa-512, (中文(简体) ), fn-dsa-1024,并混合 Ed25519 + ML-DSA 或
SLH-DSA组合. 密钥交换采用混合式X25519 + ML-KEM-768 KEM(hybridKemKeygen, (中文(简体) ),
hybridEncapsulate) (中文(简体) ).
FN-DSA(Falcon,FIPS 206)通过 @atlasauth/pca-fndsa-wasm,一个Web Assembly 建筑 Rust fn-dsa
货箱。 它被装入懒惰的第一使用。 如果无法装入, FN-DSA 验证失败
isFnDsaBackendActive() 报告是否具备.
import { randomBytes } from 'node:crypto';
import { b64u, fnDsa512Keygen, signWithSuite, verifyWithSuite } from '@atlasauth/pca';
const msg = new TextEncoder().encode('hello');
const k = fnDsa512Keygen(new Uint8Array(randomBytes(32)));
const sig = signWithSuite('fn-dsa-512', {
fnDsa512: { verifyingKey: k.verifyingKey, signingKey: k.signingKey, signSeed: new Uint8Array(randomBytes(32)) },
}, msg);
verifyWithSuite('fn-dsa-512', { fnDsa512Pub: b64u(k.verifyingKey) }, msg, sig); // true
持久状态( 只有节点)
@atlasauth/pca/durable-state 提供防撞、防篡改、多过程安全的关键/值状态
回滚保护(例如,最高许可列表版本或被接受的撤销时代). 这是一个
单独的子路径,因为它导入 node:fs。 。 。 .
import { openDurableState } from '@atlasauth/pca/durable-state';
const state = await openDurableState({ dir: '/var/lib/myapp/pca-state', hmacKey }); // hmacKey: 32+ bytes, optional
await state.update('epoch', (prev) => Math.max((prev as number) ?? 0, 5)); // atomic read-modify-write
它在腐败或倒退状态下未能关闭(DurableStateError) (中文(简体) ). 没有 hmacKey,替换
带有较旧的一致副本的完整目录无法在本地被检测出.
所需经费(部署前阅读). 锁定坐标进程于 一个主机 只:从不在主机之间共享目录. 目录必须放在 工作硬链接的本地文件系统 (单位:千美元)link(2) 带有独家创建的语义:ext4, xfs, btrfs, tmpfs, APFS. NFS、SMB/CIFS、FUSE和一些覆盖/集成挂载可两次授予锁或显示 stale上市; openDurableState 探测硬链接和 未关闭 与 DurableStateError 代码 link-unsupported 当它们无法使用时, 但它无法检测到一个本地正确链接的文件系统, 却在主机之间共享 。 活着但停滞不前的持有者( blocked fsync, SIGSTOP) 屏蔽其他进程直至其死亡: 它们失败 lock-timeout 之后 lockTimeoutMs 而不是取出锁; 重新启动或杀死被楔形控件.
找回已死亡的持有者 图书馆不能判断(R5-F1,R6-CORE-01.03). 在另一个 PID 命名空间( 崩溃的容器共享音量) 中, 在更改的主机名下, 一个无法读取或不完整的顶端 state.lock.N (单位:千美元){}, (中文(简体) ), [],没有pid/host/nonce),或遗留的单文件 state.lock 从更古老的版本中永远不能被自动判断为已死,所以每一个打开的失败都与 lock-timeout; 错误名称为屏蔽锁文件、其记录的持有人和要使用的呼叫。 在你确认持枪人走了之后 把它放出来 recoverDurableState({ dir, force: true, expectedHolder: { host, pid, nonce } }) (复制锁定文件中的3个值; 'unreadable' 对无法读取或不完整的记录; 添加 legacyLock: true 遗产 state.lock,将其移到一边,而不是删除)。 拒绝不匹配, 也没有任何变化; 无论主机名为何, 在这个 PID 命名空间中活着的持有者永远不会被释放 。 它不是自动的,从不从 openDurableState。 。 。 .
如果持有人只被暂停,什么追回担保(SIGSTOP, docker pause冰冻的VM. 恢复将锁本身,记录一个剪切(日记的尾部记录)在 state.fence,然后释放锁。 每个日记记录和头部都背有编剧的锁一代. 重命名前锁定检查失败前在任何地方被暂停的已恢复的持有人 lock-lost 写什么? 持有者在检查和重命名之间的少数指令中暂停了恢复时的重命名( 重命名(2) 无法附加条件); 它的后期日记是 在装入时被拒绝 (单位:千美元)DurableStateError corrupt,命名围栏),从未默默接受. 回收后新持有者的唱片被后期重名所取代,所以商店在运行前无法关闭 openDurableState({ ..., recoverFromCorruption: true }),用于对文件进行隔离(用于法证)并重新启动。 一个持有者在日记重名和头名重名之间暂停了,留下了被自动识别并修复的呆头(其记录是在恢复前完成的). 找回事实上运行的持有者,只能使商店倒闭,永远不接受异常的写出. 由更古老的版本所编写的记录/标题不携带生成(读作生成;由这个版本所编写的目录不能由更古老的版本打开. 型号 : formal/tla/DurableFence.tla。 。 。 .
如果恢复本身在中途死亡(SIGKILLL、OOM、电力损失). 每个步骤都是一个原子 link(2) 或者说 rename(2),因此任何一点的坠机都留下了几个定义明确的形状之一,没有一个可以让被释放的持有者迟到写入. 在取出锁前被杀死:没有改变;再次运行恢复. 锁被扣后被杀死state.lock.<g+1>标记 recovering),无论它的栅栏是否落地:这个锁现在称谓一个死过程. 一个侍从 相同的 PID 命名空间 审判它死了,并接管它 像任何死持有者,和因为 recovering 标记它首先取出自己的剪接并写出自己的栅栏(在它自己的,更新一代的)后再读出任何内容;它的锁上挂有印记,所以在它的栅栏登陆前自己被杀死的取走者将责任交给了下一部. 一个服务员进来 又一个 名称空间无法判断已死恢复并失败 lock-timeout 命名它; 再次在锁上运行恢复 。 无论是哪种方式,暂停的持有者 保持栅栏和写回。 坠机最多是孤儿 state.lock.tmp-* 或者说 state.fence.<gen>-*.tmp-* 档案,这是无害的。 每个栅栏都是自己的不可改变文件 state.fence.<gen>-<random> (单位:千美元) state.fence 列表中包含来自旧版本的栅栏和由 : recoverFromCorruption)),所以一个被暂停了并恢复了很晚的栅栏写作机永远不能同时掉出写作的栅栏. 模型检查(DurableFence.tla由SIGKILLL在每一步骤测试真正的恢复过程.
锁和栅栏的威胁模型(他们不防御的). 栅栏文件( E)state.fence, (中文(简体) ), state.fence.<gen>-*)和 state.lock.N 文件为 未签名或MACed,即使与 hmacKey。这是刻意的:任何能够删除或重写它们的人已经可以写入目录,并且能够以更简单的方式打破商店(删除日记和头部,这与第一次运行是无法区分的;或者杀死持有者)。 栅栏是用来防御 此库已暂停或已晚的进程,而不是针对一个拥有写入目录权限的攻击者. 重写 state.fence 无法让商店接受伪造的记录(记录和头部仍被散开链条并带有 hmacKey,MACed);删除它最多只能让回收的持有者负载的呆板记录,这需要该持有者在准确的窗口中也被暂停. 将目录限制在服务账户(创建为 0700)并锁定重要事项(参见 attest-allowlist-anchor) (中文(简体) ). 第二,我们.., 自动接收从不突破在另一个主机名下的锁,故意:不同主机名系指另一台机器(或容器的PID命名空间,我们无法看到) kill(pid, 0) 不说持有者的事;拿这种锁会让两个主机同时写作. 自动接收需要相同的主机名和(如果录入的话)相同的 PID 命名空间, 加上一个已死 pid; 任何其它操作员等待运行 recoverDurableState 在确认持枪者已离去后 这包括在另一主机或另一集装箱上运行的坠毁回收.
相关软件包
代理客户端 @atlasauth/pca-agent; 工具包装符 @atlasauth/pca-ai-sdk, (中文(简体) ), -langchain, (中文(简体) ), -openai, (中文(简体) ),
-anthropic, (中文(简体) ), -mcp;支付任务 @atlasauth/pca-payments; 工具 @atlasauth/pca-cli, (中文(简体) ),
@atlasauth/pca-testing, (中文(简体) ), @atlasauth/pca-events, (中文(简体) ), @atlasauth/pca-otel。 。 。 .
状态
前1.0 (0.3.0):API在小版本之间可能会有变化. 密码和协议没有
这不能代替安全审查 在你保护任何东西之前
数值. 离线,没有钩子,没有钩子 require 列表,若干检查报告 not-enforced 判决是
还是 allow: true数字 : plan_root_authorized (代理商提供自己的计划,所以单是纳入计划就证明)
没什么,它需要你自己的计划副本 context.plan 加号 context.planAuthorized, (中文(简体) ), revocation, (中文(简体) ),
threshold, (中文(简体) ), attestation, (中文(简体) ), freshness 财务报告和审定财务报表 beacon。资源服务器必须提供钩子或要求
检查 : requirePCA 默认 require 改为 DEFAULT_REQUIRED_CHECKS (对决、撤销、计划、授权),
因此,一个无强制条件的人否认 verifyPCActn 编号 : verifyPCActnCore 电话没有。 零知识后端目前使用BN254,正在向一个
透明,后量子后端;AMD SEV-SNP根链为古典.
项目审计本身以代码进行:安全关键单元的突变测试,结构意识模糊
每个解析器和核查器的切入点(包括证明证据格式)、静态分析、统计
计时检查,八语差分运行和供应链检查. 发现并固定
缺陷(在签字的图案中经常表示拒绝提供服务,敌对输入无型式例外,易受伤害者)
XML 解析器, 重用 bash scripts/pca-audit-all.sh,并在安全文件中加以说明。 这是一个
(b) 不属于独立审计.
许可证
麻省理工学院 - 见LICENSE
装甲紧凑-JWS门
assertCanonicalCompactJws(token, {parts, maxBytes, payload}) 编号 : isCanonicalCompactJws 编号 : assertCanonicalJwsSegments 编号 : decodeCanonicalBase64url 编号 : decodeCanonicalJsonSegment 编号 : compactJwsAliases:一个完全接受每个紧凑JWS一个拼写的门(收紧的不添加基数64url字母,解码-时-再编码-必须等同段,因此后行-位别名会死,没有白相间/控制字符,边长,头和有效载荷是BOM-无重复键的UTF-8严格-JSON对象). 类型 CanonicalJwsError 带有 reason. 第三方JOSE图书馆(如:. jose 5.x) 接受加法/ + / / 后继- 位 / 白空拼写相同签名, 因此任何按键在符号字符串或其散列(dedupe, 重放缓存, 分类账条目, 绑定散列) 上, 都可以通过再编码来绕行, 除非此门先运行. compactJwsAliases(token) 获得符合性测试的别名拼写.
套接字政策默认
- 无列表( N)
allowedSuites)指无限制:核查者接受其知道的每一套签名. - 空列表( N)
allowedSuites: [])表示拒绝一切. - 主机 API 默认为
ed25519加上包括Ed25519在内的混合体,并拒绝纯净的后量子套房(ml-dsa-*, (中文(简体) ),slh-dsa-*, (中文(简体) ),fn-dsa-*, (中文(简体) ),less-cat1除非操作员列出它们。 为了配合下线,通过allowedSuites确切的说:ed25519, (中文(简体) ),hybrid-ed25519-ml-dsa-65, (中文(简体) ),hybrid-nested-ed25519-ml-dsa-65, (中文(简体) ),hybrid-ed25519-ml-dsa-87, (中文(简体) ),hybrid-ed25519-slh-dsa-sha2-128f, (中文(简体) ),hybrid-ed25519-slh-dsa-sha2-256s, (中文(简体) ),hybrid-ed25519-less-cat1。有效的主机列表可在GET /v1/pca/suites页:1.