tinyhmacmd5 0.1.7 → 0.2.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/README.md +31 -14
- package/browser.min.js +1 -2
- package/main.js +44 -47
- package/package.json +9 -4
package/README.md
CHANGED
|
@@ -2,11 +2,11 @@ English | [中文](README-zh.md)
|
|
|
2
2
|
|
|
3
3
|
# Tiny HMAC MD5
|
|
4
4
|
|
|
5
|
-
A tiny and reliable HMAC-MD5 implementation for JavaScript: [`browser.min.js`](browser.min.js) is only **
|
|
5
|
+
A tiny and reliable HMAC-MD5 implementation for JavaScript: [`browser.min.js`](browser.min.js) is only **951 bytes**.
|
|
6
6
|
|
|
7
7
|
- **Input type**: `string` (UTF‑8), `Uint8Array` or `Uint8ClampedArray`
|
|
8
8
|
- **Output type**: hex `string` or bytes `Uint8Array`
|
|
9
|
-
- **Supports inputs ≥ 512 MiB**: The input length theoretically supports 0 to
|
|
9
|
+
- **Supports inputs ≥ 512 MiB**: The input length theoretically supports 0 to 2⁵³-1 (`Number.MAX_SAFE_INTEGER`).
|
|
10
10
|
- **TypeScript‑ready**: [`main.d.ts`](main.d.ts)
|
|
11
11
|
- **0 dependencies**
|
|
12
12
|
|
|
@@ -47,6 +47,14 @@ See https://www.jsdelivr.com/package/npm/tinyhmacmd5
|
|
|
47
47
|
|
|
48
48
|
It will define the `md5` function using `var`.
|
|
49
49
|
|
|
50
|
+
### UNPKG
|
|
51
|
+
|
|
52
|
+
```html
|
|
53
|
+
<script src="https://unpkg.com/tinyhmacmd5"></script>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
It will define the `md5` function using `var`.
|
|
57
|
+
|
|
50
58
|
### Inline
|
|
51
59
|
|
|
52
60
|
You can embed [`browser.min.js`](browser.min.js) directly into your script.
|
|
@@ -100,8 +108,7 @@ md5(Uint8Array.of(1, 2, 3))
|
|
|
100
108
|
md5(Uint8Array.of(1, 2, 3), null, true)
|
|
101
109
|
```
|
|
102
110
|
|
|
103
|
-
`ArrayBuffer` must be wrapped in a `Uint8Array` before use as input;
|
|
104
|
-
otherwise, it will return an incorrect MD5 hash.
|
|
111
|
+
`ArrayBuffer` must be wrapped in a `Uint8Array` before use as input; otherwise, it will return an incorrect MD5 hash.
|
|
105
112
|
|
|
106
113
|
```js
|
|
107
114
|
let data = new ArrayBuffer(8)
|
|
@@ -118,8 +125,8 @@ You can also input a `Uint8ClampedArray`, which has the same effect as using a `
|
|
|
118
125
|
md5(Uint8ClampedArray.of(1, 2, 3))
|
|
119
126
|
```
|
|
120
127
|
|
|
121
|
-
**[⚠️Unsafe]**
|
|
122
|
-
otherwise, it will return an incorrect MD5 hash.
|
|
128
|
+
**[⚠️Unsafe]**
|
|
129
|
+
You can also input a `number[]`, but every element must be an integer in the range `0 ≤ x ≤ 255`; otherwise, it will return an incorrect MD5 hash.
|
|
123
130
|
|
|
124
131
|
```js
|
|
125
132
|
let data = [0, 1, 127, 255]
|
|
@@ -134,12 +141,22 @@ md5(data)
|
|
|
134
141
|
|
|
135
142
|
## Runtime Environment
|
|
136
143
|
|
|
137
|
-
Environments that support [
|
|
138
|
-
|
|
139
|
-
-
|
|
140
|
-
-
|
|
141
|
-
-
|
|
142
|
-
-
|
|
144
|
+
Environments that support [`Uint8Array.prototype.toHex()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array/toHex) :
|
|
145
|
+
|
|
146
|
+
- Desktop
|
|
147
|
+
- Chrome ≥ 140 (2025-09-02)
|
|
148
|
+
- Edge ≥ 140 (2025-09-05)
|
|
149
|
+
- Firefox ≥ 133 (2024-11-26)
|
|
150
|
+
- Opera ≥ 124 (2025-11-13)
|
|
151
|
+
- Safari ≥ 18.2 (2024-12-11)
|
|
152
|
+
- Mobile
|
|
153
|
+
- Chrome Android ≥ 140 (2025-09-02)
|
|
154
|
+
- Firefox for Android ≥ 133 (2024-11-26)
|
|
155
|
+
- Opera Android ≥ 92 (2025-10-08)
|
|
156
|
+
- Safari on iOS ≥ 18.2 (2024-12-11)
|
|
157
|
+
- Samsung Browser ×
|
|
158
|
+
- WebView Android ≥ 140 (2025-09-02)
|
|
159
|
+
- WebView on iOS ≥ 18.2 (2024-12-11)
|
|
143
160
|
|
|
144
161
|
Not recommended for use in environments that support `node:crypto`, as `node:crypto` already provides HMAC-MD5.
|
|
145
162
|
|
|
@@ -161,13 +178,13 @@ During the adaptation, I discovered that `blueimp-md5` did not correctly handle
|
|
|
161
178
|
|
|
162
179
|
I also found that using `Array` to process inputs over 512 MiB could throw a `RangeError`, so I replaced it with `Int32Array`.
|
|
163
180
|
|
|
164
|
-
I demonstrated in practice that HMAC-MD5 can be implemented in an extremely small footprint (
|
|
181
|
+
I demonstrated in practice that HMAC-MD5 can be implemented in an extremely small footprint (951 bytes) while also improving reliability.
|
|
165
182
|
|
|
166
183
|
Maybe not many people care about saving just a few KB, but `tinyhmacmd5` exists precisely to "explore the unknown".
|
|
167
184
|
|
|
168
185
|
INVINCIBLE EXPERIMENT!
|
|
169
186
|
|
|
170
|
-
[
|
|
187
|
+
[Read the original Chinese text](README-zh.md#为什么做这个项目)
|
|
171
188
|
|
|
172
189
|
---
|
|
173
190
|
|
package/browser.min.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
{let r=[],n=Math,t=n.floor,e=r=>16*t((r+72)/64),o=(o,f,a=0,l=e(f),c=1732584193,i=271733878,d,g,h=[c,~i,~c,i],u=[...h])=>{for(o[l-1]=0|f/2**29,o[t(f/4)]|=128<<(o[l-2]=f<<3);a<o.length;){for(l=0;l<64;)h[g&=3]=0|((i=0|h[g]+(c=h[3&++g],i=h[3&++g],d=h[3&++g],(f=l>>4<<2)?f>4?f>8?i^(c|~d):c^i^d:c&d|i&~d:c&i|~c&d)+(0|o[a+(l*(29521>>f)+(1296>>f)&15)])+(d="',16%).4$+07&*/5".charCodeAt(3&l|f),r[63-l++]??=0|2**32*n.abs(n.sin(l))))<<d|i>>>64-d)+c;for(;g;a+=4)u[--g]=h[g]=0|u[g]+h[g]}return h},f=(r,n,t=("string"==typeof r?r=(new TextEncoder).encode(r):r).length,o=new Int32Array(e(4*n+t)),f=0)=>{for(;f<t;)o[n++]=r[f++]|r[f++]<<8|r[f++]<<16|r[f++]<<24;return[o,t]};var md5=(r,n,t)=>{var e=16,a=null!=n,[l,c]=f(r,a*e),i=[],d=t?new Uint8Array(e):"";if(a){let[r,t]=f(n,0);for(t>64&&(r=o(r,t));e;)i[--e]=1785358954^(l[e]=909522486^r[e]);e=16,l=i.concat(o(l,64+c)),c=80}for(l=o(l,c);e;t?d[e]=i:d=(i>>4&&"")+i.toString(16)+d)i=l[--e>>2]>>8*e&255;return d}}
|
|
1
|
+
/*! npmjs.com/tinyhmacmd5 */{let r=[],e=0,n=Math,t=n.floor,o=r=>16*t((r+72)/64),f=(e,n,f=0,a=o(n),l=1732584193,c=271733878,d,h,i=[l,~c,~l,c],u=[...i])=>{for(e[a-1]=0|n/2**29,e[t(n/4)]|=128<<(e[a-2]=n<<3);f<e.length;){for(a=0;a<64;)i[h&=3]=0|((c=0|i[h]+r[a]+(l=i[3&++h],c=i[3&++h],d=i[3&++h],(n=a>>4<<2)?n>4?n>8?c^(l|~d):l^c^d:l&d|c&~d:l&c|~l&d)+(0|e[f+(a*(29521>>n)+(1296>>n)&15)]))<<(d="',16%).4$+07&*/5".charCodeAt(3&a++|n))|c>>>64-d)+l;for(;h;f+=4)u[--h]=i[h]=0|u[h]+i[h]}return i},a=(r,e,n=("string"==typeof r?r=(new TextEncoder).encode(r):r).length,t=new Int32Array(o(4*e+n)),f=0)=>{for(;f<n;)t[e++]=r[f++]|r[f++]<<8|r[f++]<<16|r[f++]<<24;return[t,n]};for(var md5=(r,e,n)=>{var t=16,o=null!=e,[l,c]=a(r,o*t),d=[],h=new Uint8Array(t);if(o){let[r,n]=a(e,0);for(n>64&&(r=f(r,n));t;)d[--t]=1785358954^(l[t]=909522486^r[t]);t=16,l=d.concat(f(l,64+c)),c=80}for(l=f(l,c);t;)h[--t]=l[t>>2]>>8*t;return n?h:h.toHex()};e<64;)r[e]=0|2**32*n.abs(n.sin(++e))}
|
package/main.js
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
/*! npmjs.com/tinyhmacmd5 */
|
|
2
2
|
|
|
3
3
|
// Adapted from https://github.com/blueimp/JavaScript-MD5
|
|
4
4
|
|
|
5
5
|
/** @type {number[]} MD5 constants cached in memory */
|
|
6
6
|
let K = []
|
|
7
7
|
|
|
8
|
+
let i = 0
|
|
9
|
+
|
|
8
10
|
let $Math = Math
|
|
9
11
|
|
|
10
12
|
let floor = $Math.floor
|
|
11
13
|
|
|
12
14
|
/** @param {number} byteLen */
|
|
13
15
|
// `byteLen` may be >= 2**32, so cannot use `>>>` as a replacement for `floor`
|
|
14
|
-
let
|
|
16
|
+
let wordsLen = (byteLen) => floor((byteLen + 72) / 64) * 16
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
19
|
* Calculate the MD5 of an array of little-endian words, and a byte length.
|
|
@@ -24,12 +26,12 @@ let toBinlLen = (byteLen) => floor((byteLen + 72) / 64) * 16
|
|
|
24
26
|
*
|
|
25
27
|
* @returns {number[]} MD5 Array
|
|
26
28
|
*/
|
|
27
|
-
let
|
|
29
|
+
let wordsMD5 = (
|
|
28
30
|
x,
|
|
29
31
|
l,
|
|
30
32
|
// var:
|
|
31
33
|
i = 0,
|
|
32
|
-
j =
|
|
34
|
+
j = wordsLen(l),
|
|
33
35
|
t0 = 1732584193,
|
|
34
36
|
t1 = 271733878,
|
|
35
37
|
t2,
|
|
@@ -37,8 +39,6 @@ let binlMD5 = (
|
|
|
37
39
|
output = [t0, ~t1, ~t0, t1],
|
|
38
40
|
oldOutput = [...output],
|
|
39
41
|
) => {
|
|
40
|
-
// console.time("binlMD5")
|
|
41
|
-
|
|
42
42
|
// append padding
|
|
43
43
|
// `l` may be >= 2**32, so cannot use `>>>` as a replacement for `floor`
|
|
44
44
|
x[j - 1] = 0 | l / 2 ** 29;
|
|
@@ -47,35 +47,35 @@ let binlMD5 = (
|
|
|
47
47
|
for (; i < x.length;) {
|
|
48
48
|
for (j = 0; j < 64;) {
|
|
49
49
|
output[oi &= 3] = 0 | (
|
|
50
|
-
(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
K[63 - j++] ??= 0 | 2 ** 32 * $Math.abs($Math.sin(j))
|
|
50
|
+
(
|
|
51
|
+
t1 = 0 | (
|
|
52
|
+
output[oi] +
|
|
53
|
+
K[j] +
|
|
54
|
+
(
|
|
55
|
+
t0 = output[++oi & 3],
|
|
56
|
+
t1 = output[++oi & 3],
|
|
57
|
+
t2 = output[++oi & 3],
|
|
58
|
+
(l = j >> 4 << 2)
|
|
59
|
+
? l > 4
|
|
60
|
+
? l > 8
|
|
61
|
+
? t1 ^ (t0 | ~t2) // Round 4: I
|
|
62
|
+
: t0 ^ t1 ^ t2 // Round 3: H
|
|
63
|
+
: t0 & t2 | t1 & ~t2 // Round 2: G
|
|
64
|
+
: t0 & t1 | ~t0 & t2 // Round 1: F
|
|
65
|
+
) +
|
|
66
|
+
(
|
|
67
|
+
0 | x[i + (j * (0x7351 >> l) + (0x0510 >> l) & 15)]
|
|
68
|
+
)
|
|
70
69
|
)
|
|
71
|
-
)
|
|
70
|
+
) << (
|
|
71
|
+
t2 = "',16%).4$+07&*/5".charCodeAt(j++ & 3 | l)
|
|
72
|
+
) | t1 >>> 64 - t2
|
|
72
73
|
) + t0
|
|
73
74
|
}
|
|
74
75
|
for (; oi; i += 4) {
|
|
75
76
|
oldOutput[--oi] = output[oi] = 0 | oldOutput[oi] + output[oi]
|
|
76
77
|
}
|
|
77
78
|
}
|
|
78
|
-
// console.timeEnd("binlMD5")
|
|
79
79
|
return output
|
|
80
80
|
}
|
|
81
81
|
|
|
@@ -87,7 +87,7 @@ let binlMD5 = (
|
|
|
87
87
|
*
|
|
88
88
|
* @returns {[Int32Array<ArrayBuffer> | number[], number]}
|
|
89
89
|
*/
|
|
90
|
-
let
|
|
90
|
+
let inputToWords = (
|
|
91
91
|
input,
|
|
92
92
|
j,
|
|
93
93
|
// var:
|
|
@@ -98,10 +98,9 @@ let inputToBinl = (
|
|
|
98
98
|
).length,
|
|
99
99
|
// Using `Array` to process inputs over 512 MiB could throw a `RangeError`,
|
|
100
100
|
// so I replaced it with `Int32Array`.
|
|
101
|
-
output = new Int32Array(
|
|
101
|
+
output = new Int32Array(wordsLen(j * 4 + byteLen)),
|
|
102
102
|
i = 0,
|
|
103
103
|
) => {
|
|
104
|
-
// console.time("inputToBinl")
|
|
105
104
|
for (; i < byteLen;) {
|
|
106
105
|
output[j++] = (
|
|
107
106
|
input[i++] |
|
|
@@ -110,7 +109,6 @@ let inputToBinl = (
|
|
|
110
109
|
input[i++] << 24
|
|
111
110
|
)
|
|
112
111
|
}
|
|
113
|
-
// console.timeEnd("inputToBinl")
|
|
114
112
|
return [output, byteLen]
|
|
115
113
|
}
|
|
116
114
|
|
|
@@ -128,41 +126,40 @@ let inputToBinl = (
|
|
|
128
126
|
var md5 = (data, key, raw) => {
|
|
129
127
|
var i = 16
|
|
130
128
|
, hasKey = key != null
|
|
131
|
-
, [bdata, dataByteLen] =
|
|
129
|
+
, [bdata, dataByteLen] = inputToWords(data, /**@type {*}*/(hasKey) * i)
|
|
132
130
|
|
|
133
131
|
/** @type {*} */
|
|
134
132
|
var temp = []
|
|
135
133
|
|
|
136
|
-
|
|
137
|
-
var out = raw ? new Uint8Array(i) : ''
|
|
134
|
+
var out = new Uint8Array(i)
|
|
138
135
|
|
|
139
136
|
if (hasKey) {
|
|
140
137
|
// HMAC
|
|
141
|
-
let [bkey, keyByteLen] =
|
|
138
|
+
let [bkey, keyByteLen] = inputToWords(key, 0)
|
|
142
139
|
if (keyByteLen > 64) {
|
|
143
|
-
bkey =
|
|
140
|
+
bkey = wordsMD5(bkey, keyByteLen)
|
|
144
141
|
}
|
|
145
142
|
for (; i;) {
|
|
146
143
|
// (0x36363636 ^ 0x5c5c5c5c) == 0x6a6a6a6a
|
|
147
144
|
temp[--i] = 0x6a6a6a6a ^ (bdata[i] = 0x36363636 ^ bkey[i])
|
|
148
145
|
}
|
|
149
146
|
i = 16
|
|
150
|
-
bdata = temp.concat(
|
|
147
|
+
bdata = temp.concat(wordsMD5(bdata, 64 + dataByteLen))
|
|
151
148
|
dataByteLen = 80
|
|
152
149
|
}
|
|
153
150
|
|
|
154
|
-
bdata =
|
|
151
|
+
bdata = wordsMD5(bdata, dataByteLen)
|
|
155
152
|
|
|
156
|
-
//
|
|
157
|
-
for (; i;
|
|
158
|
-
|
|
159
|
-
? out[i] = temp
|
|
160
|
-
: out = (temp >> 4 && '') + temp.toString(16) + out
|
|
161
|
-
) {
|
|
162
|
-
temp = bdata[--i >> 2] >> i * 8 & 0xff
|
|
153
|
+
// words to bytes or hex
|
|
154
|
+
for (; i;) {
|
|
155
|
+
out[--i] = bdata[i >> 2] >> i * 8
|
|
163
156
|
}
|
|
164
157
|
|
|
165
|
-
return out
|
|
158
|
+
return raw ? out : out.toHex()
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
for (; i < 64;) {
|
|
162
|
+
K[i] = 0 | 2 ** 32 * $Math.abs($Math.sin(++i))
|
|
166
163
|
}
|
|
167
164
|
|
|
168
165
|
export default md5
|
package/package.json
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
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.2.0-es2026",
|
|
4
|
+
"description": "A tiny and reliable HMAC-MD5 implementation for JavaScript: browser.min.js is only 951 bytes.",
|
|
5
5
|
"author": "bddjr",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "main.js",
|
|
9
9
|
"types": "main.d.ts",
|
|
10
|
-
"
|
|
10
|
+
"jsdelivr": "browser.min.js",
|
|
11
|
+
"unpkg": "browser.min.js",
|
|
12
|
+
"cdn": "browser.min.js",
|
|
11
13
|
"files": [
|
|
12
14
|
"main.js",
|
|
13
15
|
"main.d.ts",
|
|
14
16
|
"browser.min.js"
|
|
15
17
|
],
|
|
16
18
|
"homepage": "https://bddjr.github.io/tinyhmacmd5/",
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"tag": "es2026"
|
|
21
|
+
},
|
|
17
22
|
"keywords": [
|
|
18
23
|
"md5",
|
|
19
24
|
"hash",
|
|
@@ -58,7 +63,7 @@
|
|
|
58
63
|
"typescript": "^7.0.2"
|
|
59
64
|
},
|
|
60
65
|
"scripts": {
|
|
61
|
-
"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",
|
|
62
67
|
"build:unchanged": "node scripts/build-unchanged.mjs",
|
|
63
68
|
"test": "pnpm build && pnpm test:only",
|
|
64
69
|
"test:only": "node scripts/test.mjs",
|