tinyhmacmd5 0.5.0 → 0.5.1-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/README.md +41 -31
- package/browser.min.js +1 -1
- package/main.js +41 -53
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -2,9 +2,9 @@ English | [中文](README-zh.md)
|
|
|
2
2
|
|
|
3
3
|
# Tiny HMAC MD5
|
|
4
4
|
|
|
5
|
-
A tiny and reliable HMAC-MD5 implementation for JavaScript
|
|
5
|
+
A tiny, efficient 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 **923 bytes**.
|
|
8
8
|
|
|
9
9
|
- **Input type**: `string` (UTF‑8), `Uint8Array` or `Uint8ClampedArray`
|
|
10
10
|
- **Output type**: hex `string` or bytes `Uint8Array`
|
|
@@ -25,25 +25,23 @@ If you need a smaller implementation that targets ECMAScript 2026, see the [`es2
|
|
|
25
25
|
## Benchmark
|
|
26
26
|
|
|
27
27
|
```
|
|
28
|
-
pnpm benchmark
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
```
|
|
28
|
+
> pnpm benchmark
|
|
29
|
+
$ node scripts/benchmark.mjs && node scripts/test-513MiB.mjs
|
|
32
30
|
Data length: 104857600 chars (100MiB)
|
|
33
31
|
--------------------------------------------------
|
|
34
|
-
tinyhmacmd5 :
|
|
35
|
-
js-md5 : 128.
|
|
36
|
-
blueimp-md5 :
|
|
37
|
-
crypto-js :
|
|
38
|
-
node:crypto : 129.
|
|
32
|
+
tinyhmacmd5 : 388.35 ms
|
|
33
|
+
js-md5 : 128.71 ms
|
|
34
|
+
blueimp-md5 : 3823.48 ms
|
|
35
|
+
crypto-js : 1553.58 ms
|
|
36
|
+
node:crypto : 129.86 ms
|
|
39
37
|
--------------------------------------------------
|
|
40
38
|
✅ All pure JS implementations match node:crypto result.
|
|
41
39
|
|
|
42
40
|
--- Pure 513MiB Test (No prior small tests) ---
|
|
43
|
-
tinyhmacmd5 HMAC-MD5 timer:
|
|
44
|
-
node:crypto HMAC-MD5 timer:
|
|
45
|
-
tinyhmacmd5 MD5 timer:
|
|
46
|
-
node:crypto MD5 timer:
|
|
41
|
+
tinyhmacmd5 HMAC-MD5 timer: 1.886s
|
|
42
|
+
node:crypto HMAC-MD5 timer: 548.216ms
|
|
43
|
+
tinyhmacmd5 MD5 timer: 1.868s
|
|
44
|
+
node:crypto MD5 timer: 548.352ms
|
|
47
45
|
```
|
|
48
46
|
|
|
49
47
|
CPU: i5-10600KF
|
|
@@ -62,7 +60,7 @@ As a result, the final size is not the smallest theoretically achievable.
|
|
|
62
60
|
### npm
|
|
63
61
|
|
|
64
62
|
```
|
|
65
|
-
npm i tinyhmacmd5
|
|
63
|
+
npm i tinyhmacmd5@es2026
|
|
66
64
|
```
|
|
67
65
|
|
|
68
66
|
```js
|
|
@@ -78,7 +76,7 @@ You can also use other package managers (e.g. `pnpm` or `yarn`) in place of `npm
|
|
|
78
76
|
See https://www.jsdelivr.com/package/npm/tinyhmacmd5
|
|
79
77
|
|
|
80
78
|
```html
|
|
81
|
-
<script src="https://cdn.jsdelivr.net/npm/tinyhmacmd5"></script>
|
|
79
|
+
<script src="https://cdn.jsdelivr.net/npm/tinyhmacmd5@es2026"></script>
|
|
82
80
|
```
|
|
83
81
|
|
|
84
82
|
It will define the `md5` function using `var`.
|
|
@@ -86,7 +84,7 @@ It will define the `md5` function using `var`.
|
|
|
86
84
|
### UNPKG
|
|
87
85
|
|
|
88
86
|
```html
|
|
89
|
-
<script src="https://unpkg.com/tinyhmacmd5"></script>
|
|
87
|
+
<script src="https://unpkg.com/tinyhmacmd5@es2026"></script>
|
|
90
88
|
```
|
|
91
89
|
|
|
92
90
|
It will define the `md5` function using `var`.
|
|
@@ -96,6 +94,12 @@ It will define the `md5` function using `var`.
|
|
|
96
94
|
You can embed [`browser.min.js`](browser.min.js) directly into your script.
|
|
97
95
|
It will define the `md5` function using `var`.
|
|
98
96
|
|
|
97
|
+
If you are concerned that others might not recognize what this is, you can add the following comment:
|
|
98
|
+
|
|
99
|
+
```js
|
|
100
|
+
// tinyhmacmd5 (The Unlicense)
|
|
101
|
+
```
|
|
102
|
+
|
|
99
103
|
---
|
|
100
104
|
|
|
101
105
|
## Example
|
|
@@ -173,22 +177,22 @@ md5(data)
|
|
|
173
177
|
|
|
174
178
|
## Runtime Environment
|
|
175
179
|
|
|
176
|
-
Environments that support [
|
|
180
|
+
Environments that support [`Uint8Array.prototype.toHex()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array/toHex) :
|
|
177
181
|
|
|
178
182
|
- Desktop
|
|
179
|
-
- Chrome ≥
|
|
180
|
-
- Edge ≥
|
|
181
|
-
- Firefox ≥
|
|
182
|
-
- Opera ≥
|
|
183
|
-
- Safari ≥
|
|
183
|
+
- Chrome ≥ 140 (2025-09-02)
|
|
184
|
+
- Edge ≥ 140 (2025-09-05)
|
|
185
|
+
- Firefox ≥ 133 (2024-11-26)
|
|
186
|
+
- Opera ≥ 124 (2025-11-13)
|
|
187
|
+
- Safari ≥ 18.2 (2024-12-11)
|
|
184
188
|
- Mobile
|
|
185
|
-
- Chrome Android ≥
|
|
186
|
-
- Firefox for Android ≥
|
|
187
|
-
- Opera Android ≥
|
|
188
|
-
- Safari on iOS ≥
|
|
189
|
-
- Samsung Browser
|
|
190
|
-
- WebView Android ≥
|
|
191
|
-
- WebView on iOS ≥
|
|
189
|
+
- Chrome Android ≥ 140 (2025-09-02)
|
|
190
|
+
- Firefox for Android ≥ 133 (2024-11-26)
|
|
191
|
+
- Opera Android ≥ 92 (2025-10-08)
|
|
192
|
+
- Safari on iOS ≥ 18.2 (2024-12-11)
|
|
193
|
+
- Samsung Browser ×
|
|
194
|
+
- WebView Android ≥ 140 (2025-09-02)
|
|
195
|
+
- WebView on iOS ≥ 18.2 (2024-12-11)
|
|
192
196
|
|
|
193
197
|
Not recommended for use in environments that support `node:crypto`, as `node:crypto` already provides HMAC-MD5.
|
|
194
198
|
|
|
@@ -208,3 +212,9 @@ cd tinyhmacmd5
|
|
|
208
212
|
pnpm i
|
|
209
213
|
pnpm test
|
|
210
214
|
```
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
##
|
|
219
|
+
|
|
220
|
+
INVINCIBLE EXPERIMENT!
|
package/browser.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{let e=Int32Array,r=Uint8Array,n=new e(64).map((e,r)=>2**32*Math.
|
|
1
|
+
{let e=Int32Array,r=Uint8Array,n=new e(64).map((e,r)=>2**32*Math.sin(++r%Math.PI)),t=(r,t,f=0,o=1732584193,a=271733878,l=e.of(o,~a,~o,a),w=r.length)=>{for(r[w-1]=t/2**29,r[(t-t%4)/4]|=128<<(r[w-2]=t<<3);f<w;f+=16){let{0:e,1:w,2:u,3:h}=l;for(t=o=0;t<16;t+=4)for(;o<4*t+16;w=0|((e+=n[o]+(u^(t>4?t>8?w|~h:w^h:t?h&(w^u):~w&(u^h)))+r[f+(o++*(29521>>t)+(1296>>t)&15)])<<a|e>>>32-a)+(e=h,h=u,u=w))a="',16%).4$+07&*/5".charCodeAt(3&o|t);l[0]+=e,l[1]+=w,l[2]+=u,l[3]+=h}return l},f=(t,f,o=("string"==typeof t?t=(new TextEncoder).encode(t):t).length,a=new e(f+18+(o-(o+8&63))/4),l=1&new r(n.buffer)[3]&&new r(a.buffer,4*f).set(t))=>{for(;l<o;3&++l||f++)a[f]|=t[l]<<8*l;return[a,o]};var md5=(n,o,a)=>{var l=16,w=null!=o,[u,h]=f(n,w*l),d=new r(l);if(w){let[r,n]=f(o,0),a=new e(32);for(n>64&&(r=t(r,n)),n=l;n;)a[--n]=1785358954^(u[n]=909522486^r[n]);a.set(t(u,64+h),l),u=a,h=80}for(u=t(u,h);l;)d[--l]=u[l>>2]>>8*l;return a?d:d.toHex()}}
|
package/main.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
+
// tinyhmacmd5 (The Unlicense)
|
|
2
|
+
|
|
1
3
|
let $Int32Array = Int32Array
|
|
2
4
|
|
|
3
5
|
let $Uint8Array = Uint8Array
|
|
4
6
|
|
|
5
7
|
/** MD5 constants cached in memory */
|
|
6
|
-
let K = new $Int32Array(64).map((v, i) => 2 ** 32 * Math.
|
|
7
|
-
|
|
8
|
-
/** is little-endian */
|
|
9
|
-
let isLE = new $Uint8Array(K.buffer)[3] & 1
|
|
8
|
+
let K = new $Int32Array(64).map((v, i) => 2 ** 32 * Math.sin(++i % Math.PI))
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* Calculate the MD5 of an array of little-endian words, and a byte length.
|
|
@@ -14,10 +13,6 @@ let isLE = new $Uint8Array(K.buffer)[3] & 1
|
|
|
14
13
|
* @param {Int32Array<ArrayBuffer>} x little-endian words
|
|
15
14
|
* @param {number} l Byte length
|
|
16
15
|
*
|
|
17
|
-
* @param {number} [j]
|
|
18
|
-
* @param {number} [t2]
|
|
19
|
-
* @param {number} [oi]
|
|
20
|
-
*
|
|
21
16
|
* @returns {Int32Array<ArrayBuffer>} MD5 Array
|
|
22
17
|
*/
|
|
23
18
|
let wordsMD5 = (
|
|
@@ -25,14 +20,10 @@ let wordsMD5 = (
|
|
|
25
20
|
l,
|
|
26
21
|
// var:
|
|
27
22
|
i = 0,
|
|
28
|
-
j,
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
t2,
|
|
32
|
-
oi,
|
|
23
|
+
j = 1732584193,
|
|
24
|
+
cnt = 271733878,
|
|
25
|
+
output = $Int32Array.of(j, ~cnt, ~j, cnt),
|
|
33
26
|
xLen = x.length,
|
|
34
|
-
output = $Int32Array.of(t0, ~t1, ~t0, t1),
|
|
35
|
-
oldOutput = new $Int32Array(output),
|
|
36
27
|
) => {
|
|
37
28
|
// append padding
|
|
38
29
|
// `l` may be >= 2**32, so cannot use `>>>` as a replacement for `floor`.
|
|
@@ -41,38 +32,40 @@ let wordsMD5 = (
|
|
|
41
32
|
x[(l - l % 4) / 4] |= 0x80 << (x[xLen - 2] = l << 3);
|
|
42
33
|
|
|
43
34
|
for (; i < xLen; i += 16) {
|
|
35
|
+
// Avoid array destructuring, as invoking the iterator protocol hurts performance.
|
|
36
|
+
let { 0: a, 1: b, 2: c, 3: d } = output
|
|
44
37
|
for (l = j = 0; l < 16; l += 4) {
|
|
45
|
-
for (
|
|
46
|
-
|
|
38
|
+
for (
|
|
39
|
+
; j < 4 * l + 16
|
|
40
|
+
; b = 0 | (
|
|
47
41
|
(
|
|
48
|
-
|
|
49
|
-
output[oi] +
|
|
42
|
+
(a += (
|
|
50
43
|
K[j] +
|
|
51
|
-
(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
l
|
|
57
|
-
?
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
) + t0
|
|
44
|
+
(c ^ (
|
|
45
|
+
l > 4
|
|
46
|
+
? l > 8
|
|
47
|
+
? b | ~d // Round 4: I
|
|
48
|
+
: b ^ d // Round 3: H
|
|
49
|
+
: l
|
|
50
|
+
? d & (b ^ c) // Round 2: G
|
|
51
|
+
: ~b & (c ^ d) // Round 1: F
|
|
52
|
+
)) +
|
|
53
|
+
x[i + (j++ * (0x7351 >> l) + (0x0510 >> l) & 15)]
|
|
54
|
+
)) << cnt | a >>> 32 - cnt // Keep `32 -` so JS engines can recognize bit rotation (ROL/ROR).
|
|
55
|
+
) + (
|
|
56
|
+
a = d,
|
|
57
|
+
d = c,
|
|
58
|
+
c = b
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
) {
|
|
62
|
+
cnt = "',16%).4$+07&*/5".charCodeAt(j & 3 | l)
|
|
71
63
|
}
|
|
72
64
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
65
|
+
output[0] += a
|
|
66
|
+
output[1] += b
|
|
67
|
+
output[2] += c
|
|
68
|
+
output[3] += d
|
|
76
69
|
}
|
|
77
70
|
return output
|
|
78
71
|
}
|
|
@@ -101,7 +94,7 @@ let inputToWords = (
|
|
|
101
94
|
// so I replaced it with `Int32Array`.
|
|
102
95
|
output = new $Int32Array(j + 18 + (byteLen - (byteLen + 8 & 63)) / 4),
|
|
103
96
|
// (fast) little-endian
|
|
104
|
-
i =
|
|
97
|
+
i = new $Uint8Array(K.buffer)[3] & 1 && new $Uint8Array(output.buffer, j * 4).set(input),
|
|
105
98
|
) => {
|
|
106
99
|
// (slow) big-endian
|
|
107
100
|
for (; i < byteLen; ++i & 3 || j++) {
|
|
@@ -122,12 +115,11 @@ let inputToWords = (
|
|
|
122
115
|
* @returns {string | Uint8Array<ArrayBuffer>} The MD5 (or HMAC‑MD5) digest, either as a hex string or a Uint8Array.
|
|
123
116
|
*/
|
|
124
117
|
let md5 = (data, key, raw) => {
|
|
118
|
+
// Do not use parameter defaults to declare variables in public functions.
|
|
125
119
|
var i = 16
|
|
126
120
|
, hasKey = key != null
|
|
127
121
|
, [bdata, temp] = inputToWords(data, /**@type {*}*/(hasKey) * i)
|
|
128
|
-
|
|
129
|
-
/** @type {*} */
|
|
130
|
-
var out = raw ? new $Uint8Array(i) : ''
|
|
122
|
+
, out = new $Uint8Array(i)
|
|
131
123
|
|
|
132
124
|
if (hasKey) {
|
|
133
125
|
// HMAC
|
|
@@ -148,15 +140,11 @@ let md5 = (data, key, raw) => {
|
|
|
148
140
|
bdata = wordsMD5(bdata, temp)
|
|
149
141
|
|
|
150
142
|
// words to bytes or hex
|
|
151
|
-
for (; i;
|
|
152
|
-
|
|
153
|
-
? out[i] = temp
|
|
154
|
-
: out = (temp >> 4 && '') + temp.toString(16) + out
|
|
155
|
-
) {
|
|
156
|
-
temp = bdata[--i >> 2] >> i * 8 & 0xff
|
|
143
|
+
for (; i;) {
|
|
144
|
+
out[--i] = bdata[i >> 2] >> i * 8
|
|
157
145
|
}
|
|
158
146
|
|
|
159
|
-
return out
|
|
147
|
+
return raw ? out : out.toHex()
|
|
160
148
|
}
|
|
161
149
|
|
|
162
150
|
export default md5
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tinyhmacmd5",
|
|
3
|
-
"version": "0.5.
|
|
4
|
-
"description": "A tiny and reliable HMAC-MD5 implementation for JavaScript
|
|
3
|
+
"version": "0.5.1-es2026",
|
|
4
|
+
"description": "A tiny (923 Bytes), efficient and reliable HMAC-MD5 implementation for JavaScript.",
|
|
5
5
|
"author": "bddjr",
|
|
6
6
|
"license": "Unlicense",
|
|
7
7
|
"type": "module",
|
|
@@ -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",
|