tinyhmacmd5 0.1.4 → 0.1.6
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 +6 -2
- package/browser.min.js +1 -1
- package/main.d.ts +9 -4
- package/main.js +30 -40
- package/package.json +19 -4
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@ English | [中文](README-zh.md)
|
|
|
3
3
|
# Tiny HMAC MD5
|
|
4
4
|
|
|
5
5
|
A tiny, fully compliant HMAC-MD5 implementation for JavaScript:
|
|
6
|
-
[`browser.min.js`](browser.min.js) is only **
|
|
6
|
+
[`browser.min.js`](browser.min.js) is only **1017 bytes**.
|
|
7
7
|
|
|
8
8
|
- **Input type**: `string` (UTF‑8), `Uint8Array` or `Uint8ClampedArray`
|
|
9
9
|
- **Output type**: hex `string` or raw `Uint8Array`
|
|
@@ -11,6 +11,8 @@ A tiny, fully compliant HMAC-MD5 implementation for JavaScript:
|
|
|
11
11
|
- **TypeScript‑ready**: [`main.d.ts`](main.d.ts)
|
|
12
12
|
- **0 dependencies**
|
|
13
13
|
|
|
14
|
+
The goal of `tinyhmacmd5` is to strike a balance between size and performance, rather than sacrificing performance for the sake of minimizing size. Therefore, some performance-oriented optimizations are intentionally retained, and the final size is not the smallest theoretically achievable.
|
|
15
|
+
|
|
14
16
|
**Live demo**: https://bddjr.github.io/tinyhmacmd5/
|
|
15
17
|
|
|
16
18
|
> [!WARNING]
|
|
@@ -109,6 +111,8 @@ Environments that support [Nullish coalescing assignment (`??=`)](https://develo
|
|
|
109
111
|
- Firefox ≥ 79 (2020-07-28)
|
|
110
112
|
- Safari ≥ 14 (2020-09-16)
|
|
111
113
|
|
|
114
|
+
Not recommended for use in environments that support `node:crypto`, as `node:crypto` already provides HMAC-MD5.
|
|
115
|
+
|
|
112
116
|
---
|
|
113
117
|
|
|
114
118
|
## Why I Made This Project
|
|
@@ -131,7 +135,7 @@ During the adaptation, I discovered that `blueimp-md5` did not correctly handle
|
|
|
131
135
|
|
|
132
136
|
I also found that using `Array` to process inputs over 512 MiB could throw a `RangeError`, so I replaced it with `Int32Array`.
|
|
133
137
|
|
|
134
|
-
I demonstrated in practice that HMAC-MD5 can be implemented in an extremely small footprint (
|
|
138
|
+
I demonstrated in practice that HMAC-MD5 can be implemented in an extremely small footprint (1017 bytes) while also improving reliability.
|
|
135
139
|
|
|
136
140
|
Maybe not many people care about saving just a few KB, but `tinyhmacmd5` exists precisely to "explore the unknown".
|
|
137
141
|
|
package/browser.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** @license https://bddjr.github.io/tinyhmacmd5/lic */
|
|
2
|
-
{let r=1732584193,
|
|
2
|
+
{let r=1732584193,n=271733878,t=[],e=Math,o=e.floor,f=r=>16*o((r+72)/64),a=(a,l,c=0,i=f(l),d,g,h,u,s=[r,~n,~r,n],w=[...s])=>{for(a[i-1]=0|l/2**29,a[i-2]=0|8*l,a[o(l/4)]|=128<<8*l;c<a.length;){for(i=0;i<64;)s[u&=3]=0|((d=0|(d=s[3&++u],g=s[3&++u],h=s[3&++u],((l=i>>4<<2)?l>4?l>8?g^(d|~h):d^g^h:d&h|g&~h:d&g|~d&h)+(0|a[c+(i*(29521>>l)+(1296>>l)&15)])+(g="',16%).4$+07&*/5".charCodeAt(l+i%4),t[63-i++]??=0|2**32*e.abs(e.sin(i)))+s[u+1&3]))<<g|d>>>64-g)+s[u+2&3];for(;u;c+=4)w[--u]=s[u]=0|w[u]+s[u]}return s},l=(r,n,t=("string"==typeof r?r=(new TextEncoder).encode(r):r).length,e=new Int32Array(f(4*n+t)),o=0)=>{for(;o<t;)e[n++]=r[o++]|r[o++]<<8|r[o++]<<16|r[o++]<<24;return[e,t]};var md5=(r,n,t)=>{var e=16,o=null!=n,[f,c]=l(r,o*e),i=[],d=t?new Uint8Array(e):"";if(o){let[r,t]=l(n,0);for(t>64&&(r=a(r,t));e;)i[--e]=1785358954^(f[e]=909522486^r[e]);e=16,f=i.concat(a(f,64+c)),c=80}for(f=a(f,c);e;t?d[e]=i:d=(i>>4&&"")+i.toString(16)+d)i=f[--e>>2]>>8*e&255;return d}}
|
package/main.d.ts
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* By default, returns the hash as a lowercase hexadecimal string.
|
|
5
5
|
* If `raw` is true, returns a Uint8Array.
|
|
6
6
|
*
|
|
7
|
-
* @param
|
|
8
|
-
* @param
|
|
9
|
-
* @param
|
|
10
|
-
* @returns
|
|
7
|
+
* @param data The input data to hash. Strings are UTF‑8 encoded.
|
|
8
|
+
* @param key Optional HMAC key. When given, HMAC‑MD5 is calculated instead of plain MD5.
|
|
9
|
+
* @param raw If true, the hash is returned as raw bytes (Uint8Array); otherwise, as a hex string.
|
|
10
|
+
* @returns The MD5 (or HMAC‑MD5) digest, either as a hex string or a Uint8Array.
|
|
11
11
|
*/
|
|
12
12
|
declare var md5: {
|
|
13
13
|
(
|
|
@@ -20,5 +20,10 @@ declare var md5: {
|
|
|
20
20
|
key: string | Uint8Array | Uint8ClampedArray | null | undefined,
|
|
21
21
|
raw: true
|
|
22
22
|
): Uint8Array<ArrayBuffer>;
|
|
23
|
+
(
|
|
24
|
+
data: string | Uint8Array | Uint8ClampedArray,
|
|
25
|
+
key: string | Uint8Array | Uint8ClampedArray | null | undefined,
|
|
26
|
+
raw: boolean
|
|
27
|
+
): string | Uint8Array<ArrayBuffer>;
|
|
23
28
|
};
|
|
24
29
|
export default md5;
|
package/main.js
CHANGED
|
@@ -4,23 +4,20 @@
|
|
|
4
4
|
|
|
5
5
|
let A = 1732584193
|
|
6
6
|
, D = 271733878
|
|
7
|
-
, C = ~A
|
|
8
|
-
, B = ~D
|
|
9
7
|
|
|
10
|
-
|
|
8
|
+
/** @type {number[]} MD5 constants cached in memory */
|
|
9
|
+
let K = []
|
|
11
10
|
|
|
12
11
|
let $Math = Math
|
|
13
12
|
|
|
14
13
|
let floor = $Math.floor
|
|
15
14
|
|
|
16
15
|
/** @param {number} byteLen */
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
/** @type {number[]} MD5 constants cached in memory */
|
|
20
|
-
let K = []
|
|
16
|
+
// `byteLen` may be >= 2**32, so cannot use `>>>` as a replacement for `floor`
|
|
17
|
+
let toBinlLen = (byteLen) => floor((byteLen + 72) / 64) * 16
|
|
21
18
|
|
|
22
19
|
/**
|
|
23
|
-
* Calculate the MD5 of an array of little-endian words, and a
|
|
20
|
+
* Calculate the MD5 of an array of little-endian words, and a byte length.
|
|
24
21
|
*
|
|
25
22
|
* @param {Int32Array | number[]} x Array of little-endian words
|
|
26
23
|
* @param {number} l Byte length
|
|
@@ -43,19 +40,20 @@ let binlMD5 = (
|
|
|
43
40
|
t1,
|
|
44
41
|
t2,
|
|
45
42
|
oi,
|
|
46
|
-
output = [A,
|
|
43
|
+
output = [A, ~D, ~A, D],
|
|
47
44
|
oldOutput = [...output],
|
|
48
45
|
) => {
|
|
49
46
|
// console.time("binlMD5")
|
|
50
47
|
|
|
51
48
|
// append padding
|
|
52
|
-
|
|
49
|
+
// `l` may be >= 2**32, so cannot use `>>>` as a replacement for `floor`
|
|
50
|
+
x[j - 1] = 0 | l / 2 ** 29;
|
|
53
51
|
x[j - 2] = 0 | l * 8;
|
|
54
|
-
x[floor(l / 4)] |= 0x80 << l
|
|
52
|
+
x[floor(l / 4)] |= 0x80 << l * 8;
|
|
55
53
|
|
|
56
|
-
for (; i < x.length;
|
|
57
|
-
for (
|
|
58
|
-
output[oi
|
|
54
|
+
for (; i < x.length;) {
|
|
55
|
+
for (j = 0; j < 64;) {
|
|
56
|
+
output[oi &= 3] = (
|
|
59
57
|
t0 = 0 | (
|
|
60
58
|
(
|
|
61
59
|
t0 = output[++oi & 3],
|
|
@@ -74,14 +72,14 @@ let binlMD5 = (
|
|
|
74
72
|
) +
|
|
75
73
|
(
|
|
76
74
|
t1 = "',16%).4$+07&*/5".charCodeAt(l + j % 4),
|
|
77
|
-
K[63 - j++] ??= 0 |
|
|
75
|
+
K[63 - j++] ??= 0 | 2 ** 32 * $Math.abs($Math.sin(j))
|
|
78
76
|
) +
|
|
79
77
|
output[oi + 1 & 3]
|
|
80
78
|
),
|
|
81
79
|
0 | (t0 << t1 | t0 >>> 64 - t1) + output[oi + 2 & 3]
|
|
82
80
|
)
|
|
83
81
|
}
|
|
84
|
-
for (oi
|
|
82
|
+
for (; oi; i += 4) {
|
|
85
83
|
oldOutput[--oi] = output[oi] = 0 | oldOutput[oi] + output[oi]
|
|
86
84
|
}
|
|
87
85
|
}
|
|
@@ -124,20 +122,6 @@ let inputToBinl = (
|
|
|
124
122
|
return [output, byteLen]
|
|
125
123
|
}
|
|
126
124
|
|
|
127
|
-
/**
|
|
128
|
-
* @overload
|
|
129
|
-
* @param {string | Uint8Array | Uint8ClampedArray} data
|
|
130
|
-
* @param {string | Uint8Array | Uint8ClampedArray | null} [key]
|
|
131
|
-
* @param {false} [raw]
|
|
132
|
-
* @returns {string}
|
|
133
|
-
*/
|
|
134
|
-
/**
|
|
135
|
-
* @overload
|
|
136
|
-
* @param {string | Uint8Array | Uint8ClampedArray} data
|
|
137
|
-
* @param {string | Uint8Array | Uint8ClampedArray | null | undefined} key
|
|
138
|
-
* @param {true} raw
|
|
139
|
-
* @returns {Uint8Array<ArrayBuffer>}
|
|
140
|
-
*/
|
|
141
125
|
/**
|
|
142
126
|
* Computes the MD5 hash of the input data.
|
|
143
127
|
* If a key is provided, computes HMAC-MD5.
|
|
@@ -153,34 +137,40 @@ var md5 = (data, key, raw) => {
|
|
|
153
137
|
var i = 16
|
|
154
138
|
, hasKey = key != null
|
|
155
139
|
, [bdata, dataByteLen] = inputToBinl(data, /**@type {*}*/(hasKey) * i)
|
|
156
|
-
|
|
140
|
+
|
|
141
|
+
/** @type {*} */
|
|
142
|
+
var temp = []
|
|
143
|
+
|
|
144
|
+
/** @type {*} */
|
|
145
|
+
var out = raw ? new Uint8Array(i) : ''
|
|
157
146
|
|
|
158
147
|
if (hasKey) {
|
|
159
148
|
// HMAC
|
|
160
149
|
let [bkey, keyByteLen] = inputToBinl(key, 0)
|
|
161
|
-
let opad = []
|
|
162
150
|
if (keyByteLen > 64) {
|
|
163
151
|
bkey = binlMD5(bkey, keyByteLen)
|
|
164
152
|
}
|
|
165
153
|
for (; i;) {
|
|
166
154
|
// (0x36363636 ^ 0x5c5c5c5c) == 0x6a6a6a6a
|
|
167
|
-
|
|
155
|
+
temp[--i] = 0x6a6a6a6a ^ (bdata[i] = 0x36363636 ^ bkey[i])
|
|
168
156
|
}
|
|
169
157
|
i = 16
|
|
170
|
-
bdata =
|
|
158
|
+
bdata = temp.concat(binlMD5(bdata, 64 + dataByteLen))
|
|
171
159
|
dataByteLen = 80
|
|
172
160
|
}
|
|
173
161
|
|
|
174
162
|
bdata = binlMD5(bdata, dataByteLen)
|
|
175
163
|
|
|
176
|
-
// binl to bytes
|
|
177
|
-
for (; i;
|
|
178
|
-
|
|
164
|
+
// binl to bytes or hex
|
|
165
|
+
for (; i;
|
|
166
|
+
raw
|
|
167
|
+
? out[i] = temp
|
|
168
|
+
: out = (temp >> 4 && '') + temp.toString(16) + out
|
|
169
|
+
) {
|
|
170
|
+
temp = bdata[--i >> 2] >> i * 8 & 0xff
|
|
179
171
|
}
|
|
180
172
|
|
|
181
|
-
return
|
|
182
|
-
? out
|
|
183
|
-
: out.reduce((p, v) => p + (v >> 4 && '') + v.toString(16), '')
|
|
173
|
+
return out
|
|
184
174
|
}
|
|
185
175
|
|
|
186
176
|
export default md5
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tinyhmacmd5",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "A tiny, fully compliant HMAC-MD5 implementation for JavaScript: browser.min.js is only
|
|
3
|
+
"version": "0.1.6",
|
|
4
|
+
"description": "A tiny, fully compliant HMAC-MD5 implementation for JavaScript: browser.min.js is only 1017 bytes.",
|
|
5
5
|
"author": "bddjr",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"type": "module",
|
|
@@ -17,20 +17,35 @@
|
|
|
17
17
|
"keywords": [
|
|
18
18
|
"md5",
|
|
19
19
|
"hash",
|
|
20
|
+
"hashing",
|
|
20
21
|
"hmac",
|
|
21
22
|
"hmacmd5",
|
|
22
23
|
"hmac-md5",
|
|
23
24
|
"tiny",
|
|
25
|
+
"tiny-hmac-md5",
|
|
26
|
+
"small",
|
|
27
|
+
"lightweight",
|
|
28
|
+
"minimal",
|
|
24
29
|
"hex",
|
|
25
30
|
"crypto",
|
|
26
31
|
"encryption",
|
|
27
32
|
"cryptography",
|
|
33
|
+
"message-digest",
|
|
34
|
+
"cryptographic-hash",
|
|
35
|
+
"web",
|
|
36
|
+
"pure-javascript",
|
|
37
|
+
"esm",
|
|
38
|
+
"javascript",
|
|
39
|
+
"typescript",
|
|
40
|
+
"frontend",
|
|
41
|
+
"front-end",
|
|
28
42
|
"blueimp",
|
|
29
43
|
"blueimp-md5",
|
|
30
44
|
"js-md5",
|
|
31
45
|
"crypto-js",
|
|
32
|
-
"
|
|
33
|
-
"
|
|
46
|
+
"tiny-hashes",
|
|
47
|
+
"tiny-js-md5",
|
|
48
|
+
"spark-md5"
|
|
34
49
|
],
|
|
35
50
|
"repository": {
|
|
36
51
|
"type": "git",
|