tinyhmacmd5 0.5.2 → 0.5.3
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 +26 -27
- package/browser.min.js +1 -1
- package/main.d.ts +6 -6
- package/main.js +42 -38
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -4,9 +4,9 @@ English | [中文](README-zh.md)
|
|
|
4
4
|
|
|
5
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 **926 Bytes**.
|
|
8
8
|
|
|
9
|
-
- **Input type**: `string` (UTF‑8), `Uint8Array` or `
|
|
9
|
+
- **Input type**: `string` (UTF‑8), `Uint8Array`, `Uint8ClampedArray`, `Int8Array` or `number[]`
|
|
10
10
|
- **Output type**: hex `string` or bytes `Uint8Array`
|
|
11
11
|
- **Supports inputs ≥ 512 MiB**: The input length theoretically supports 0 to 2⁵³-137
|
|
12
12
|
- **TypeScript‑ready**: [`main.d.ts`](main.d.ts)
|
|
@@ -29,20 +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 :
|
|
33
|
-
spark-md5 :
|
|
34
|
-
js-md5 :
|
|
35
|
-
crypto-js :
|
|
36
|
-
blueimp-md5 :
|
|
37
|
-
node:crypto :
|
|
32
|
+
tinyhmacmd5 : 374.04 ms
|
|
33
|
+
spark-md5 : 513.18 ms
|
|
34
|
+
js-md5 : 481.65 ms
|
|
35
|
+
crypto-js : 1667.43 ms
|
|
36
|
+
blueimp-md5 : 3753.25 ms
|
|
37
|
+
node:crypto : 130.88 ms
|
|
38
38
|
--------------------------------------------------
|
|
39
39
|
✅ All pure JS implementations match node:crypto result.
|
|
40
40
|
|
|
41
41
|
--- Pure 513MiB Test (No prior small tests) ---
|
|
42
|
-
tinyhmacmd5 HMAC-MD5 timer: 1.
|
|
43
|
-
node:crypto HMAC-MD5 timer:
|
|
44
|
-
tinyhmacmd5 MD5 timer: 1.
|
|
45
|
-
node:crypto MD5 timer:
|
|
42
|
+
tinyhmacmd5 HMAC-MD5 timer: 1.794s
|
|
43
|
+
node:crypto HMAC-MD5 timer: 550.872ms
|
|
44
|
+
tinyhmacmd5 MD5 timer: 1.786s
|
|
45
|
+
node:crypto MD5 timer: 548.873ms
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
CPU: i5-10600KF
|
|
@@ -61,7 +61,7 @@ As a result, the final size is not the smallest theoretically achievable.
|
|
|
61
61
|
### npm
|
|
62
62
|
|
|
63
63
|
```
|
|
64
|
-
npm i tinyhmacmd5
|
|
64
|
+
npm i tinyhmacmd5@latest
|
|
65
65
|
```
|
|
66
66
|
|
|
67
67
|
```js
|
|
@@ -80,21 +80,20 @@ See https://www.jsdelivr.com/package/npm/tinyhmacmd5
|
|
|
80
80
|
<script src="https://cdn.jsdelivr.net/npm/tinyhmacmd5"></script>
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
-
It will define the `md5` function using `var`.
|
|
84
|
-
|
|
85
83
|
### UNPKG
|
|
86
84
|
|
|
87
85
|
```html
|
|
88
86
|
<script src="https://unpkg.com/tinyhmacmd5"></script>
|
|
89
87
|
```
|
|
90
88
|
|
|
91
|
-
|
|
89
|
+
### cdnjs
|
|
90
|
+
|
|
91
|
+
See https://cdnjs.com/libraries/tinyhmacmd5
|
|
92
92
|
|
|
93
93
|
### Inline
|
|
94
94
|
|
|
95
95
|
You can embed [`browser.min.js`](browser.min.js) directly into your script.
|
|
96
|
-
It will define the `md5` function using `var`.
|
|
97
|
-
|
|
96
|
+
It will define the `md5` function using `var`.
|
|
98
97
|
If you are concerned that others might not recognize what this is, you can add the following comment:
|
|
99
98
|
|
|
100
99
|
```js
|
|
@@ -145,7 +144,7 @@ md5(Uint8Array.of(1, 2, 3))
|
|
|
145
144
|
md5(Uint8Array.of(1, 2, 3), null, true)
|
|
146
145
|
```
|
|
147
146
|
|
|
148
|
-
`ArrayBuffer` must be wrapped in a `Uint8Array` before use as input; otherwise, it will return an incorrect MD5 hash
|
|
147
|
+
`ArrayBuffer` must be wrapped in a `Uint8Array` before use as input; otherwise, it will return an incorrect MD5 hash `"0123456789abcdeffedcba9876543210"`.
|
|
149
148
|
|
|
150
149
|
```js
|
|
151
150
|
let data = new ArrayBuffer(8)
|
|
@@ -154,24 +153,24 @@ let data = new ArrayBuffer(8)
|
|
|
154
153
|
md5(new Uint8Array(data))
|
|
155
154
|
```
|
|
156
155
|
|
|
157
|
-
You can also input
|
|
156
|
+
You can also input `Uint8ClampedArray` or `Int8Array`.
|
|
158
157
|
|
|
159
158
|
```js
|
|
160
159
|
// MD5: bytes to hex
|
|
161
160
|
// returns "5289df737df57326fcdd22597afb1fac"
|
|
162
161
|
md5(Uint8ClampedArray.of(1, 2, 3))
|
|
162
|
+
|
|
163
|
+
// MD5: bytes to hex
|
|
164
|
+
// returns "915273adf4c4b9b384bc5550b54d6319"
|
|
165
|
+
md5(Int8Array.of(1, -2, 3, -4))
|
|
163
166
|
```
|
|
164
167
|
|
|
165
|
-
|
|
166
|
-
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.
|
|
168
|
+
You can also input a `number[]`, and each item will be converted to a byte.
|
|
167
169
|
|
|
168
170
|
```js
|
|
169
|
-
let data = [0, 1, 127, 255]
|
|
170
|
-
|
|
171
171
|
// MD5: bytes to hex
|
|
172
|
-
// returns "
|
|
173
|
-
|
|
174
|
-
md5(data)
|
|
172
|
+
// returns "47e3385934cd3e9abefb2f87c3bd4288"
|
|
173
|
+
md5([0, 1, 127, 255, -9])
|
|
175
174
|
```
|
|
176
175
|
|
|
177
176
|
---
|
package/browser.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{let e=Int32Array,r=Uint8Array,
|
|
1
|
+
{let e=Int32Array,r=Uint8Array,t=new e(64).map((e,r)=>2**32*Math.sin(++r%Math.PI)),n=1&new r(t.buffer)[0],f=e=>n?e.reverse():e,o=(r,n,f=0,o=1732584193,a=271733878,l=e.of(o,~a,~o,a),u=r.length)=>{for(r[u-1]=n/2**29,r[(n-n%4)/4]|=128<<(r[u-2]=n<<3);f<u;f+=16){let{0:e,1:u,2:w,3:d}=l;for(n=o=0;n<16;n+=4)for(let l=29521>>n,h=1296>>n;o<4*n+16;u=0|((e+=t[o]+(w^(n>4?n>8?u|~d:u^d:n?d&(u^w):~u&(w^d)))+r[f+(o++*l+h&15)])>>>a|e<<32-a)+(e=d,d=w,w=u))a="94/*;72,<50):61+".charCodeAt(3&o|n);l[0]+=e,l[1]+=u,l[2]+=w,l[3]+=d}return l},a=(t,n,o=("string"==typeof t?t=(new TextEncoder).encode(t):t).length,a=new r(n+o+72-(o+8&63)))=>[f(new e(a.buffer),a.set(t,n),f(a)),o];var md5=(t,n,l)=>{var u=null!=n,[w,d]=a(t,64*u);if(u){let[r,t]=a(n,0),f=new e(32);for(t>64&&(r=o(r,t)),t=16;t;)f[--t]=1785358954^(w[t]=909522486^r[t]);f.set(o(w,64+d),16),w=f,d=80}return u=f(new r(f(o(w,d)).buffer)),l?u:u.reduce((e,r)=>e+(r>>4&&"")+r.toString(16),"")}}
|
package/main.d.ts
CHANGED
|
@@ -11,18 +11,18 @@
|
|
|
11
11
|
*/
|
|
12
12
|
declare var md5: {
|
|
13
13
|
(
|
|
14
|
-
data: string | Uint8Array | Uint8ClampedArray,
|
|
15
|
-
key?: string | Uint8Array | Uint8ClampedArray | null,
|
|
14
|
+
data: string | Uint8Array | Uint8ClampedArray | Int8Array | number[],
|
|
15
|
+
key?: string | Uint8Array | Uint8ClampedArray | Int8Array | number[] | null,
|
|
16
16
|
raw?: false
|
|
17
17
|
): string;
|
|
18
18
|
(
|
|
19
|
-
data: string | Uint8Array | Uint8ClampedArray,
|
|
20
|
-
key: string | Uint8Array | Uint8ClampedArray | null | undefined,
|
|
19
|
+
data: string | Uint8Array | Uint8ClampedArray | Int8Array | number[],
|
|
20
|
+
key: string | Uint8Array | Uint8ClampedArray | Int8Array | number[] | null | undefined,
|
|
21
21
|
raw: true
|
|
22
22
|
): Uint8Array<ArrayBuffer>;
|
|
23
23
|
(
|
|
24
|
-
data: string | Uint8Array | Uint8ClampedArray,
|
|
25
|
-
key: string | Uint8Array | Uint8ClampedArray | null | undefined,
|
|
24
|
+
data: string | Uint8Array | Uint8ClampedArray | Int8Array | number[],
|
|
25
|
+
key: string | Uint8Array | Uint8ClampedArray | Int8Array | number[] | null | undefined,
|
|
26
26
|
raw: boolean
|
|
27
27
|
): string | Uint8Array<ArrayBuffer>;
|
|
28
28
|
};
|
package/main.js
CHANGED
|
@@ -10,18 +10,17 @@ let K = new $Int32Array(64).map((v, i) => 2 ** 32 * Math.sin(++i % Math.PI))
|
|
|
10
10
|
/** is big-endian */
|
|
11
11
|
let isBE = /** @type {0 | 1} */(new $Uint8Array(K.buffer)[0] & 1)
|
|
12
12
|
|
|
13
|
-
/** @type {(
|
|
14
|
-
let
|
|
13
|
+
/** @type {<T extends { reverse(): T }>(a: T, ..._: any[]) => T} */
|
|
14
|
+
let reverseOnBE = a => isBE ? a.reverse() : a
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
* Calculate the MD5 of an
|
|
17
|
+
* Calculate the MD5 of an Int32Array of little-endian words, and a byte length.
|
|
18
18
|
*
|
|
19
|
-
* @
|
|
20
|
-
* @param
|
|
21
|
-
*
|
|
22
|
-
* @returns {Int32Array<ArrayBuffer>} MD5 Array
|
|
19
|
+
* @type {(x: Int32Array<ArrayBuffer>, l: number) => Int32Array<ArrayBuffer>}
|
|
20
|
+
* @param x words
|
|
21
|
+
* @param l Byte length
|
|
23
22
|
*/
|
|
24
|
-
let wordsMD5 = (
|
|
23
|
+
let wordsMD5 = ((
|
|
25
24
|
x,
|
|
26
25
|
l,
|
|
27
26
|
// var:
|
|
@@ -42,6 +41,7 @@ let wordsMD5 = (
|
|
|
42
41
|
let { 0: a, 1: b, 2: c, 3: d } = output
|
|
43
42
|
for (l = j = 0; l < 16; l += 4) {
|
|
44
43
|
for (
|
|
44
|
+
let mul = 0x7351 >> l, add = 0x0510 >> l
|
|
45
45
|
; j < 4 * l + 16
|
|
46
46
|
; b = 0 | (
|
|
47
47
|
(
|
|
@@ -56,8 +56,8 @@ let wordsMD5 = (
|
|
|
56
56
|
? d & (b ^ c) // Round 2: G
|
|
57
57
|
: ~b & (c ^ d) // Round 1: F
|
|
58
58
|
)) +
|
|
59
|
-
x[i + (j++ *
|
|
60
|
-
))
|
|
59
|
+
x[i + (j++ * mul + add & 15)]
|
|
60
|
+
)) >>> cnt | a << 32 - cnt // Keep `32 -` so JS engines can recognize bit rotation (ROR).
|
|
61
61
|
) + (
|
|
62
62
|
a = d,
|
|
63
63
|
d = c,
|
|
@@ -65,7 +65,7 @@ let wordsMD5 = (
|
|
|
65
65
|
)
|
|
66
66
|
)
|
|
67
67
|
) {
|
|
68
|
-
cnt = "
|
|
68
|
+
cnt = "94/*;72,<50):61+".charCodeAt(j & 3 | l)
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
output[0] += a
|
|
@@ -74,17 +74,17 @@ let wordsMD5 = (
|
|
|
74
74
|
output[3] += d
|
|
75
75
|
}
|
|
76
76
|
return output
|
|
77
|
-
}
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
/** @typedef {string | Uint8Array | Uint8ClampedArray | Int8Array | number[]} Input */
|
|
78
80
|
|
|
79
81
|
/**
|
|
80
|
-
* Convert bytes to an
|
|
82
|
+
* Convert bytes to an Int32Array of little-endian words
|
|
81
83
|
*
|
|
82
|
-
* @
|
|
83
|
-
* @param
|
|
84
|
-
*
|
|
85
|
-
* @returns {[Int32Array<ArrayBuffer>, number]}
|
|
84
|
+
* @type {(input: Input, padLen: number) => [Int32Array<ArrayBuffer>, number]}
|
|
85
|
+
* @param padLen pad byte-length (0 or 64)
|
|
86
86
|
*/
|
|
87
|
-
let inputToWords = (
|
|
87
|
+
let inputToWords = ((
|
|
88
88
|
input,
|
|
89
89
|
padLen,
|
|
90
90
|
// var:
|
|
@@ -94,14 +94,16 @@ let inputToWords = (
|
|
|
94
94
|
? input = new TextEncoder().encode(input)
|
|
95
95
|
: input
|
|
96
96
|
).length,
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
97
|
+
outputBytes = new $Uint8Array(padLen + byteLen + 72 - (byteLen + 8 & 63)),
|
|
98
|
+
) =>
|
|
99
|
+
[
|
|
100
|
+
reverseOnBE(
|
|
101
|
+
new $Int32Array(outputBytes.buffer),
|
|
102
|
+
outputBytes.set(/** @type {Exclude<Input, string>} */(input), padLen),
|
|
103
|
+
reverseOnBE(outputBytes)
|
|
104
|
+
),
|
|
105
|
+
byteLen
|
|
106
|
+
]
|
|
105
107
|
)
|
|
106
108
|
|
|
107
109
|
/**
|
|
@@ -110,8 +112,8 @@ let inputToWords = (
|
|
|
110
112
|
* By default, returns the hash as a lowercase hexadecimal string.
|
|
111
113
|
* If `raw` is true, returns a Uint8Array.
|
|
112
114
|
*
|
|
113
|
-
* @param {
|
|
114
|
-
* @param {
|
|
115
|
+
* @param {Input} data The input data to hash. Strings are UTF‑8 encoded.
|
|
116
|
+
* @param {Input | null} [key] Optional HMAC key. When given, HMAC‑MD5 is calculated instead of plain MD5.
|
|
115
117
|
* @param {boolean} [raw] If true, the hash is returned as raw bytes (Uint8Array); otherwise, as a hex string.
|
|
116
118
|
* @returns {string | Uint8Array<ArrayBuffer>} The MD5 (or HMAC‑MD5) digest, either as a hex string or a Uint8Array.
|
|
117
119
|
*/
|
|
@@ -119,17 +121,16 @@ let md5 = (data, key, raw) => {
|
|
|
119
121
|
// Do not use parameter defaults to declare variables in public functions.
|
|
120
122
|
/** @type {boolean | Uint8Array<ArrayBuffer>} */
|
|
121
123
|
var temp = key != null
|
|
122
|
-
, [bdata, dataByteLen] = inputToWords(data,
|
|
124
|
+
, [bdata, dataByteLen] = inputToWords(data, /** @type {*} */(temp) * 64)
|
|
123
125
|
|
|
124
126
|
if (temp) {
|
|
125
127
|
// HMAC
|
|
126
|
-
let [bkey,
|
|
128
|
+
let [bkey, i] = inputToWords(key, 0)
|
|
127
129
|
, opad = new $Int32Array(32)
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
bkey = wordsMD5(bkey, keyByteLen)
|
|
130
|
+
if (i > 64) {
|
|
131
|
+
bkey = wordsMD5(bkey, i)
|
|
131
132
|
}
|
|
132
|
-
for (; i;) {
|
|
133
|
+
for (i = 16; i;) {
|
|
133
134
|
// (0x36363636 ^ 0x5c5c5c5c) == 0x6a6a6a6a
|
|
134
135
|
opad[--i] = 0x6a6a6a6a ^ (bdata[i] = 0x36363636 ^ bkey[i])
|
|
135
136
|
}
|
|
@@ -138,10 +139,13 @@ let md5 = (data, key, raw) => {
|
|
|
138
139
|
dataByteLen = 80
|
|
139
140
|
}
|
|
140
141
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
142
|
+
temp = reverseOnBE(
|
|
143
|
+
new $Uint8Array(
|
|
144
|
+
reverseOnBE(
|
|
145
|
+
wordsMD5(bdata, dataByteLen)
|
|
146
|
+
).buffer
|
|
147
|
+
)
|
|
148
|
+
)
|
|
145
149
|
return raw
|
|
146
150
|
? temp
|
|
147
151
|
: temp.reduce((p, v) => p + (v >> 4 && "") + v.toString(16), "")
|
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.3",
|
|
4
|
+
"description": "A tiny (926 Bytes), fast and reliable implementation of MD5 and HMAC-MD5 for JavaScript.",
|
|
5
5
|
"author": "bddjr",
|
|
6
6
|
"license": "Unlicense",
|
|
7
7
|
"type": "module",
|
|
@@ -56,10 +56,10 @@
|
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"blueimp-md5": "^2.19.0",
|
|
58
58
|
"crypto-js": "^4.2.0",
|
|
59
|
-
"es-check": "^9.
|
|
59
|
+
"es-check": "^9.7.1",
|
|
60
60
|
"js-md5": "^0.9.2",
|
|
61
61
|
"spark-md5": "^3.0.2",
|
|
62
|
-
"terser": "^5.
|
|
62
|
+
"terser": "^5.51.2",
|
|
63
63
|
"tinyhmacmd5": "link:",
|
|
64
64
|
"typescript": "^7.0.2"
|
|
65
65
|
},
|