tinyhmacmd5 0.5.1 → 0.5.2-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 +29 -28
- package/browser.min.js +1 -1
- package/main.js +33 -39
- package/package.json +4 -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,
|
|
5
|
+
A tiny, fast and reliable implementation of MD5 and HMAC-MD5 for JavaScript.
|
|
6
6
|
|
|
7
|
-
[`browser.min.js`](browser.min.js) is only **
|
|
7
|
+
[`browser.min.js`](browser.min.js) is only **905 Bytes**.
|
|
8
8
|
|
|
9
9
|
- **Input type**: `string` (UTF‑8), `Uint8Array` or `Uint8ClampedArray`
|
|
10
10
|
- **Output type**: hex `string` or bytes `Uint8Array`
|
|
@@ -29,19 +29,20 @@ If you need a smaller implementation that targets ECMAScript 2026, see the [`es2
|
|
|
29
29
|
$ node scripts/benchmark.mjs && node scripts/test-513MiB.mjs
|
|
30
30
|
Data length: 104857600 chars (100MiB)
|
|
31
31
|
--------------------------------------------------
|
|
32
|
-
tinyhmacmd5 : 388.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
crypto-js :
|
|
36
|
-
|
|
32
|
+
tinyhmacmd5 : 388.45 ms
|
|
33
|
+
spark-md5 : 520.13 ms
|
|
34
|
+
js-md5 : 480.29 ms
|
|
35
|
+
crypto-js : 1661.32 ms
|
|
36
|
+
blueimp-md5 : 3749.15 ms
|
|
37
|
+
node:crypto : 129.97 ms
|
|
37
38
|
--------------------------------------------------
|
|
38
39
|
✅ All pure JS implementations match node:crypto result.
|
|
39
40
|
|
|
40
41
|
--- Pure 513MiB Test (No prior small tests) ---
|
|
41
|
-
tinyhmacmd5 HMAC-MD5 timer: 1.
|
|
42
|
-
node:crypto HMAC-MD5 timer: 548.
|
|
43
|
-
tinyhmacmd5 MD5 timer: 1.
|
|
44
|
-
node:crypto MD5 timer:
|
|
42
|
+
tinyhmacmd5 HMAC-MD5 timer: 1.867s
|
|
43
|
+
node:crypto HMAC-MD5 timer: 548.332ms
|
|
44
|
+
tinyhmacmd5 MD5 timer: 1.869s
|
|
45
|
+
node:crypto MD5 timer: 551.244ms
|
|
45
46
|
```
|
|
46
47
|
|
|
47
48
|
CPU: i5-10600KF
|
|
@@ -60,7 +61,7 @@ As a result, the final size is not the smallest theoretically achievable.
|
|
|
60
61
|
### npm
|
|
61
62
|
|
|
62
63
|
```
|
|
63
|
-
npm i tinyhmacmd5
|
|
64
|
+
npm i tinyhmacmd5@es2026
|
|
64
65
|
```
|
|
65
66
|
|
|
66
67
|
```js
|
|
@@ -76,7 +77,7 @@ You can also use other package managers (e.g. `pnpm` or `yarn`) in place of `npm
|
|
|
76
77
|
See https://www.jsdelivr.com/package/npm/tinyhmacmd5
|
|
77
78
|
|
|
78
79
|
```html
|
|
79
|
-
<script src="https://cdn.jsdelivr.net/npm/tinyhmacmd5"></script>
|
|
80
|
+
<script src="https://cdn.jsdelivr.net/npm/tinyhmacmd5@es2026"></script>
|
|
80
81
|
```
|
|
81
82
|
|
|
82
83
|
It will define the `md5` function using `var`.
|
|
@@ -84,7 +85,7 @@ It will define the `md5` function using `var`.
|
|
|
84
85
|
### UNPKG
|
|
85
86
|
|
|
86
87
|
```html
|
|
87
|
-
<script src="https://unpkg.com/tinyhmacmd5"></script>
|
|
88
|
+
<script src="https://unpkg.com/tinyhmacmd5@es2026"></script>
|
|
88
89
|
```
|
|
89
90
|
|
|
90
91
|
It will define the `md5` function using `var`.
|
|
@@ -97,7 +98,7 @@ It will define the `md5` function using `var`.
|
|
|
97
98
|
If you are concerned that others might not recognize what this is, you can add the following comment:
|
|
98
99
|
|
|
99
100
|
```js
|
|
100
|
-
// tinyhmacmd5
|
|
101
|
+
// https://npmjs.com/tinyhmacmd5
|
|
101
102
|
```
|
|
102
103
|
|
|
103
104
|
---
|
|
@@ -177,22 +178,22 @@ md5(data)
|
|
|
177
178
|
|
|
178
179
|
## Runtime Environment
|
|
179
180
|
|
|
180
|
-
Environments that support [
|
|
181
|
+
Environments that support [`Uint8Array.prototype.toHex()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array/toHex) :
|
|
181
182
|
|
|
182
183
|
- Desktop
|
|
183
|
-
- Chrome ≥
|
|
184
|
-
- Edge ≥
|
|
185
|
-
- Firefox ≥
|
|
186
|
-
- Opera ≥
|
|
187
|
-
- Safari ≥
|
|
184
|
+
- Chrome ≥ 140 (2025-09-02)
|
|
185
|
+
- Edge ≥ 140 (2025-09-05)
|
|
186
|
+
- Firefox ≥ 133 (2024-11-26)
|
|
187
|
+
- Opera ≥ 124 (2025-11-13)
|
|
188
|
+
- Safari ≥ 18.2 (2024-12-11)
|
|
188
189
|
- Mobile
|
|
189
|
-
- Chrome Android ≥
|
|
190
|
-
- Firefox for Android ≥
|
|
191
|
-
- Opera Android ≥
|
|
192
|
-
- Safari on iOS ≥
|
|
193
|
-
- Samsung Browser
|
|
194
|
-
- WebView Android ≥
|
|
195
|
-
- WebView on iOS ≥
|
|
190
|
+
- Chrome Android ≥ 140 (2025-09-02)
|
|
191
|
+
- Firefox for Android ≥ 133 (2024-11-26)
|
|
192
|
+
- Opera Android ≥ 92 (2025-10-08)
|
|
193
|
+
- Safari on iOS ≥ 18.2 (2024-12-11)
|
|
194
|
+
- Samsung Browser ×
|
|
195
|
+
- WebView Android ≥ 140 (2025-09-02)
|
|
196
|
+
- WebView on iOS ≥ 18.2 (2024-12-11)
|
|
196
197
|
|
|
197
198
|
Not recommended for use in environments that support `node:crypto`, as `node:crypto` already provides HMAC-MD5.
|
|
198
199
|
|
package/browser.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
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},
|
|
1
|
+
{let e=Int32Array,r=Uint8Array,n=new e(64).map((e,r)=>2**32*Math.sin(++r%Math.PI)),t=1&new r(n.buffer)[0],f=e=>e.reverse(),o=(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},a=(n,o,a=("string"==typeof n?n=(new TextEncoder).encode(n):n).length,l=new e(o+18+(a-(a+8&63))/4),w=new r(l.buffer))=>(w.set(n,4*o),t&&f(w,f(l)),[l,a]);var md5=(n,l,w)=>{var u=null!=l,[h,s]=a(n,16*u);if(u){let[r,n]=a(l,0),t=new e(32),f=16;for(n>64&&(r=o(r,n));f;)t[--f]=1785358954^(h[f]=909522486^r[f]);t.set(o(h,64+s),16),h=t,s=80}return h=o(h,s),u=new r(h.buffer),t&&f(u,f(h)),w?u:u.toHex()}}
|
package/main.js
CHANGED
|
@@ -7,6 +7,12 @@ let $Uint8Array = Uint8Array
|
|
|
7
7
|
/** MD5 constants cached in memory */
|
|
8
8
|
let K = new $Int32Array(64).map((v, i) => 2 ** 32 * Math.sin(++i % Math.PI))
|
|
9
9
|
|
|
10
|
+
/** is big-endian */
|
|
11
|
+
let isBE = /** @type {0 | 1} */(new $Uint8Array(K.buffer)[0] & 1)
|
|
12
|
+
|
|
13
|
+
/** @type {(a: Uint8Array | Int32Array, ...x: any[]) => any} */
|
|
14
|
+
let reverse = a => a.reverse()
|
|
15
|
+
|
|
10
16
|
/**
|
|
11
17
|
* Calculate the MD5 of an array of little-endian words, and a byte length.
|
|
12
18
|
*
|
|
@@ -74,15 +80,13 @@ let wordsMD5 = (
|
|
|
74
80
|
* Convert bytes to an array of little-endian words
|
|
75
81
|
*
|
|
76
82
|
* @param {*} input
|
|
77
|
-
* @param {number}
|
|
78
|
-
*
|
|
79
|
-
* @param {*} [i]
|
|
83
|
+
* @param {number} padLen pad int32 length (0 or 16)
|
|
80
84
|
*
|
|
81
85
|
* @returns {[Int32Array<ArrayBuffer>, number]}
|
|
82
86
|
*/
|
|
83
87
|
let inputToWords = (
|
|
84
88
|
input,
|
|
85
|
-
|
|
89
|
+
padLen,
|
|
86
90
|
// var:
|
|
87
91
|
byteLen = (
|
|
88
92
|
// Don't replace the type check below with something like `input.big`; it's unreliable.
|
|
@@ -92,16 +96,13 @@ let inputToWords = (
|
|
|
92
96
|
).length,
|
|
93
97
|
// Using `Array` to process inputs over 512 MiB could throw a `RangeError`,
|
|
94
98
|
// so I replaced it with `Int32Array`.
|
|
95
|
-
output = new $Int32Array(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
return [output, byteLen]
|
|
104
|
-
}
|
|
99
|
+
output = new $Int32Array(padLen + 18 + (byteLen - (byteLen + 8 & 63)) / 4),
|
|
100
|
+
outputBytes = new $Uint8Array(output.buffer),
|
|
101
|
+
) => (
|
|
102
|
+
outputBytes.set(input, padLen * 4),
|
|
103
|
+
isBE && reverse(outputBytes, reverse(output)),
|
|
104
|
+
[output, byteLen]
|
|
105
|
+
)
|
|
105
106
|
|
|
106
107
|
/**
|
|
107
108
|
* Computes the MD5 hash of the input data.
|
|
@@ -116,41 +117,34 @@ let inputToWords = (
|
|
|
116
117
|
*/
|
|
117
118
|
let md5 = (data, key, raw) => {
|
|
118
119
|
// Do not use parameter defaults to declare variables in public functions.
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
, [bdata,
|
|
122
|
-
|
|
123
|
-
/** @type {*} */
|
|
124
|
-
var out = raw ? new $Uint8Array(i) : ''
|
|
120
|
+
/** @type {boolean | Uint8Array<ArrayBuffer>} */
|
|
121
|
+
var temp = key != null
|
|
122
|
+
, [bdata, dataByteLen] = inputToWords(data, /**@type {*}*/(temp) * 16)
|
|
125
123
|
|
|
126
|
-
if (
|
|
124
|
+
if (temp) {
|
|
127
125
|
// HMAC
|
|
128
|
-
let [bkey,
|
|
126
|
+
let [bkey, keyByteLen] = inputToWords(key, 0)
|
|
129
127
|
, opad = new $Int32Array(32)
|
|
130
|
-
|
|
131
|
-
|
|
128
|
+
, i = 16
|
|
129
|
+
if (keyByteLen > 64) {
|
|
130
|
+
bkey = wordsMD5(bkey, keyByteLen)
|
|
132
131
|
}
|
|
133
|
-
for (
|
|
132
|
+
for (; i;) {
|
|
134
133
|
// (0x36363636 ^ 0x5c5c5c5c) == 0x6a6a6a6a
|
|
135
|
-
opad[--
|
|
134
|
+
opad[--i] = 0x6a6a6a6a ^ (bdata[i] = 0x36363636 ^ bkey[i])
|
|
136
135
|
}
|
|
137
|
-
opad.set(wordsMD5(bdata, 64 +
|
|
136
|
+
opad.set(wordsMD5(bdata, 64 + dataByteLen), 16)
|
|
138
137
|
bdata = opad
|
|
139
|
-
|
|
138
|
+
dataByteLen = 80
|
|
140
139
|
}
|
|
141
140
|
|
|
142
|
-
bdata = wordsMD5(bdata,
|
|
143
|
-
|
|
144
|
-
// words to bytes or hex
|
|
145
|
-
for (; i;
|
|
146
|
-
raw
|
|
147
|
-
? out[i] = temp
|
|
148
|
-
: out = (temp >> 4 && '') + temp.toString(16) + out
|
|
149
|
-
) {
|
|
150
|
-
temp = bdata[--i >> 2] >> i * 8 & 0xff
|
|
151
|
-
}
|
|
141
|
+
bdata = wordsMD5(bdata, dataByteLen)
|
|
152
142
|
|
|
153
|
-
|
|
143
|
+
temp = new $Uint8Array(bdata.buffer)
|
|
144
|
+
isBE && reverse(temp, reverse(bdata))
|
|
145
|
+
return raw
|
|
146
|
+
? temp
|
|
147
|
+
: temp.toHex()
|
|
154
148
|
}
|
|
155
149
|
|
|
156
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 (
|
|
3
|
+
"version": "0.5.2-es2026",
|
|
4
|
+
"description": "A tiny (905 Bytes), fast and reliable implementation of MD5 and HMAC-MD5 for JavaScript.",
|
|
5
5
|
"author": "bddjr",
|
|
6
6
|
"license": "Unlicense",
|
|
7
7
|
"type": "module",
|
|
@@ -58,12 +58,13 @@
|
|
|
58
58
|
"crypto-js": "^4.2.0",
|
|
59
59
|
"es-check": "^9.6.4",
|
|
60
60
|
"js-md5": "^0.9.2",
|
|
61
|
+
"spark-md5": "^3.0.2",
|
|
61
62
|
"terser": "^5.49.0",
|
|
62
63
|
"tinyhmacmd5": "link:",
|
|
63
64
|
"typescript": "^7.0.2"
|
|
64
65
|
},
|
|
65
66
|
"scripts": {
|
|
66
|
-
"build": "tsc && node scripts/build.mjs && es-check
|
|
67
|
+
"build": "tsc && node scripts/build.mjs && es-check es2026 --module --checkFeatures main.js browser.min.js",
|
|
67
68
|
"build:unchanged": "node scripts/build-unchanged.mjs",
|
|
68
69
|
"test": "pnpm build && pnpm test:only",
|
|
69
70
|
"test:only": "node scripts/test.mjs && node scripts/test-513MiB.mjs",
|