tinyhmacmd5 0.4.2 → 0.5.0-es2026
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -18
- package/README.md +56 -85
- package/browser.min.js +1 -1
- package/main.js +5 -15
- package/package.json +4 -4
package/LICENSE
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
This is free and unencumbered software released into the public domain.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Anyone is free to copy, modify, publish, use, compile, sell, or
|
|
4
|
+
distribute this software, either in source code form or as a compiled
|
|
5
|
+
binary, for any purpose, commercial or non-commercial, and by any
|
|
6
|
+
means.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
this software
|
|
9
|
-
the
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
In jurisdictions that recognize copyright laws, the author or authors
|
|
9
|
+
of this software dedicate any and all copyright interest in the
|
|
10
|
+
software to the public domain. We make this dedication for the benefit
|
|
11
|
+
of the public at large and to the detriment of our heirs and
|
|
12
|
+
successors. We intend this dedication to be an overt act of
|
|
13
|
+
relinquishment in perpetuity of all present and future rights to this
|
|
14
|
+
software under copyright law.
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
|
+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
20
|
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
21
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
|
16
23
|
|
|
17
|
-
|
|
18
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
19
|
-
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
20
|
-
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
21
|
-
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
22
|
-
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
24
|
+
For more information, please refer to <https://unlicense.org/>
|
package/README.md
CHANGED
|
@@ -4,32 +4,65 @@ English | [中文](README-zh.md)
|
|
|
4
4
|
|
|
5
5
|
A tiny and reliable HMAC-MD5 implementation for JavaScript:
|
|
6
6
|
|
|
7
|
-
[`browser.min.js`](browser.min.js) is only **
|
|
7
|
+
[`browser.min.js`](browser.min.js) is only **947 bytes**.
|
|
8
8
|
|
|
9
9
|
- **Input type**: `string` (UTF‑8), `Uint8Array` or `Uint8ClampedArray`
|
|
10
10
|
- **Output type**: hex `string` or bytes `Uint8Array`
|
|
11
|
-
- **Supports inputs ≥ 512 MiB**: The input length theoretically supports 0 to 2⁵³-
|
|
11
|
+
- **Supports inputs ≥ 512 MiB**: The input length theoretically supports 0 to 2⁵³-137
|
|
12
12
|
- **TypeScript‑ready**: [`main.d.ts`](main.d.ts)
|
|
13
13
|
- **0 dependencies**
|
|
14
14
|
|
|
15
15
|
**Live demo**: https://bddjr.github.io/tinyhmacmd5/
|
|
16
16
|
|
|
17
|
-
`tinyhmacmd5` does not simply aim for the smallest possible size.
|
|
18
|
-
Its goal is to balance code size and runtime performance, so some performance-oriented implementations are intentionally retained.
|
|
19
|
-
As a result, the final size is not the smallest theoretically achievable.
|
|
20
|
-
|
|
21
17
|
If you need a smaller implementation that targets ECMAScript 2026, see the [`es2026`](https://github.com/bddjr/tinyhmacmd5/tree/es2026) branch.
|
|
22
18
|
|
|
23
19
|
> [!WARNING]
|
|
24
20
|
> MD5 is cryptographically broken and unsafe for security-sensitive applications.
|
|
25
21
|
> Do not rely on it for password hashing, digital signatures, or certificate verification.
|
|
26
22
|
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Benchmark
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
pnpm benchmark
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
Data length: 104857600 chars (100MiB)
|
|
33
|
+
--------------------------------------------------
|
|
34
|
+
tinyhmacmd5 : 550.92 ms
|
|
35
|
+
js-md5 : 128.96 ms
|
|
36
|
+
blueimp-md5 : 3837.83 ms
|
|
37
|
+
crypto-js : 1562.08 ms
|
|
38
|
+
node:crypto : 129.08 ms
|
|
39
|
+
--------------------------------------------------
|
|
40
|
+
✅ All pure JS implementations match node:crypto result.
|
|
41
|
+
|
|
42
|
+
--- Pure 513MiB Test (No prior small tests) ---
|
|
43
|
+
tinyhmacmd5 HMAC-MD5 timer: 2.706s
|
|
44
|
+
node:crypto HMAC-MD5 timer: 547.808ms
|
|
45
|
+
tinyhmacmd5 MD5 timer: 2.693s
|
|
46
|
+
node:crypto MD5 timer: 550.144ms
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
CPU: i5-10600KF
|
|
50
|
+
DRAM: 64GiB DDR4 3333MT/s
|
|
51
|
+
OS: Windows 11 Pro for Workstations 25H2 26200.8737
|
|
52
|
+
Node.js: v26.8.1
|
|
53
|
+
|
|
54
|
+
`tinyhmacmd5` does not simply aim for the smallest possible size.
|
|
55
|
+
Its goal is to balance code size and runtime performance, so some performance-oriented implementations are intentionally retained.
|
|
56
|
+
As a result, the final size is not the smallest theoretically achievable.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
27
60
|
## Setup
|
|
28
61
|
|
|
29
62
|
### npm
|
|
30
63
|
|
|
31
64
|
```
|
|
32
|
-
npm i tinyhmacmd5
|
|
65
|
+
npm i tinyhmacmd5@es2026
|
|
33
66
|
```
|
|
34
67
|
|
|
35
68
|
```js
|
|
@@ -45,7 +78,7 @@ You can also use other package managers (e.g. `pnpm` or `yarn`) in place of `npm
|
|
|
45
78
|
See https://www.jsdelivr.com/package/npm/tinyhmacmd5
|
|
46
79
|
|
|
47
80
|
```html
|
|
48
|
-
<script src="https://cdn.jsdelivr.net/npm/tinyhmacmd5"></script>
|
|
81
|
+
<script src="https://cdn.jsdelivr.net/npm/tinyhmacmd5@es2026"></script>
|
|
49
82
|
```
|
|
50
83
|
|
|
51
84
|
It will define the `md5` function using `var`.
|
|
@@ -53,7 +86,7 @@ It will define the `md5` function using `var`.
|
|
|
53
86
|
### UNPKG
|
|
54
87
|
|
|
55
88
|
```html
|
|
56
|
-
<script src="https://unpkg.com/tinyhmacmd5"></script>
|
|
89
|
+
<script src="https://unpkg.com/tinyhmacmd5@es2026"></script>
|
|
57
90
|
```
|
|
58
91
|
|
|
59
92
|
It will define the `md5` function using `var`.
|
|
@@ -67,10 +100,6 @@ It will define the `md5` function using `var`.
|
|
|
67
100
|
|
|
68
101
|
## Example
|
|
69
102
|
|
|
70
|
-
> [!NOTE]
|
|
71
|
-
> Please ensure that the input type matches the definition in [`main.d.ts`](main.d.ts).
|
|
72
|
-
> Invalid types may return an incorrect MD5 hash.
|
|
73
|
-
|
|
74
103
|
HMAC-MD5:
|
|
75
104
|
|
|
76
105
|
```js
|
|
@@ -144,88 +173,30 @@ md5(data)
|
|
|
144
173
|
|
|
145
174
|
## Runtime Environment
|
|
146
175
|
|
|
147
|
-
Environments that support [
|
|
176
|
+
Environments that support [`Uint8Array.prototype.toHex()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array/toHex) :
|
|
148
177
|
|
|
149
178
|
- Desktop
|
|
150
|
-
- Chrome ≥
|
|
151
|
-
- Edge ≥
|
|
152
|
-
- Firefox ≥
|
|
153
|
-
- Opera ≥
|
|
154
|
-
- Safari ≥
|
|
179
|
+
- Chrome ≥ 140 (2025-09-02)
|
|
180
|
+
- Edge ≥ 140 (2025-09-05)
|
|
181
|
+
- Firefox ≥ 133 (2024-11-26)
|
|
182
|
+
- Opera ≥ 124 (2025-11-13)
|
|
183
|
+
- Safari ≥ 18.2 (2024-12-11)
|
|
155
184
|
- Mobile
|
|
156
|
-
- Chrome Android ≥
|
|
157
|
-
- Firefox for Android ≥
|
|
158
|
-
- Opera Android ≥
|
|
159
|
-
- Safari on iOS ≥
|
|
160
|
-
- Samsung Browser
|
|
161
|
-
- WebView Android ≥
|
|
162
|
-
- WebView on iOS ≥
|
|
185
|
+
- Chrome Android ≥ 140 (2025-09-02)
|
|
186
|
+
- Firefox for Android ≥ 133 (2024-11-26)
|
|
187
|
+
- Opera Android ≥ 92 (2025-10-08)
|
|
188
|
+
- Safari on iOS ≥ 18.2 (2024-12-11)
|
|
189
|
+
- Samsung Browser ×
|
|
190
|
+
- WebView Android ≥ 140 (2025-09-02)
|
|
191
|
+
- WebView on iOS ≥ 18.2 (2024-12-11)
|
|
163
192
|
|
|
164
193
|
Not recommended for use in environments that support `node:crypto`, as `node:crypto` already provides HMAC-MD5.
|
|
165
194
|
|
|
166
195
|
---
|
|
167
196
|
|
|
168
|
-
## Benchmark
|
|
169
|
-
|
|
170
|
-
```
|
|
171
|
-
pnpm benchmark
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
```
|
|
175
|
-
Data length: 104857600 chars (100MiB)
|
|
176
|
-
--------------------------------------------------
|
|
177
|
-
tinyhmacmd5 : 550.92 ms
|
|
178
|
-
js-md5 : 128.96 ms
|
|
179
|
-
blueimp-md5 : 3837.83 ms
|
|
180
|
-
crypto-js : 1562.08 ms
|
|
181
|
-
node:crypto : 129.08 ms
|
|
182
|
-
--------------------------------------------------
|
|
183
|
-
✅ All pure JS implementations match node:crypto result.
|
|
184
|
-
|
|
185
|
-
--- Pure 513MiB Test (No prior small tests) ---
|
|
186
|
-
tinyhmacmd5 HMAC-MD5 timer: 2.706s
|
|
187
|
-
node:crypto HMAC-MD5 timer: 547.808ms
|
|
188
|
-
tinyhmacmd5 MD5 timer: 2.693s
|
|
189
|
-
node:crypto MD5 timer: 550.144ms
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
CPU: i5-10600KF
|
|
193
|
-
DRAM: 64GiB DDR4 3333MT/s
|
|
194
|
-
OS: Windows 11 Pro for Workstations 25H2 26200.8737
|
|
195
|
-
Node.js: v26.8.1
|
|
196
|
-
|
|
197
|
-
---
|
|
198
|
-
|
|
199
|
-
## Why I Made This Project
|
|
200
|
-
|
|
201
|
-
I initially used HMAC-MD5 just to call a certain website's API. That site signs the request body with `crypto-js`'s HMAC-MD5 to make reverse engineering harder.
|
|
202
|
-
|
|
203
|
-
But I only needed HMAC-MD5. Depending on `crypto-js` felt way too bloated. The Web Crypto API doesn't support HMAC-MD5, so I had no choice but to drag in a dependency.
|
|
204
|
-
|
|
205
|
-
Then I found `blueimp-md5`. Its `md5.min.js` is only 3750 bytes, even smaller than `js-md5`.
|
|
206
|
-
|
|
207
|
-
But I felt `blueimp-md5` was still far too bloated. It has some completely unnecessary design choices—it repeatedly parses strings and creates new ones, adding a lot of unnecessary overhead.
|
|
208
|
-
|
|
209
|
-
So I decided to adapt it, use a more modern implementation, and shrink the size even further. That's how `tinyhmacmd5` was born.
|
|
210
|
-
|
|
211
|
-
During the adaptation, I discovered that `blueimp-md5` did not correctly handle the 64-bit length field required by MD5 when the input bit-length exceeded 32 bits. It wrote only the low 32 bits and ignored the high 32 bits. I fixed this bug.
|
|
212
|
-
|
|
213
|
-
I also found that using `Array` to process inputs over 512 MiB could throw a `RangeError`, so I replaced it with `Int32Array`.
|
|
214
|
-
|
|
215
|
-
I demonstrated in practice that HMAC-MD5 can be implemented in an extremely small footprint (1007 bytes) while also improving reliability.
|
|
216
|
-
|
|
217
|
-
Maybe not many people care about saving just a few KB, but `tinyhmacmd5` exists precisely to "explore the unknown".
|
|
218
|
-
|
|
219
|
-
INVINCIBLE EXPERIMENT!
|
|
220
|
-
|
|
221
|
-
[Read the original Chinese text](README-zh.md#为什么做这个项目)
|
|
222
|
-
|
|
223
|
-
---
|
|
224
|
-
|
|
225
197
|
## License
|
|
226
198
|
|
|
227
|
-
|
|
228
|
-
See: [`LICENSE`](LICENSE)
|
|
199
|
+
This project is released into the public domain under the [Unlicense](https://unlicense.org).
|
|
229
200
|
|
|
230
201
|
---
|
|
231
202
|
|
package/browser.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
{let e=Int32Array,r=Uint8Array,n=new e(64).map((e,r)=>2**32*Math.abs(Math.sin(r+1))),t=1&new r(n.buffer)[3],f=(r,t,f=0,o,a=1732584193,w=271733878,l,u,h=r.length,s=e.of(a,~w,~a,w),d=new e(s))=>{for(r[h-1]=t/2**29,r[(t-t%4)/4]|=128<<(r[h-2]=t<<3);f<h;f+=16){for(t=o=0;t<16;t+=4)for(;o<4*t+16;)s[u&=3]=((w=s[u]+n[o]+(a=s[3&++u],w=s[3&++u],l=s[3&++u],w^(t>4?t>8?a|~l:a^l:t?l&(a^w):~a&(w^l)))+r[f+(o*(29521>>t)+(1296>>t)&15)])<<(l="',16%).4$+07&*/5".charCodeAt(3&o++|t))|w>>>32-l)+a;for(;u;)d[--u]=s[u]+=d[u]}return s},o=(n,f,o=("string"==typeof n?n=(new TextEncoder).encode(n):n).length,a=new e(f+18+(o-(o+8&63))/4),w=t&&new r(a.buffer,4*f).set(n))=>{for(;w<o;3&++w||f++)a[f]|=n[w]<<8*w;return[a,o]};var md5=(n,t,a)=>{var w=16,l=null!=t,[u,h]=o(n,l*w),s=new r(w);if(l){let[r,n]=o(t,0),a=new e(32);for(n>64&&(r=f(r,n)),n=w;n;)a[--n]=1785358954^(u[n]=909522486^r[n]);a.set(f(u,64+h),w),u=a,h=80}for(u=f(u,h);w;)s[--w]=u[w>>2]>>8*w;return a?s:s.toHex()}}
|
package/main.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/*! npmjs.com/tinyhmacmd5 */
|
|
2
|
-
|
|
3
|
-
// Adapted from https://github.com/blueimp/JavaScript-MD5
|
|
4
|
-
|
|
5
1
|
let $Int32Array = Int32Array
|
|
6
2
|
|
|
7
3
|
let $Uint8Array = Uint8Array
|
|
@@ -125,13 +121,11 @@ let inputToWords = (
|
|
|
125
121
|
* @param {boolean} [raw] If true, the hash is returned as raw bytes (Uint8Array); otherwise, as a hex string.
|
|
126
122
|
* @returns {string | Uint8Array<ArrayBuffer>} The MD5 (or HMAC‑MD5) digest, either as a hex string or a Uint8Array.
|
|
127
123
|
*/
|
|
128
|
-
|
|
124
|
+
let md5 = (data, key, raw) => {
|
|
129
125
|
var i = 16
|
|
130
126
|
, hasKey = key != null
|
|
131
127
|
, [bdata, temp] = inputToWords(data, /**@type {*}*/(hasKey) * i)
|
|
132
|
-
|
|
133
|
-
/** @type {*} */
|
|
134
|
-
var out = raw ? new $Uint8Array(i) : ''
|
|
128
|
+
, out = new $Uint8Array(i)
|
|
135
129
|
|
|
136
130
|
if (hasKey) {
|
|
137
131
|
// HMAC
|
|
@@ -152,15 +146,11 @@ var md5 = (data, key, raw) => {
|
|
|
152
146
|
bdata = wordsMD5(bdata, temp)
|
|
153
147
|
|
|
154
148
|
// words to bytes or hex
|
|
155
|
-
for (; i;
|
|
156
|
-
|
|
157
|
-
? out[i] = temp
|
|
158
|
-
: out = (temp >> 4 && '') + temp.toString(16) + out
|
|
159
|
-
) {
|
|
160
|
-
temp = bdata[--i >> 2] >> i * 8 & 0xff
|
|
149
|
+
for (; i;) {
|
|
150
|
+
out[--i] = bdata[i >> 2] >> i * 8
|
|
161
151
|
}
|
|
162
152
|
|
|
163
|
-
return out
|
|
153
|
+
return raw ? out : out.toHex()
|
|
164
154
|
}
|
|
165
155
|
|
|
166
156
|
export default md5
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tinyhmacmd5",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "A tiny and reliable HMAC-MD5 implementation for JavaScript: browser.min.js is only
|
|
3
|
+
"version": "0.5.0-es2026",
|
|
4
|
+
"description": "A tiny and reliable HMAC-MD5 implementation for JavaScript: browser.min.js is only 947 bytes.",
|
|
5
5
|
"author": "bddjr",
|
|
6
|
-
"license": "
|
|
6
|
+
"license": "Unlicense",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "main.js",
|
|
9
9
|
"types": "main.d.ts",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"typescript": "^7.0.2"
|
|
64
64
|
},
|
|
65
65
|
"scripts": {
|
|
66
|
-
"build": "tsc && node scripts/build.mjs && es-check
|
|
66
|
+
"build": "tsc && node scripts/build.mjs && es-check es2026 --module --checkFeatures main.js browser.min.js",
|
|
67
67
|
"build:unchanged": "node scripts/build-unchanged.mjs",
|
|
68
68
|
"test": "pnpm build && pnpm test:only",
|
|
69
69
|
"test:only": "node scripts/test.mjs && node scripts/test-513MiB.mjs",
|