hash-wasm

hash-wasm

快速轻量级的WebAssembly哈希函数库

hash-wasm是一个基于WebAssembly的高性能哈希函数库,支持浏览器和Node.js环境。该库采用优化的WebAssembly实现,计算速度显著优于同类库。支持MD5、SHA系列、Argon2等主流哈希算法,具有轻量级、支持大数据流、模块化设计等特点。适用于要求高效哈希计算的Web和Node.js应用场景。

hash-wasm哈希算法WebAssembly性能优化加密Github开源项目

hash-wasm

npm包 包大小 codecov 构建状态 JSDelivr下载量

Hash-WASM是一个⚡超快速⚡的哈希函数库,适用于浏览器和Node.js。 它使用经过手动优化的WebAssembly二进制文件来计算哈希值,比其他库更快。

支持的算法

名称打包大小(gzip压缩后)
Adler-323 kB
Argon2: Argon2d, Argon2i, Argon2id (v1.3)11 kB
bcrypt11 kB
BLAKE2b6 kB
BLAKE2s5 kB
BLAKE39 kB
CRC32, CRC32C3 kB
HMAC-
MD44 kB
MD54 kB
PBKDF2-
RIPEMD-1605 kB
scrypt10 kB
SHA-15 kB
SHA-2: SHA-224, SHA-2567 kB
SHA-2: SHA-384, SHA-5128 kB
SHA-3: SHA3-224, SHA3-256, SHA3-384, SHA3-5124 kB
Keccak-224, Keccak-256, Keccak-384, Keccak-5124 kB
SM34 kB
Whirlpool6 kB
xxHash323 kB
xxHash644 kB
xxHash37 kB
xxHash1288 kB

特性

  • 比其他JS / WASM实现快得多(见下方基准测试
  • 轻量级。参见上表
  • 从高度优化的C语言算法编译而来
  • 支持所有现代浏览器、Node.js和Deno
  • 支持大型数据流
  • 支持UTF-8字符串和类型化数组
  • 支持分块输入流
  • 模块化架构(算法被编译成独立的WASM二进制文件)
  • WASM模块以base64字符串形式打包(没有链接问题)
  • 支持树摇(Webpack只打包你使用的哈希算法)
  • 无需Webpack或其他打包工具即可工作
  • 包含TypeScript类型定义
  • 可在Web Workers中工作
  • 零依赖
  • 支持使用多个状态进行并发哈希计算
  • 支持保存和加载哈希的内部状态(分段哈希和回溯)
  • 所有算法都有单元测试
  • 100%开源且透明的构建过程
  • 易于使用的基于Promise的API

安装

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>

示例

演示应用

哈希计算器 - 源代码

使用HTML5 File API的MD5文件哈希计算器

使用简写形式

这是计算哈希的最简单和最快速的方法。当输入缓冲区已经在内存中时使用它。

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参考

使用Argon2对密码进行哈希处理

选择参数的推荐过程可以在这里找到: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参考

使用bcrypt对密码进行哈希处理

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

所有支持的哈希函数都可用于计算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

所有支持的哈希函数都可用于计算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/>

浏览器支持

<br/>
ChromeSafariFirefoxEdgeIENode.jsDeno
57+11+53+16+不支持8+1+
<br/>

基准测试

你可以在这里进行自己的测量:链接

测量了两种场景:

  • 短格式的吞吐量(输入大小 = 32字节)
  • 长格式的吞吐量(输入大小 = 1MB)

结果:

MD5吞吐量(32字节)吞吐量(1MB)
hash-wasm 4.4.157.43 MB/s596.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.147.97 MB/s649.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.135.67 MB/s254.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.122.91 MB/s177.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.188.33 MB/s12 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.1348 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.1256 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倍)
<br/>

* 这些测量是在Kaby Lake桌面CPU上使用Chrome v89进行的。

API

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)

编辑推荐精选

TRAE编程

TRAE编程

AI辅助编程,代码自动修复

Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。

AI工具TraeAI IDE协作生产力转型热门
蛙蛙写作

蛙蛙写作

AI小说写作助手,一站式润色、改写、扩写

蛙蛙写作—国内先进的AI写作平台,涵盖小说、学术、社交媒体等多场景。提供续写、改写、润色等功能,助力创作者高效优化写作流程。界面简洁,功能全面,适合各类写作者提升内容品质和工作效率。

AI辅助写作AI工具蛙蛙写作AI写作工具学术助手办公助手营销助手AI助手
问小白

问小白

全能AI智能助手,随时解答生活与工作的多样问题

问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松管理个人事务。

热门AI助手AI对话AI工具聊天机器人
Transly

Transly

实时语音翻译/同声传译工具

Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。

讯飞智文

讯飞智文

一键生成PPT和Word,让学习生活更轻松

讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。

AI办公办公工具AI工具讯飞智文AI在线生成PPTAI撰写助手多语种文档生成AI自动配图热门
讯飞星火

讯飞星火

深度推理能力全新升级,全面对标OpenAI o1

科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。

热门AI开发模型训练AI工具讯飞星火大模型智能问答内容创作多语种支持智慧生活
Spark-TTS

Spark-TTS

一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型

Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。

咔片PPT

咔片PPT

AI助力,做PPT更简单!

咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。

讯飞绘文

讯飞绘文

选题、配图、成文,一站式创作,让内容运营更高效

讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。

热门AI辅助写作AI工具讯飞绘文内容运营AI创作个性化文章多平台分发AI助手
材料星

材料星

专业的AI公文写作平台,公文写作神器

AI 材料星,专业的 AI 公文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。

下拉加载更多