paulmillr/noble-hashes

GitHub: paulmillr/noble-hashes

一款经过审计、极简且跨平台的 JavaScript 密码学哈希、MAC 和 KDF 实现库。

Stars: 844 | Forks: 62

# noble-hashes 经过审计且极简的哈希函数、MAC 和 KDF 的 JS 实现。 - 🔒 由独立安全公司[**审计**](#security) - 🔻 Tree-shakeable:未使用的代码会被排除在你的构建之外 - 🏎 快速:针对 JS 引擎的特性进行了手工优化 - 🔍 可靠:经过链式/滑动窗口/DoS/ACVP 测试和模糊测试 - 🔁 无循环展开:更易于验证,并将源代码大小减少了多达 5 倍 - 🦘 包括 SHA, RIPEMD, BLAKE, HMAC, HKDF, PBKDF, Scrypt, Argon2 - 🥈 可选的、友好的原生 WebCrypto 封装 - 🪶 全部功能 22KB (gzipped),单哈希构建 2.4KB 如果你需要更快的 (WASM) 替代方案,请使用 [awasm-noble](https://github.com/paulmillr/awasm-noble)。 请查看 [升级](#upgrading) 以获取有关从先前版本升级的信息。 请浏览 [GitHub Discussions](https://github.com/paulmillr/noble-hashes/discussions) 以提问和寻求支持。 该库的初始开发由 [Ethereum Foundation](https://ethereum.org/) 资助。 ### 该库属于 _noble_ 密码学系列 - 零或极少的依赖 - 高度可读的 TypeScript / JS 代码 - PGP 签名的发布和透明的 NPM 构建 - 所有库: [ciphers](https://github.com/paulmillr/noble-ciphers), [curves](https://github.com/paulmillr/noble-curves), [hashes](https://github.com/paulmillr/noble-hashes), [post-quantum](https://github.com/paulmillr/noble-post-quantum), 5kb [secp256k1](https://github.com/paulmillr/noble-secp256k1) / [ed25519](https://github.com/paulmillr/noble-ed25519) - [查看主页](https://paulmillr.com/noble/) 以获取阅读资源、文档和使用 noble 构建的应用 ## 用法 我们支持所有主要平台和运行时。 对于 React Native,你可能需要一个 [getRandomValues 的 polyfill](https://github.com/LinusU/react-native-get-random-values)。 还提供了一个独立文件 [noble-hashes.js](https://github.com/paulmillr/noble-hashes/releases)。 ``` // import * from '@noble/hashes'; // Error: use sub-imports, to ensure small app size import { sha256 as noble_sha256 } from '@noble/hashes/sha2.js'; const hash = noble_sha256(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])); // Available modules import { sha256, sha384, sha512, sha224, sha512_224, sha512_256 } from '@noble/hashes/sha2.js'; import { sha3_256, sha3_512, keccak_256, keccak_512, shake128, shake256, } from '@noble/hashes/sha3.js'; import { cshake256, turboshake256, kmac256, tuplehash256, kt128, kt256, keccakprg, } from '@noble/hashes/sha3-addons.js'; import { blake3 } from '@noble/hashes/blake3.js'; import { blake2b, blake2s } from '@noble/hashes/blake2.js'; import { blake256, blake512 } from '@noble/hashes/blake1.js'; import { sha1, md5, ripemd160 } from '@noble/hashes/legacy.js'; import { hmac } from '@noble/hashes/hmac.js'; import { hkdf } from '@noble/hashes/hkdf.js'; import { pbkdf2, pbkdf2Async } from '@noble/hashes/pbkdf2.js'; import { scrypt, scryptAsync } from '@noble/hashes/scrypt.js'; import { argon2d, argon2i, argon2id } from '@noble/hashes/argon2.js'; import * as webcrypto from '@noble/hashes/webcrypto.js'; // const { sha256, sha384, sha512, hmac, hkdf, pbkdf2 } = webcrypto; import * as utils from '@noble/hashes/utils.js'; const { bytesToHex, concatBytes, equalBytes, hexToBytes } = utils; ``` - [sha2: sha256, sha384, sha512](#sha2-sha256-sha384-sha512-and-others) - [sha3: FIPS, SHAKE, Keccak](#sha3-fips-shake-keccak) - [sha3-addons: cSHAKE, KMAC, KT128, TurboSHAKE](#sha3-addons-cshake-kmac-kt128-turboshake) - [blake1, blake2, blake3](#blake1-blake2-blake3) - [legacy: sha1, md5, ripemd160](#legacy-sha1-md5-ripemd160) - MACs: [hmac](#hmac) | [kmac](#sha3-addons-cshake-kmac-kt128-turboshake) | [blake3 key mode](#blake1-blake2-blake3) - KDFs: [hkdf](#hkdf) | [pbkdf2](#pbkdf2) | [scrypt](#scrypt) | [argon2](#argon2) - [webcrypto: 友好的封装](#webcrypto-friendly-wrapper) - [utils](#utils) - [安全性](#security) | [速度](#speed) | [贡献与测试](#contributing--testing) | [许可证](#license) ### 实现 哈希函数: - `sha256()`:接收并返回 `Uint8Array` - `sha256.create().update(a).update(b).digest()`:支持部分更新 - `blake3.create({ context: 'e', dkLen: 32 })`:可以带有选项 - 支持小端架构;也实验性地支持大端 - 每个块最多可哈希 4GB,块数量不限 #### sha2: sha256, sha384, sha512 及其他 ``` import { sha224, sha256, sha384, sha512, sha512_224, sha512_256 } from '@noble/hashes/sha2.js'; const res = sha256(Uint8Array.from([0xbc])); // basic for (let hash of [sha256, sha384, sha512, sha224, sha512_224, sha512_256]) { const arr = Uint8Array.from([0x10, 0x20, 0x30]); const a = hash(arr); const b = hash.create().update(arr).digest(); } ``` 查看 [RFC 4634](https://datatracker.ietf.org/doc/html/rfc4634) 和 [关于截断 SHA512/256 的论文](https://eprint.iacr.org/2010/548.pdf)。 #### sha3: FIPS、SHAKE、Keccak ``` import { sha3_224, sha3_256, sha3_384, sha3_512, keccak_224, keccak_256, keccak_384, keccak_512, shake128, shake256, } from '@noble/hashes/sha3.js'; for (let hash of [ sha3_224, sha3_256, sha3_384, sha3_512, keccak_224, keccak_256, keccak_384, keccak_512, ]) { const arr = Uint8Array.from([0x10, 0x20, 0x30]); const a = hash(arr); const b = hash.create().update(arr).digest(); } const shka = shake128(Uint8Array.from([0x10]), { dkLen: 512 }); const shkb = shake256(Uint8Array.from([0x30]), { dkLen: 512 }); ``` 查看 [FIPS-202](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf), [网站](https://keccak.team/keccak.html)。 查看 [SHA-3 和 Keccak 之间的区别](https://crypto.stackexchange.com/questions/15727/what-are-the-key-differences-between-the-draft-sha-3-standard-and-the-keccak-sub) #### sha3-addons: cSHAKE、KMAC、K12、TurboSHAKE ``` import { cshake128, cshake256, kt128, kt256, keccakprg, kmac128, kmac256, parallelhash256, tuplehash256, turboshake128, turboshake256, } from '@noble/hashes/sha3-addons.js'; const data = Uint8Array.from([0x10, 0x20, 0x30]); const personalization = new TextEncoder().encode('def'); const ec1 = cshake128(data, { personalization }); const ec2 = cshake256(data, { personalization }); const et1 = turboshake128(data); const et2 = turboshake256(data, { D: 0x05 }); // tuplehash(['ab', 'c']) !== tuplehash(['a', 'bc']) !== tuplehash([data]) const et3 = tuplehash256([new TextEncoder().encode('ab'), new TextEncoder().encode('c')]); // Not parallel in JS (similar to blake3 / kt128), added for compat const ep1 = parallelhash256(data, { blockLen: 8 }); const kk = Uint8Array.from([0xca]); const ek10 = kmac128(kk, data); const ek11 = kmac256(kk, data); const ek12 = kt128(data); // kangarootwelve 128-bit const ek13 = kt256(data); // kangarootwelve 256-bit // pseudo-random generator, first argument is capacity. XKCP recommends 254 bits capacity for 128-bit security strength. // * with a capacity of 254 bits. const p = keccakprg(254); p.addEntropy(Uint8Array.from([1, 2, 3])); const rand1b = p.randomBytes(32); ``` - cSHAKE, KMAC, TupleHash, ParallelHash + XOF 均可用,符合 [NIST SP 800-185](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf) - 减少轮次的 Keccak KT128 (KangarooTwelve 🦘, K12) 和 TurboSHAKE 均可用,符合 [RFC 9861](https://datatracker.ietf.org/doc/rfc9861/). - [KeccakPRG](https://keccak.team/files/CSF-0.1.pdf):基于 Keccak 的伪随机生成器 #### blake1、blake2、blake3 ``` import { blake224, blake256, blake384, blake512 } from '@noble/hashes/blake1.js'; import { blake2b, blake2s } from '@noble/hashes/blake2.js'; import { blake3 } from '@noble/hashes/blake3.js'; for (let hash of [blake224, blake256, blake384, blake512, blake2b, blake2s, blake3]) { const arr = Uint8Array.from([0x10, 0x20, 0x30]); const a = hash(arr); const b = hash.create().update(arr).digest(); } // blake2 advanced usage const ab = Uint8Array.from([0x01]); const txt = new TextEncoder(); blake2s(ab); blake2s(ab, { key: new Uint8Array(32) }); blake2s(ab, { personalization: txt.encode('pers1234') }); blake2s(ab, { salt: txt.encode('salt1234') }); blake2b(ab); blake2b(ab, { key: new Uint8Array(64) }); blake2b(ab, { personalization: txt.encode('pers1234pers1234') }); blake2b(ab, { salt: txt.encode('salt1234salt1234') }); // blake3 advanced usage blake3(ab); blake3(ab, { dkLen: 256 }); blake3(ab, { key: new Uint8Array(32) }); blake3(ab, { context: txt.encode('application-name') }); ``` - Blake1 是遗留哈希,是 SHA3 提案之一。它很少在任何地方使用。见 [pdf](https://www.aumasson.jp/blake/blake.pdf)。 - Blake2 是流行的快速哈希。blake2b 专注于 64 位平台,而 blake2s 适用于 8 位到 32 位平台。见 [RFC 7693](https://datatracker.ietf.org/doc/html/rfc7693),[网站](https://www.blake2.net) - Blake3 更快,是减少轮次的 blake2。见 [网站 & 规范](https://blake3.io) #### legacy: sha1、md5、ripemd160 SHA1 (RFC 3174), MD5 (RFC 1321) 和 RIPEMD160 (RFC 2286) 遗留的、弱哈希函数。 不要在新协议中使用它们。“弱”意味着: - MD5 可以在 2^18 的努力下产生碰撞,SHA1 为 2^60,RIPEMD160 为 2^80。 - 没有实际的原图攻击(只有理论上的,2^123.4) - HMAC 似乎还可以:https://datatracker.ietf.org/doc/html/rfc6151 ``` import { md5, ripemd160, sha1 } from '@noble/hashes/legacy.js'; for (let hash of [md5, ripemd160, sha1]) { const arr = Uint8Array.from([0x10, 0x20, 0x30]); const a = hash(arr); const b = hash.create().update(arr).digest(); } ``` #### hmac ``` import { hmac } from '@noble/hashes/hmac.js'; import { sha256 } from '@noble/hashes/sha2.js'; const key = new Uint8Array(32).fill(1); const msg = new Uint8Array(32).fill(2); const mac1 = hmac(sha256, key, msg); const mac2 = hmac.create(sha256, key).update(msg).digest(); ``` 符合 [RFC 2104](https://datatracker.ietf.org/doc/html/rfc2104)。 #### hkdf ``` import { hkdf } from '@noble/hashes/hkdf.js'; import { randomBytes } from '@noble/hashes/utils.js'; import { sha256 } from '@noble/hashes/sha2.js'; const inputKey = randomBytes(32); const salt = randomBytes(32); const info = new TextEncoder().encode('application-key'); const hk1 = hkdf(sha256, inputKey, salt, info, 32); // == same as import { extract, expand } from '@noble/hashes/hkdf.js'; const prk = extract(sha256, inputKey, salt); const hk2 = expand(sha256, prk, info, 32); ``` 符合 [RFC 5869](https://datatracker.ietf.org/doc/html/rfc5869)。 #### pbkdf2 ``` import { pbkdf2, pbkdf2Async } from '@noble/hashes/pbkdf2.js'; import { sha256 } from '@noble/hashes/sha2.js'; const pbkey1 = pbkdf2(sha256, 'password', 'salt', { c: 524288, dkLen: 32 }); const pbkey2 = await pbkdf2Async(sha256, 'password', 'salt', { c: 524288, dkLen: 32 }); const pbkey3 = await pbkdf2Async(sha256, Uint8Array.from([1, 2, 3]), Uint8Array.from([4, 5, 6]), { c: 524288, dkLen: 32, }); ``` 符合 [RFC 2898](https://datatracker.ietf.org/doc/html/rfc2898)。 #### scrypt ``` import { scrypt, scryptAsync } from '@noble/hashes/scrypt.js'; const scr1 = scrypt('password', 'salt', { N: 2 ** 16, r: 8, p: 1, dkLen: 32 }); const scr2 = await scryptAsync('password', 'salt', { N: 2 ** 16, r: 8, p: 1, dkLen: 32 }); const scr3 = await scryptAsync(Uint8Array.from([1, 2, 3]), Uint8Array.from([4, 5, 6]), { N: 2 ** 17, r: 8, p: 1, dkLen: 32, onProgress(percentage) { console.log('progress', percentage); }, maxmem: 2 ** 32 + 128 * 8 * 1, // N * r * p * 128 + (128*r*p) }); ``` 符合 [RFC 7914](https://datatracker.ietf.org/doc/html/rfc7914), [网站](https://www.tarsnap.com/scrypt.html) - `N, r, p` 是工作量因子。通常只调整 N,同时保持 `r: 8, p: 1`。 见[博客文章](https://blog.filippo.io/the-scrypt-parameters/)。 JS 不支持并行化,使得增加 `p` 毫无意义。 - `dkLen` 是输出字节的长度,例如 `32` 或 `64` - `onProgress` 可以与函数的异步版本一起使用,以向用户报告进度。 - `maxmem` 防止 DoS,限制为 `1GB + 1KB` (`2**30 + 2**10`),但可以使用公式调整:`N * r * p * 128 + (128 * r * p)` 在 Apple M4 上使用不同的 N (2\*\*N) 值派生 Scrypt 密钥所需的时间(手机可能会慢 1x-4x): | N pow | 时间 | RAM | | ----- | ---- | ----- | | 16 | 0.1s | 64MB | | 17 | 0.2s | 128MB | | 18 | 0.4s | 256MB | | 19 | 0.8s | 512MB | | 20 | 1.5s | 1GB | | 21 | 3.1s | 2GB | | 22 | 6.2s | 4GB | | 23 | 13s | 8GB | | 24 | 27s | 16GB | #### argon2 ``` import { argon2d, argon2i, argon2id } from '@noble/hashes/argon2.js'; const arg1 = argon2id('password', 'saltsalt', { t: 2, m: 65536, p: 1, maxmem: 2 ** 32 - 1 }); ``` Argon2 [RFC 9106](https://datatracker.ietf.org/doc/html/rfc9106) 实现。 #### webcrypto: 友好的封装 ``` import { sha256, sha384, sha512, hmac, hkdf, pbkdf2 } from '@noble/hashes/webcrypto.js'; import { randomBytes } from '@noble/hashes/utils.js'; const whash = await sha256(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])); const key = new Uint8Array(32).fill(1); const msg = new Uint8Array(32).fill(2); const wmac = await hmac(sha256, key, msg); const inputKey = randomBytes(32); const salt = randomBytes(32); const info = new TextEncoder().encode('application-key'); const hk1 = await hkdf(sha256, inputKey, salt, info, 32); const pbkey1 = await pbkdf2(sha256, 'password', 'salt', { c: 524288, dkLen: 32 }); ``` 有时人们想使用内置的 `crypto.subtle` 而不是纯 JS 实现。 然而,它的 API 很糟糕。 我们使用镜像 noble-hashes 的 API 简化了对内置功能的访问。 开销极小 - 只有 30 多行代码,用于验证输入的正确性。 #### utils ``` import { bytesToHex as toHex, randomBytes } from '@noble/hashes/utils.js'; console.log(toHex(randomBytes(32))); ``` - `bytesToHex` 将 `Uint8Array` 转换为十六进制字符串 - `randomBytes(bytes)` 将生成密码学安全的、长度为 `bytes` 的随机 `Uint8Array` ## 安全性 该库已经过审计: - 在 2.1.0 版本,2026 年 4 月,由我们自己(自我审计) - 范围:所有内容 - [审计后的变更](https://github.com/paulmillr/noble-hashes/compare/2.1.0..main) - 在 1.0.0 版本,2022 年 1 月,独立由 [Cure53](https://cure53.de) 进行 - PDF:[网站](https://cure53.de/pentest-report_hashing-libs.pdf),[仓库内](./audit/2022-01-05-cure53-audit-nbl2.pdf) - 范围:除 `blake3`, `sha3-addons`, `sha1` 和 `argon2` 之外的所有内容,这些未被审计 - 审计由 [Ethereum Foundation](https://ethereum.org/en/) 在 [Nomic Labs](https://nomiclabs.io) 的帮助下资助 它经过了基于属性的、跨库的和 Wycheproof 向量的测试, 并在[单独的仓库](https://github.com/paulmillr/fuzzing)中进行模糊测试。 如果你发现任何异常:请调查并报告。 ### 恒定时间性 我们的目标是算法上的恒定时间。_JIT-compiler_ 和 _Garbage Collector_ 使得在脚本语言中 极难实现针对[计时攻击](https://en.wikipedia.org/wiki/Timing_attack)的抵抗能力。 这意味着_任何其他 JS 库都无法实现恒定时间性_。即使是静态类型的 Rust,一种没有 GC 的语言, [在某些情况下也更难实现恒定时间](https://www.chosenplaintext.ca/open-source/rust-timing-shield/security)。 如果你的目标是绝对安全,不要使用任何 JS 库——包括绑定到原生代码的库。 请使用底层库和语言。 ### 内存转储 该库在哈希函数调用之间共享状态缓冲区。 缓冲区在每次调用后被清零。但是,如果攻击者能够读取应用程序内存, 无论如何你都注定在劫难逃: - 在某些时候,输入将是一个字符串,而字符串在 JS 中是不可变的: 无法用零覆盖它们。例如:从 `scrypt(password, salt)` 派生密钥,其中 password 和 salt 是字符串 - 来自文件的输入将保留在文件缓冲区中 - 输入/输出将在应用程序中多次重用,这意味着它可能保留在内存中 - `await anything()` 总是将所有内部变量(包括数字)写入 内存。对于异步函数/Promises,无法保证代码块何时执行。 这意味着攻击者有充足的时间从内存中读取数据 - 如果没有复杂的测试套件(将转储进程内存并验证没有 敏感数据残留),就无法保证任何关于清零敏感数据的事情。 对于 JS,这意味着测试所有浏览器(包括移动端), 这很复杂。当然,如果不使用相同的测试套件在实际使用该库的应用程序中进行测试,这将是徒劳的。 ### 供应链安全 - **提交** 使用 PGP 密钥签名以防伪造。请务必验证提交签名 - **发布** 通过无令牌的 GitHub CI 和可信发布透明进行。请务必验证 [来源日志](https://docs.npmjs.com/generating-provenance-statements) 的真实性。 - **极少发布** 以最大限度地减少最终用户重新审计的需要。 - **依赖** 被最小化并严格锁定以降低供应链风险。 - 我们使用尽可能少的依赖。 - 版本范围被锁定,并使用 npm-diff 检查更改。 - **开发依赖** 从最终用户安装中排除;它们仅用于开发和构建步骤。 对于此包,有 0 个依赖项;以及一些开发依赖项: - jsbt 包含用于构建、基准测试和测试安全 JS 应用程序的助手。它由同一作者开发 - prettier, fast-check 和 typescript 用于代码质量/测试生成/ts 编译 ### 随机性 我们依赖内置的 [`crypto.getRandomValues`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues), 这被认为是密码学安全的 PRNG。 浏览器过去曾有弱点——将来可能还会有——但实现用户空间 CSPRNG 更糟糕,因为没有可靠的用户空间高质量熵源。 ### 量子计算机 如果建造出密码学相关的量子计算机,将允许利用 Grover 算法在 2^n/2 次操作中破解哈希,而不是 2^n。 这意味着 SHA256 应被替换为 SHA512,SHA3-256 应被替换为 SHA3-512,SHAKE128 应被替换为 SHAKE256 等。 澳大利亚 ASD [在 2030 年之后](https://www.cyber.gov.au/resources-business-and-government/essential-cyber-security/ism/cyber-security-guidelines/guidelines-cryptography) 禁止使用 SHA256 和类似的哈希。 ## 升级 支持的 node.js 版本: - v2: v20.19+ (仅 ESM) - v1: v14.21+ (M & CJS) v2.0 更新日志: - 该包现在仅支持 ESM。ESM 终于可以在 node v20.19+ 上从 common.js 加载 - 所有模块必须使用 `.js` 扩展名 - 旧版:`@noble/hashes/sha3` - 新版:`@noble/hashes/sha3.js` - 这简化了在没有转译器的情况下在浏览器中原生工作 - 仅允许 Uint8Array 作为哈希输入,禁止 `string` - 严格的验证检查提高了安全性 - 要复制先前的行为,请使用 `utils.utf8ToBytes` - 重命名/删除某些模块以保持一致性。以前,sha384 位于 sha512 中,这很奇怪 - `sha256`, `sha512` => `sha2.js` (与 `sha3.js` 一致) - `blake2b`, `blake2s` => `blake2.js` (与 `blake3.js`, `blake1.js` 一致) - `ripemd160`, `sha1`, `md5` => `legacy.js` (所有低安全性哈希都在那里) - `_assert` => `utils.js` - `crypto` 内部模块已删除:请改用内置 WebCrypto - 改进 typescript 类型和选项自动补全 - 将编译目标从 es2020 提升到 es2022 ## 贡献与测试 `test/misc` 目录包含循环展开和 md5 的实现。 - `npm install && npm run build && npm test` 将构建代码并运行测试。 - `npm run lint` / `npm run format` 将运行 linter/修复 linter 问题。 - `npm run bench` 将运行基准测试 - `npm run build:release` 将构建单个文件 - 有**额外的** 20 分钟 DoS 测试 `npm run test:dos` 和 2 小时多核测试 `npm run test:slow`。 请参阅[我们的测试方法](./test/README.md) 某些哈希不在此库的范围内: - [micro-zk-proofs 中的 Pedersen](https://github.com/paulmillr/micro-zk-proofs/blob/1ed5ce1253583b2e540eef7f3477fb52bf5344ff/src/pedersen.ts) - [noble-curves 中的 Poseidon](https://github.com/paulmillr/noble-curves/blob/3d124dd3ecec8b6634cc0b2ba1c183aded5304f9/src/abstract/poseidon.ts) - [noble-ciphers 中的 Poly1305 & GHash](https://github.com/paulmillr/noble-ciphers) 请参阅 [paulmillr.com/noble](https://paulmillr.com/noble/) 获取与该库相关的有用资源、文章、文档和演示。 ## 速度 ``` npm run bench ``` 基准测试在 Apple M4 上测量。如果你需要真正卓越的性能,请切换到 [awasm-noble](https://github.com/paulmillr/awasm-noble)。 ``` # 32B sha256 x 2,016,129 ops/sec @ 496ns/op sha512 x 740,740 ops/sec @ 1μs/op sha3_256 x 287,686 ops/sec @ 3μs/op sha3_512 x 288,267 ops/sec @ 3μs/op k12 x 476,190 ops/sec @ 2μs/op blake2b x 410,340 ops/sec @ 2μs/op blake2s x 942,507 ops/sec @ 1μs/op blake3 x 1,006,036 ops/sec @ 994ns/op ripemd160 x 1,410,437 ops/sec @ 709ns/op md5 x 1,663,893 ops/sec @ 601ns/op sha1 x 1,589,825 ops/sec @ 629ns/op # 1MB sha256 x 331 ops/sec @ 3ms/op sha512 x 128 ops/sec @ 7ms/op sha3_256 x 39 ops/sec @ 25ms/op sha3_512 x 21 ops/sec @ 46ms/op kt128 x 91 ops/sec @ 10ms/op kt256 x 75 ops/sec @ 13ms/op turboshake128 x 93 ops/sec @ 10ms/op blake256 x 57 ops/sec @ 17ms/op blake2b x 61 ops/sec @ 16ms/op blake2s x 78 ops/sec @ 12ms/op blake3 x 95 ops/sec @ 10ms/op ripemd160 x 177 ops/sec @ 5ms/op md5 x 250 ops/sec @ 3ms/op sha1 x 416 ops/sec @ 2ms/op # MAC hmac(sha256) x 599,880 ops/sec @ 1μs/op hmac(sha512) x 197,122 ops/sec @ 5μs/op kmac256 x 87,981 ops/sec @ 11μs/op blake3(key) x 796,812 ops/sec @ 1μs/op # KDF hkdf(sha256) x 259,942 ops/sec @ 3μs/op blake3(context) x 424,808 ops/sec @ 2μs/op pbkdf2(sha256, c: 2 ** 18) x 5 ops/sec @ 197ms/op pbkdf2(sha512, c: 2 ** 18) x 1 ops/sec @ 630ms/op scrypt(n: 2 ** 18, r: 8, p: 1) x 2 ops/sec @ 400ms/op argon2id(t: 1, m: 256MB) 2881ms ``` 该库可以通过利用循环展开快 3 倍。未使用它是因为展开 a) 会增加包大小 b) 使库不可读 c) 当前性能对于大多数用例来说“足够快”。 ## 许可证 The MIT License (MIT) Copyright (c) 2022 Paul Miller [(https://paulmillr.com)](https://paulmillr.com) 请参阅 LICENSE 文件。
标签:Argon2, BLAKE, CMS安全, DNS 反向解析, GNU通用公共许可证, HKDF, HMAC, JavaScript, KDF, MAC, MITM代理, Noble, Node.js, PBKDF2, POC验证, RIPEMD, Scrypt, SHA, StruQ, Tree-shaking, TypeScript, WebCrypto, 前端安全, 加密库, 哈希函数, 哈希算法, 安全插件, 密码学, 密钥派生, 手动系统调用, 数据可视化, 本体建模, 消息认证码, 自动化攻击, 零依赖