@ codumation-cc/ 工人- crypto
字节和文本 工人代码需要它们 对于符号,签名和网络呼号。 仅建在WebCrypto上,所以 运行在Workers,节点和浏览器中. 唯一的例外是MD5,只有工人才有.
npm install @codefusion-cc/workers-crypto
import { base64UrlToBytes, digestHex, hmacMatches, hmacSha256, keyedHash, randomToken, safeEqual } from '@codefusion-cc/workers-crypto'
const token = randomToken() // 32 random bytes, 43 characters of base64url
const bytes = base64UrlToBytes(header) // null when it is not base64url: no exception to catch
const ok = safeEqual(await digestHex('SHA-384', JSON.stringify(fields)), notification.sign)
// Sign a webhook body, and check the signature a provider sent, in constant time.
headers.set('x-signature', await hmacSha256(env.WEBHOOK_SECRET, body, 'hex'))
const genuine = await hmacMatches(env.WEBHOOK_SECRET, body, request.headers.get('x-signature') ?? '', 'hex')
// An id that cannot be traced back to the visitor, and matches nothing else the secret signs.
const visitor = await keyedHash(env.VISITOR_HASH_SECRET, 'console-visitor', visitorId, { bytes: 8 })
- 每个解码器返回无效 案文不改为:
base64UrlToBytes, (中文(简体) ),base64ToBytes, (中文(简体) ),hexToBytes财务报告和审定财务报表base64UrlToUtf8。每个值有一个拼写。 白空格被拒绝, 上次设置的未使用位数也是如此 字符,一个宽松的解码器将读取为相同的字节. base64UrlToBytes拒绝=粘贴,除非{ padded: true }因为信使和JWT从没有过.base64ToBytes读取标准基数64并需要其加载,除非{ padding: 'optional' }通过.hmacSha256(secret, data, encoding?)将秘密作为文本(UTF-8, 即工人的秘密设置),字节,或 a 密码键。 它返回32个字节,或文字在'hex', (中文(简体) ),'base64'或者说'base64url'输入文本密钥一次 每个隔离。 空的或缺失的秘密,或用于另一种算法或散列的 CryptoKey,用 TypeError 拒绝 .hmacMatches(secret, data, mac, encoding?)以恒定时间比较。 永远不要将两个MAC与===文本 MAC需要它的编码(一个没有编码的TypeError;一个错误编码或长度错误的MAC不匹配.keyedHash(secret, label, value, { bytes, encoding })为 HMAC 的label\nvalue切为bytes标签 保持一个用途的散列 与另一个用途的 在同一秘密之下。 这一定是一行.- 永远不要为两者使用一个秘密
keyedHash财务报告和审定财务报表hmacSha256。 。 。 .keyedHash这是hmacSha256标签,行 分解和值,所以一个MAC在数据上 形状等于按键散列。 各各献出自在秘密. safeEqual需要的时间并不取决于两个文本的不同之处。 只有长度差异显示.digestHex('MD5' | 'SHA-1', …)只针对其签名需要这些算法的供应商。 一些支付网关做.
在 WebCrypto 上构建的代码
进口密钥或打开密封数据需要的每包有两个东西,保存在这里一次.
import { createPromiseCache, nullIfRefused } from '@codefusion-cc/workers-crypto'
// Import each key once per isolate (or page), at most 64 of them.
const imported = createPromiseCache<CryptoKey>(64)
const keyFor = (raw: string) => imported(raw, () => crypto.subtle.importKey('raw', decode(raw), 'AES-GCM', false, ['decrypt']))
// null when the tag does not match (tampered, or another key); an outage rejects as itself.
const plain = await nullIfRefused(crypto.subtle.decrypt({ name: 'AES-GCM', iv }, await keyFor(raw), data), 'OperationError')
createPromiseCache<T>(limit)返回时(key, make) => Promise<T>。呼吁按键共享make(key),以及 其结果为以后的每一次呼吁服务。 它维持最多limit成果,工作仍在进行中,并让 最近用过的最好先用. 拒绝永远不会被保留: 那些等待它的召唤者看见它,而下一个召唤就运行了make因此,一个失败的导入不会在隔离者的余生中打破那个键. 无效的结果是 一个答案,并被保存.nullIfRefused(call, ...names)解决WebCrypto调用的问题, 或当WebCrypto拒绝输入时无效 其中一个names数字 :OperationError(不匹配的AES-GCM标记、ECDH或X25519点表示不) 秘密吗,DataError(不是关键数据),InvalidAccessError(与操作不同的密钥). 其它的失败(运行时间缺少的算法,断开绑定,断出)都拒绝自己. 捕捉 反之,一切都变成了"没有钥匙","被标记"或"被伪造", 以及用这些来操作的代码(写出新的) 键,删除数据,签名人退出),然后进行损坏.refusedWith(error, ...names)是同一个测试 (单位:千美元)catch块。 两者都只读出错误的名字,所以一个来自另一个域的 DOM Exception 仍然算数.