tinyhmacmd5 0.1.8 → 0.2.0
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 +40 -38
- package/package.json +3 -3
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 **983 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 [Exponentiation (`**`)](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Exponentiation) and [`TextEncoder`](https://developer.mozilla.org/docs/Web/API/TextEncoder) :
|
|
145
|
+
|
|
146
|
+
- Desktop
|
|
147
|
+
- Chrome ≥ 52 (2016-07-20)
|
|
148
|
+
- Edge ≥ 79 (2020-01-15)
|
|
149
|
+
- Firefox ≥ 52 (2017-03-07)
|
|
150
|
+
- Opera ≥ 39 (2016-08-02)
|
|
151
|
+
- Safari ≥ 10.1 (2017-03-27)
|
|
152
|
+
- Mobile
|
|
153
|
+
- Chrome Android ≥ 52 (2016-07-27)
|
|
154
|
+
- Firefox for Android ≥ 52 (2017-03-07)
|
|
155
|
+
- Opera Android ≥ 41 (2016-10-25)
|
|
156
|
+
- Safari on iOS ≥ 10.3 (2017-03-27)
|
|
157
|
+
- Samsung Browser ≥ 6 (2017-08-23)
|
|
158
|
+
- WebView Android ≥ 51 (2016-06-08)
|
|
159
|
+
- WebView on iOS ≥ 10.3 (2017-03-27)
|
|
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 (983 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=[],n=0,t=Math,e=t.floor,o=r=>16*e((r+72)/64),f=(n,t,f=0,a=o(t),l=1732584193,c=271733878,i,d,g=[l,~c,~l,c],h=[...g])=>{for(n[a-1]=0|t/2**29,n[e(t/4)]|=128<<(n[a-2]=t<<3);f<n.length;){for(a=0;a<64;)g[d&=3]=0|((c=0|g[d]+r[a]+(l=g[3&++d],c=g[3&++d],i=g[3&++d],(t=a>>4<<2)?t>4?t>8?c^(l|~i):l^c^i:l&i|c&~i:l&c|~l&i)+(0|n[f+(a*(29521>>t)+(1296>>t)&15)]))<<(i="',16%).4$+07&*/5".charCodeAt(3&a++|t))|c>>>64-i)+l;for(;d;f+=4)h[--d]=g[d]=0|h[d]+g[d]}return g},a=(r,n,t=("string"==typeof r?r=(new TextEncoder).encode(r):r).length,e=new Int32Array(o(4*n+t)),f=0)=>{for(;f<t;)e[n++]=r[f++]|r[f++]<<8|r[f++]<<16|r[f++]<<24;return[e,t]};for(var md5=(r,n,t)=>{var e=16,o=null!=n,[l,c]=a(r,o*e),i=[],d=t?new Uint8Array(e):"";if(o){let[r,t]=a(n,0);for(t>64&&(r=f(r,t));e;)i[--e]=1785358954^(l[e]=909522486^r[e]);e=16,l=i.concat(f(l,64+c)),c=80}for(l=f(l,c);e;t?d[e]=i:d=(i>>4&&"")+i.toString(16)+d)i=l[--e>>2]>>8*e&255;return d};n<64;)r[n]=0|2**32*t.abs(t.sin(++n))}
|
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,7 +126,7 @@ 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 = []
|
|
@@ -138,22 +136,22 @@ var md5 = (data, key, raw) => {
|
|
|
138
136
|
|
|
139
137
|
if (hasKey) {
|
|
140
138
|
// HMAC
|
|
141
|
-
let [bkey, keyByteLen] =
|
|
139
|
+
let [bkey, keyByteLen] = inputToWords(key, 0)
|
|
142
140
|
if (keyByteLen > 64) {
|
|
143
|
-
bkey =
|
|
141
|
+
bkey = wordsMD5(bkey, keyByteLen)
|
|
144
142
|
}
|
|
145
143
|
for (; i;) {
|
|
146
144
|
// (0x36363636 ^ 0x5c5c5c5c) == 0x6a6a6a6a
|
|
147
145
|
temp[--i] = 0x6a6a6a6a ^ (bdata[i] = 0x36363636 ^ bkey[i])
|
|
148
146
|
}
|
|
149
147
|
i = 16
|
|
150
|
-
bdata = temp.concat(
|
|
148
|
+
bdata = temp.concat(wordsMD5(bdata, 64 + dataByteLen))
|
|
151
149
|
dataByteLen = 80
|
|
152
150
|
}
|
|
153
151
|
|
|
154
|
-
bdata =
|
|
152
|
+
bdata = wordsMD5(bdata, dataByteLen)
|
|
155
153
|
|
|
156
|
-
//
|
|
154
|
+
// words to bytes or hex
|
|
157
155
|
for (; i;
|
|
158
156
|
raw
|
|
159
157
|
? out[i] = temp
|
|
@@ -165,4 +163,8 @@ var md5 = (data, key, raw) => {
|
|
|
165
163
|
return out
|
|
166
164
|
}
|
|
167
165
|
|
|
166
|
+
for (; i < 64;) {
|
|
167
|
+
K[i] = 0 | 2 ** 32 * $Math.abs($Math.sin(++i))
|
|
168
|
+
}
|
|
169
|
+
|
|
168
170
|
export default md5
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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",
|
|
4
|
+
"description": "A tiny and reliable HMAC-MD5 implementation for JavaScript: browser.min.js is only 983 bytes.",
|
|
5
5
|
"author": "bddjr",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"type": "module",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"typescript": "^7.0.2"
|
|
61
61
|
},
|
|
62
62
|
"scripts": {
|
|
63
|
-
"build": "tsc && node scripts/build.mjs && es-check
|
|
63
|
+
"build": "tsc && node scripts/build.mjs && es-check es2016 --module --checkFeatures main.js browser.min.js",
|
|
64
64
|
"build:unchanged": "node scripts/build-unchanged.mjs",
|
|
65
65
|
"test": "pnpm build && pnpm test:only",
|
|
66
66
|
"test:only": "node scripts/test.mjs",
|