@codefusion-cc/workers-crypto

中文文档
0.1.2发布于 2026/10/04MITTypeScriptES Module零依赖近 30 天下载 2299

Bytes and text for tokens, signatures and webhooks on WebCrypto: base64url and base64 both ways, hex, digests (MD5 too in Workers, for payment gateways), HMAC-SHA256 signing and constant-time checking, labelled keyed hashes, a constant-time comparison and

原始使用文档

@codefusion-cc/workers-crypto

Bytes and text the way Workers code needs them for tokens, signatures and webhooks. Built on WebCrypto only, so it runs in Workers, Node and the browser. The one exception is MD5, which only Workers have.

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 })
  • Every decoder returns null for text it does not read: base64UrlToBytes, base64ToBytes, hexToBytes and base64UrlToUtf8. Each value has one spelling. Whitespace is refused, and so are unused bits set in the last character, which a lenient decoder would read as the same bytes.
  • base64UrlToBytes refuses = padding unless { padded: true } is passed, because tokens and JWTs never have it.
  • base64ToBytes reads standard base64 and requires its padding unless { padding: 'optional' } is passed.
  • hmacSha256(secret, data, encoding?) takes the secret as text (UTF-8, as Worker secrets are set), bytes, or a CryptoKey. It returns 32 bytes, or text in 'hex', 'base64' or 'base64url'. A text secret is imported once per isolate. An empty or missing secret, or a CryptoKey for another algorithm or hash, rejects with a TypeError.
  • hmacMatches(secret, data, mac, encoding?) compares in constant time. Never compare two MACs with ===. A text MAC needs its encoding (a TypeError without one); a MAC in the wrong encoding or of the wrong length does not match.
  • keyedHash(secret, label, value, { bytes, encoding }) is the HMAC of label\nvalue, cut to bytes. The label keeps one use's hashes apart from another's under the same secret. It must be one line.
  • Never use one secret for both keyedHash and hmacSha256. keyedHash is the hmacSha256 of the label, a line break and the value, so a MAC over data shaped that way equals a keyed hash. Give each its own secret.
  • safeEqual takes time that does not depend on where two texts differ. Only a length difference shows.
  • digestHex('MD5' | 'SHA-1', …) is only for providers whose signatures require those algorithms. Some payment gateways do.

Code built on WebCrypto

Two things every package that imports keys or opens sealed data needs, kept here once.

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) returns (key, make) => Promise<T>. Calls for a key share one run of make(key), and its result serves every later call. It keeps at most limit results, work still running among them, and lets the least recently used go first. A rejection is never kept: the callers waiting on it see it, and the next call runs make again, so one failed import does not break that key for the rest of the isolate's life. A null result is an answer and is kept.
  • nullIfRefused(call, ...names) resolves what a WebCrypto call resolves, or null when WebCrypto refuses the input with one of names: OperationError (an AES-GCM tag that does not match, an ECDH or X25519 point that gives no secret), DataError (key data that is no key), InvalidAccessError (a key of another kind than the operation). Every other failure (an algorithm the runtime lacks, a broken binding, an outage) rejects as itself. Catching everything instead turns an outage into "no key", "tampered" or "forged", and code that acts on those (writes new keys, deletes the data, signs the person out) then does damage. refusedWith(error, ...names) is the same test for a catch block. Both read the error's name alone, so a DOMException from another realm still counts.

版本与发布记录

@codefusion-cc/workers-crypto 共发布 4 个版本,首次发布于 2026/10/02;过去 12 个月发布了 4 个版本。

版本发布日期距今
0.1.2latest2026/10/041 个月前
0.1.12026/10/031 个月前
0.1.02026/10/021 个月前
1.0.02026/10/021 个月前

关于 @codefusion-cc/workers-crypto 的常见问题

@codefusion-cc/workers-crypto 是什么?

Bytes and text for tokens, signatures and webhooks on WebCrypto: base64url and base64 both ways, hex, digests (MD5 too in Workers, for payment gateways), HMAC-SHA256 signing and constant-time checking, labelled keyed hashes, a constant-time comparison and

如何安装 @codefusion-cc/workers-crypto?

在项目目录运行 npm install @codefusion-cc/workers-crypto,或使用 pnpm add / yarn add / bun add。

@codefusion-cc/workers-crypto 支持 TypeScript 吗?

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

@codefusion-cc/workers-crypto 支持 ESM 还是 CommonJS?

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

@codefusion-cc/workers-crypto 需要什么版本的 Node.js?

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

@codefusion-cc/workers-crypto 可以商用吗?

@codefusion-cc/workers-crypto 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@codefusion-cc/workers-crypto 的下载量有多少?

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

@codefusion-cc/workers-crypto 还在维护吗?

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