快速轻量级的WebAssembly哈希函数库
hash-wasm是一个基于WebAssembly的高性能哈希函数库,支持浏览器和Node.js环境。该库采用优化的WebAssembly实现,计算速度显著优于同类库。支持MD5、SHA系列、Argon2等主流哈希算法,具有轻量级、支持大数据流、模块化设计等特点。适用于要求高效哈希计算的Web和Node.js应用场景。
Hash-WASM是一个⚡超快速⚡的哈希函数库,适用于浏览器和Node.js。 它使用经过手动优化的WebAssembly二进制文件来计算哈希值,比其他库更快。
名称 | 打包大小(gzip压缩后) |
---|---|
Adler-32 | 3 kB |
Argon2: Argon2d, Argon2i, Argon2id (v1.3) | 11 kB |
bcrypt | 11 kB |
BLAKE2b | 6 kB |
BLAKE2s | 5 kB |
BLAKE3 | 9 kB |
CRC32, CRC32C | 3 kB |
HMAC | - |
MD4 | 4 kB |
MD5 | 4 kB |
PBKDF2 | - |
RIPEMD-160 | 5 kB |
scrypt | 10 kB |
SHA-1 | 5 kB |
SHA-2: SHA-224, SHA-256 | 7 kB |
SHA-2: SHA-384, SHA-512 | 8 kB |
SHA-3: SHA3-224, SHA3-256, SHA3-384, SHA3-512 | 4 kB |
Keccak-224, Keccak-256, Keccak-384, Keccak-512 | 4 kB |
SM3 | 4 kB |
Whirlpool | 6 kB |
xxHash32 | 3 kB |
xxHash64 | 4 kB |
xxHash3 | 7 kB |
xxHash128 | 8 kB |
npm i hash-wasm
也可以直接在HTML中使用(通过jsDelivr):
<!-- 将所有算法加载到全局变量 `hashwasm` 中 --> <script src="https://cdn.jsdelivr.net/npm/hash-wasm@4"></script> <!-- 将单个算法加载到全局变量 `hashwasm` 中 --> <script src="https://cdn.jsdelivr.net/npm/hash-wasm@4/dist/md5.umd.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/hash-wasm@4/dist/hmac.umd.min.js"></script>
这是计算哈希的最简单和最快速的方法。当输入缓冲区已经在内存中时使用它。
import { md5, sha1, sha512, sha3 } from 'hash-wasm'; async function run() { console.log('MD5:', await md5('demo')); const int8Buffer = new Uint8Array([0, 1, 2, 3]); console.log('SHA1:', await sha1(int8Buffer)); console.log('SHA512:', await sha512(int8Buffer)); const int32Buffer = new Uint32Array([1056, 641]); console.log('SHA3-256:', await sha3(int32Buffer, 256)); } run();
* 参见字符串编码陷阱
** 参见API参考
createXXXX() 函数创建具有单独状态的新WASM实例,可用于并行计算多个哈希值。与重用相同WASM实例和状态进行多次计算的简写函数(如md5())相比,它们的速度较慢。因此,当数据已经在内存中时,始终首选简写形式。
为了获得最佳性能,避免在循环中调用createXXXX()函数。当顺序计算多个哈希值时,可以使用init()函数在运行之间重置内部状态。这比使用createXXXX()创建新实例更快。
import { createSHA1 } from 'hash-wasm'; async function run() { const sha1 = await createSHA1(); sha1.init(); while (hasMoreData()) { const chunk = readChunk(); sha1.update(chunk); } const hash = sha1.digest('binary'); // 返回Uint8Array console.log('SHA1:', hash); } run();
* 参见字符串编码陷阱
** 参见API参考
选择参数的推荐过程可以在这里找到:https://tools.ietf.org/html/draft-irtf-cfrg-argon2-04#section-4
import { argon2id, argon2Verify } from 'hash-wasm'; async function run() { const salt = new Uint8Array(16); window.crypto.getRandomValues(salt); const key = await argon2id({ password: 'pass', salt, // salt是包含随机字节的缓冲区 parallelism: 1, iterations: 256, memorySize: 512, // 使用512KB内存 hashLength: 32, // 输出大小 = 32字节 outputType: 'encoded', // 返回包含验证密钥所需参数的标准编码字符串 }); console.log('派生密钥:', key); const isValid = await argon2Verify({ password: 'pass', hash: key, }); console.log(isValid ? '密码有效' : '密码无效'); } run();
* 参见字符串编码陷阱
** 参见API参考
import { bcrypt, bcryptVerify } from 'hash-wasm'; async function run() { const salt = new Uint8Array(16); window.crypto.getRandomValues(salt); const key = await bcrypt({ password: 'pass', salt, // salt是包含16个随机字节的缓冲区 costFactor: 11, outputType: 'encoded', // 返回包含验证密钥所需参数的标准编码字符串 }); console.log('派生密钥:', key); const isValid = await bcryptVerify({ password: 'pass', hash: key, }); console.log(isValid ? '密码有效' : '密码无效'); } run();
* 参见字符串编码陷阱
** 参见API参考
所有支持的哈希函数都可用于计算HMAC。为了获得最佳性能,避免在循环中调用createXXXX()(参见上面的"使用流式输入的高级用法"部分)
import { createHMAC, createSHA3 } from 'hash-wasm'; async function run() { const hashFunc = createSHA3(224); // SHA3-224 const hmac = await createHMAC(hashFunc, 'key'); const fruits = ['apple', 'raspberry', 'watermelon']; console.log('输入:', fruits); const codes = fruits.map(data => { hmac.init(); hmac.update(data); return hmac.digest(); }); console.log('HMAC:', codes); } run();
* 参见字符串编码陷阱
** 参见API参考
所有支持的哈希函数都可用于计算PBKDF2。为了获得最佳性能,避免在循环中调用createXXXX()(参见上面的"使用流式输入的高级用法"部分)
import { pbkdf2, createSHA1 } from 'hash-wasm'; async function run() { const salt = new Uint8Array(16); window.crypto.getRandomValues(salt); const key = await pbkdf2({ password: 'password', salt, iterations: 1000, hashLength: 32, hashFunction: createSHA1(), outputType: 'hex', }); console.log('派生密钥:', key); } run();
* 参见字符串编码陷阱
** 参见API参考
你应该注意到,一个给定的字符串可能有多种UTF-8表示:
'\u00fc' // 编码ü字符 'u\u0308' // 也编码ü字符 '\u00fc' === 'u\u0308' // false 'ü' === 'ü' // false
此库中定义的所有算法都依赖于输入字符串的二进制表示。因此,强烈建议在将字符串传递给hash-wasm之前对其进行规范化。你可以使用内置的String函数normalize()
来实现这一点:
'\u00fc'.normalize() === 'u\u0308'.normalize() // true const te = new TextEncoder(); te.encode('u\u0308'); // Uint8Array(3) [117, 204, 136] te.encode('\u00fc'); // Uint8Array(2) [195, 188] te.encode('u\u0308'.normalize('NFKC')); // Uint8Array(2) [195, 188] te.encode('\u00fc'.normalize('NFKC')); // Uint8Array(2) [195, 188]
你可以在这里阅读更多关于这个问题的信息:https://en.wikipedia.org/wiki/Unicode_equivalence
你可以使用.save()
函数保存哈希的当前内部状态。这个状态可以写入磁盘或存储在内存的其他位置。
然后你可以使用.load(state)
函数将该状态重新加载到哈希的新实例中,或者加载回同一个实例。
这允许你将哈希文件的工作跨多个进程进行(例如在像AWS Lambda这样执行时间有限的环境中,大型作业需要跨多个调用分割),或者将哈希回退到流中的早期点。例如,第一个进程可以:
// 第一个进程开始哈希计算 const md5 = await createMD5(); md5.init(); md5.update("Hello, "); const state = md5.save(); // 保存这个状态 // 第二个进程从存储的状态恢复哈希计算 const md5 = await createMD5(); md5.load(state); md5.update("world!"); console.log(md5.digest()); // 输出 6cd3556deb0da54bca060b4c39479839 = md5("Hello, world!")
注意,保存和加载进程必须运行兼容版本的哈希函数(即在保存和加载进程中使用的hash-wasm版本之间哈希函数没有变化)。如果保存的状态不兼容,load()
将抛出异常。
保存的状态可能包含有关输入的信息,包括明文输入字节,因此从安全角度来看,它必须与输入数据本身一样谨慎处理。
<br/>Chrome | Safari | Firefox | Edge | IE | Node.js | Deno |
---|---|---|---|---|---|---|
57+ | 11+ | 53+ | 16+ | 不支持 | 8+ | 1+ |
你可以在这里进行自己的测量:链接
测量了两种场景:
结果:
MD5 | 吞吐量(32字节) | 吞吐量(1MB) |
---|---|---|
hash-wasm 4.4.1 | 57.43 MB/s | 596.64 MB/s |
spark-md5 3.0.1 (来自npm) | 28.08 MB/s (慢2.0倍) | 110.12 MB/s (慢5.4倍) |
md5-wasm 2.0.0 (来自npm) | 16.49 MB/s (慢3.4倍) | 74.43 MB/s (慢8.0倍) |
crypto-js 4.0.0 (来自npm) | 3.80 MB/s (慢15倍) | 26.70 MB/s (慢22倍) |
node-forge 0.10.0 (来自npm) | 9.28 MB/s (慢6.2倍) | 12.27 MB/s (慢49倍) |
md5 2.3.0 (来自npm) | 7.66 MB/s (慢7.5倍) | 11.42 MB/s (慢52倍) |
SHA1 | 吞吐量(32字节) | 吞吐量(1MB) |
---|---|---|
hash-wasm 4.4.1 | 47.97 MB/s | 649.13 MB/s |
jsSHA 3.2.0 (来自npm) | 6.15 MB/s (慢7.8倍) | 46.13 MB/s (慢14倍) |
crypto-js 4.0.0 (来自npm) | 4.10 MB/s (慢12倍) | 40.36 MB/s (慢16倍) |
sha1 1.1.1 (来自npm) | 6.86 MB/s (慢7.0倍) | 12.46 MB/s (慢52倍) |
node-forge 0.10.0 (来自npm) | 8.71 MB/s (慢5.5倍) | 12.86 MB/s (慢50倍) |
SHA256 | 吞吐量(32字节) | 吞吐量(1MB) |
---|---|---|
hash-wasm 4.4.1 | 35.67 MB/s | 254.40 MB/s |
sha256-wasm 2.1.2 (来自npm) | 17.83 MB/s (慢2倍) | 164.13 MB/s (慢1.5倍) |
jsSHA 3.2.0 (来自npm) | 5.57 MB/s (慢6.4倍) | 35.81 MB/s (慢7.1倍) |
crypto-js 4.0.0 (来自npm) | 3.51 MB/s (慢10倍) | 36.48 MB/s (慢7倍) |
node-forge 0.10.0 (来自npm) | 6.81 MB/s (慢5.2倍) | 11.91 MB/s (慢21倍) |
SHA3-512 | 吞吐量(32字节) | 吞吐量(1MB) |
---|---|---|
hash-wasm 4.4.1 | 22.91 MB/s | 177.16 MB/s |
sha3-wasm 1.0.0 (来自npm) | 7.16 MB/s (慢3.2倍) | 74.75 MB/s (慢2.4倍) |
sha3 2.1.4 (来自npm) | 2.00 MB/s (慢11倍) | 6.48 MB/s (慢27倍) |
jsSHA 3.2.0 (来自npm) | 0.93 MB/s (慢24倍) | 2.09 MB/s (慢85倍) |
XXHash64 | 吞吐量(32字节) | 吞吐量(1MB) |
---|---|---|
hash-wasm 4.4.1 | 88.33 MB/s | 12 012.74 MB/s |
xxhash-wasm 0.4.1 (来自npm) | 28.44 MB/s (慢3.1倍) | 11 296.84 MB/s |
xxhashjs 0.2.2 (来自npm) | 0.37 MB/s (慢239倍) | 17.95 MB/s (慢669倍) |
PBKDF2-SHA512 - 1000次迭代 | 每秒操作次数(16字节) |
---|---|
hash-wasm 4.4.1 | 348 ops |
pbkdf2 3.1.1 (来自npm) | 55 ops (慢6.3倍) |
crypto-js 4.0.0 (来自npm) | 13 ops (慢27倍) |
Argon2id (m=512, t=8, p=1) | 每秒操作次数(16字节) |
---|---|
hash-wasm 4.4.1 | 256 ops |
argon2-browser 1.15.3 (来自npm) | 104 ops (慢2.5倍) |
argon2-wasm 0.9.0 (来自npm) | 101 ops (慢2.5倍) |
argon2-wasm-pro 1.1.0 (来自npm) | 100 ops (慢2.5倍) |
* 这些测量是在Kaby Lake桌面CPU上使用Chrome v89
进行的。
type IDataType = string | Buffer | Uint8Array | Uint16Array | Uint32Array; // 所有函数返回十六进制格式的哈希值 adler32(data: IDataType): Promise<string> blake2b(data: IDataType, bits?: number, key?: IDataType): Promise<string> // 默认为512位 blake2s(data: IDataType, bits?: number, key?: IDataType): Promise<string> // 默认为256位 blake3(data: IDataType, bits?: number, key?: IDataType): Promise<string> // 默认为256位 crc32(data: IDataType): Promise<string> crc32c(data: IDataType): Promise<string> keccak(data: IDataType, bits?: 224 | 256 | 384 | 512): Promise<string> // 默认为512位 md4(data: IDataType): Promise<string> md5(data: IDataType): Promise<string> ripemd160(data: IDataType): Promise<string> sha1(data: IDataType): Promise<string> sha224(data: IDataType): Promise<string> sha256(data: IDataType): Promise<string> sha3(data: IDataType, bits?: 224 | 256 | 384 | 512): Promise<string> // 默认为512位 sha384(data: IDataType): Promise<string> sha512(data: IDataType): Promise<string> sm3(data: IDataType): Promise<string> whirlpool(data: IDataType): Promise<string> xxhash32(data: IDataType, seed?: number): Promise<string> xxhash64(data: IDataType, seedLow?: number, seedHigh?: number): Promise<string> xxhash3(data: IDataType, seedLow?: number, seedHigh?: number): Promise<string> xxhash128(data: IDataType, seedLow?: number, seedHigh?: number): Promise<string> interface IHasher { init: () => IHasher; update: (data: IDataType) => IHasher; digest: (outputType: 'hex' | 'binary') => string | Uint8Array; // 默认返回十六进制字符串 save: () => Uint8Array; // 返回内部状态以供后续恢复 load: (state: Uint8Array) => IHasher; // 加载先前保存的内部状态 blockSize: number; // 以字节为单位 digestSize: number; // 以字节为单位 } createAdler32(): Promise<IHasher> createBLAKE2b(bits?: number, key?: IDataType): Promise<IHasher> // 默认为512位 createBLAKE2s(bits?: number, key?: IDataType): Promise<IHasher> // 默认为256位 createBLAKE3(bits?: number, key?: IDataType): Promise<IHasher> // 默认为256位 createCRC32(): Promise<IHasher> createCRC32C(): Promise<IHasher> createKeccak(bits?: 224 | 256 | 384 | 512): Promise<IHasher> // 默认为512位 createMD4(): Promise<IHasher> createMD5(): Promise<IHasher> createRIPEMD160(): Promise<IHasher> createSHA1(): Promise<IHasher> createSHA224(): Promise<IHasher> createSHA256(): Promise<IHasher> createSHA3(bits?: 224 | 256 | 384 | 512): Promise<IHasher> // 默认为512位 createSHA384(): Promise<IHasher> createSHA512(): Promise<IHasher> createSM3(): Promise<IHasher> createWhirlpool(): Promise<IHasher> createXXHash32(seed: number): Promise<IHasher> createXXHash64(seedLow: number, seedHigh: number): Promise<IHasher> createXXHash3(seedLow: number, seedHigh: number): Promise<IHasher> createXXHash128(seedLow: number, seedHigh: number): Promise<IHasher> createHMAC(hashFunction: Promise<IHasher>, key: IDataType): Promise<IHasher> pbkdf2({ password: IDataType, // 要哈希的密码(或消息) salt: IDataType, // 盐(通常包含随机字节) iterations: number, // 执行迭代的次数 hashLength: number, // 输出大小(字节) hashFunction: Promise<IHasher>, // 像createSHA1()这样函数的返回值 outputType?: 'hex' | 'binary', // 默认返回十六进制字符串 }): Promise<string | Uint8Array> scrypt({ password: IDataType, // 要哈希的密码(或消息) salt: IDataType, // 盐(通常包含随机字节) costFactor: number, // CPU/内存成本 - 必须是2的幂(如1024) blockSize: number, // 块大小参数(通常使用8) parallelism: number, // 并行度 hashLength: number, // 输出大小(字节) outputType?: 'hex' | 'binary', // 默认返回十六进制字符串 }): Promise<string | Uint8Array> interface IArgon2Options { password: IDataType; // 要哈希的密码(或消息) salt: IDataType; // 盐(通常包含随机字节) secret?: IDataType; // 用于键控哈希的密钥 iterations: number; // 执行迭代的次数 parallelism: number; // 并行度 memorySize: number; // 要使用的内存量(以kibibytes为单位,1024字节) hashLength: number; // 输出大小(字节) outputType?: 'hex' | 'binary' | 'encoded'; // 默认返回十六进制字符串 } argon2i(options: IArgon2Options): Promise<string | Uint8Array> argon2d(options: IArgon2Options): Promise<string | Uint8Array> argon2id(options: IArgon2Options): Promise<string | Uint8Array> argon2Verify({ password: IDataType, // 密码 secret?: IDataType, // 哈希创建时使用的密钥 hash: string, // 编码后的哈希 }): Promise<boolean> bcrypt({ password: IDataType, // 密码 salt: IDataType, // 盐(16字节长 - 通常包含随机字节) costFactor: number, // 执行迭代的次数(4 - 31) outputType?: 'hex' | 'binary' | 'encoded', // 默认返回编码字符串 }): Promise<string | Uint8Array> bcryptVerify({ password: IDataType, // 密码 hash: string, // 编码后的哈希 }): Promise<boolean> 未来计划 ===== - 添加更多知名算法 - 编写一个多填充程序,保持打包大小小,并支持运行包含较新WASM指令的二进制文件 - 使用WebAssembly批量内存操作 - 使用WebAssembly SIMD指令(预期性能提升10-20%) - 在可能的情况下启用多线程(如Argon2)
AI辅助编程,代码自动修复
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。
AI小说写作助手,一站式润色、改写、扩写
蛙蛙写作—国内先进的AI写作平台,涵盖小说、学术、社交媒体等多场景。提供续写、改写、润色等功能,助力创作者高效优化写作流程。界面简洁,功能全面,适合各类写作者提升内容品质和工作效率。
全能AI智能助手,随时解答生活与工作的多样问题
问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松管理个人事务。
实时语音翻译/同声传译工具
Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。
一键生成PPT和Word,让学习生活更轻松
讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。
深度推理能力全新升级,全面对标OpenAI o1
科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。
一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型
Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语 音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。
AI助力,做PPT更简单!
咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。
选题、配图、成文,一站式创作,让内容运营更高效
讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。
专业的AI公文写作平台,公文写作神器
AI 材料星,专业的 AI 公文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。
最新AI工具、AI资讯
独家AI资源、AI项目落地
微信扫一扫关注公众号