Skip to content

Commit cbf9d1d

Browse files
feat: added md4 (wasm version) and md4-native (crypto module version) algorithms
1 parent 58bb233 commit cbf9d1d

8 files changed

+338
-234
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,12 @@ The following tokens are replaced in the `name` parameter:
7575
- `[query]` the queryof the resource, i.e. `?foo=bar`
7676
- `[contenthash]` the hash of `options.content` (Buffer) (by default it's the hex digest of the `xxhash64` hash)
7777
- `[<hashType>:contenthash:<digestType>:<length>]` optionally one can configure
78-
- other `hashType`s, i. e. `xxhash64`, `sha1`, `md4`, `md5`, `sha256`, `sha512`
78+
- other `hashType`s, i. e. `xxhash64`, `sha1`, `md4` (wasm version), `native-md4` (`crypto` module version), `md5`, `sha256`, `sha512`
7979
- other `digestType`s, i. e. `hex`, `base26`, `base32`, `base36`, `base49`, `base52`, `base58`, `base62`, `base64`
8080
- and `length` the length in chars
8181
- `[hash]` the hash of `options.content` (Buffer) (by default it's the hex digest of the `xxhash64` hash)
8282
- `[<hashType>:hash:<digestType>:<length>]` optionally one can configure
83-
- other `hashType`s, i. e. `xxhash64`, `sha1`, `md4`, `md5`, `sha256`, `sha512`
83+
- other `hashType`s, i. e. `xxhash64`, `sha1`, `md4` (wasm version), `native-md4` (`crypto` module version), `md5`, `sha256`, `sha512`
8484
- other `digestType`s, i. e. `hex`, `base26`, `base32`, `base36`, `base49`, `base52`, `base58`, `base62`, `base64`
8585
- and `length` the length in chars
8686
- `[N]` the N-th match obtained from matching the current file name against `options.regExp`

lib/getHashDigest.js

Lines changed: 29 additions & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -1,168 +1,5 @@
11
"use strict";
22

3-
// Copied from `webpack`
4-
//#region wasm code: xxhash64 (../../../assembly/hash/xxhash64.asm.ts) --initialMemory 1
5-
const xxhash64 = new WebAssembly.Module(
6-
Buffer.from(
7-
// 1180 bytes
8-
"AGFzbQEAAAABCAJgAX8AYAAAAwQDAQAABQMBAAEGGgV+AUIAC34BQgALfgFCAAt+AUIAC34BQgALByIEBGluaXQAAAZ1cGRhdGUAAQVmaW5hbAACBm1lbW9yeQIACrwIAzAAQtbrgu7q/Yn14AAkAELP1tO+0ser2UIkAUIAJAJC+erQ0OfJoeThACQDQgAkBAvUAQIBfwR+IABFBEAPCyMEIACtfCQEIwAhAiMBIQMjAiEEIwMhBQNAIAIgASkDAELP1tO+0ser2UJ+fEIfiUKHla+vmLbem55/fiECIAMgASkDCELP1tO+0ser2UJ+fEIfiUKHla+vmLbem55/fiEDIAQgASkDEELP1tO+0ser2UJ+fEIfiUKHla+vmLbem55/fiEEIAUgASkDGELP1tO+0ser2UJ+fEIfiUKHla+vmLbem55/fiEFIAAgAUEgaiIBSw0ACyACJAAgAyQBIAQkAiAFJAMLsgYCAX8EfiMEQgBSBH4jACICQgGJIwEiA0IHiXwjAiIEQgyJfCMDIgVCEol8IAJCz9bTvtLHq9lCfkIfiUKHla+vmLbem55/foVCh5Wvr5i23puef35CnaO16oOxjYr6AH0gA0LP1tO+0ser2UJ+Qh+JQoeVr6+Ytt6bnn9+hUKHla+vmLbem55/fkKdo7Xqg7GNivoAfSAEQs/W077Sx6vZQn5CH4lCh5Wvr5i23puef36FQoeVr6+Ytt6bnn9+Qp2jteqDsY2K+gB9IAVCz9bTvtLHq9lCfkIfiUKHla+vmLbem55/foVCh5Wvr5i23puef35CnaO16oOxjYr6AH0FQsXP2bLx5brqJwsjBCAArXx8IQIDQCABQQhqIABNBEAgAiABKQMAQs/W077Sx6vZQn5CH4lCh5Wvr5i23puef36FQhuJQoeVr6+Ytt6bnn9+Qp2jteqDsY2K+gB9IQIgAUEIaiEBDAELCyABQQRqIABNBEACfyACIAE1AgBCh5Wvr5i23puef36FQheJQs/W077Sx6vZQn5C+fPd8Zn2masWfCECIAFBBGoLIQELA0AgACABRwRAIAIgATEAAELFz9my8eW66id+hUILiUKHla+vmLbem55/fiECIAFBAWohAQwBCwtBACACIAJCIYiFQs/W077Sx6vZQn4iAiACQh2IhUL5893xmfaZqxZ+IgIgAkIgiIUiAjcDAEEAIAJCIIgiA0L//wODQiCGIANCgID8/w+DQhCIhCIDQv+BgIDwH4NCEIYgA0KA/oOAgOA/g0IIiIQiA0KPgLyA8IHAB4NCCIYgA0LwgcCHgJ6A+ACDQgSIhCIDQoaMmLDgwIGDBnxCBIhCgYKEiJCgwIABg0InfiADQrDgwIGDhoyYMIR8NwMAQQggAkL/////D4MiAkL//wODQiCGIAJCgID8/w+DQhCIhCICQv+BgIDwH4NCEIYgAkKA/oOAgOA/g0IIiIQiAkKPgLyA8IHAB4NCCIYgAkLwgcCHgJ6A+ACDQgSIhCICQoaMmLDgwIGDBnxCBIhCgYKEiJCgwIABg0InfiACQrDgwIGDhoyYMIR8NwMACw==",
9-
"base64"
10-
)
11-
);
12-
//#endregion
13-
14-
class XxHash64 {
15-
/**
16-
* @param {WebAssembly.Instance} instance wasm instance
17-
*/
18-
constructor(instance) {
19-
const exports = /** @type {any} */ (instance.exports);
20-
21-
exports.init();
22-
23-
this.exports = exports;
24-
this.mem = Buffer.from(exports.memory.buffer, 0, 65536);
25-
this.buffered = 0;
26-
}
27-
28-
reset() {
29-
this.buffered = 0;
30-
this.exports.init();
31-
}
32-
33-
/**
34-
* @param {Buffer | string} data data
35-
* @param {BufferEncoding=} encoding encoding
36-
* @returns {this} itself
37-
*/
38-
update(data, encoding) {
39-
if (typeof data === "string") {
40-
if (data.length < 21845) {
41-
this._updateWithShortString(data, encoding);
42-
43-
return this;
44-
} else {
45-
data = Buffer.from(data, encoding);
46-
}
47-
}
48-
49-
this._updateWithBuffer(data);
50-
51-
return this;
52-
}
53-
54-
/**
55-
* @param {string} data data
56-
* @param {BufferEncoding=} encoding encoding
57-
* @returns {void}
58-
*/
59-
_updateWithShortString(data, encoding) {
60-
const { exports, buffered, mem } = this;
61-
62-
let endPos;
63-
64-
if (data.length < 70) {
65-
if (!encoding || encoding === "utf-8" || encoding === "utf8") {
66-
endPos = buffered;
67-
68-
for (let i = 0; i < data.length; i++) {
69-
const cc = data.charCodeAt(i);
70-
71-
if (cc < 0x80) {
72-
mem[endPos++] = cc;
73-
} else if (cc < 0x800) {
74-
mem[endPos] = (cc >> 6) | 0xc0;
75-
mem[endPos + 1] = (cc & 0x3f) | 0x80;
76-
endPos += 2;
77-
} else {
78-
// bail-out for weird chars
79-
endPos += mem.write(data.slice(endPos), endPos, encoding);
80-
break;
81-
}
82-
}
83-
} else if (encoding === "latin1") {
84-
endPos = buffered;
85-
86-
for (let i = 0; i < data.length; i++) {
87-
const cc = data.charCodeAt(i);
88-
89-
mem[endPos++] = cc;
90-
}
91-
} else {
92-
endPos = buffered + mem.write(data, buffered, encoding);
93-
}
94-
} else {
95-
endPos = buffered + mem.write(data, buffered, encoding);
96-
}
97-
98-
if (endPos < 32) {
99-
this.buffered = endPos;
100-
} else {
101-
const l = (endPos >> 5) << 5;
102-
103-
exports.update(l);
104-
105-
const newBuffered = endPos - l;
106-
107-
this.buffered = newBuffered;
108-
109-
if (newBuffered > 0) {
110-
mem.copyWithin(0, l, endPos);
111-
}
112-
}
113-
}
114-
115-
/**
116-
* @param {Buffer} data data
117-
* @returns {void}
118-
*/
119-
_updateWithBuffer(data) {
120-
const { exports, buffered, mem } = this;
121-
const length = data.length;
122-
if (buffered + length < 32) {
123-
data.copy(mem, buffered, 0, length);
124-
this.buffered += length;
125-
} else {
126-
const l = ((buffered + length) >> 5) << 5;
127-
if (l > 65536) {
128-
let i = 65536 - buffered;
129-
data.copy(mem, buffered, 0, i);
130-
exports.update(65536);
131-
const stop = l - buffered - 65536;
132-
while (i < stop) {
133-
data.copy(mem, 0, i, i + 65536);
134-
exports.update(65536);
135-
i += 65536;
136-
}
137-
data.copy(mem, 0, i, l - buffered);
138-
exports.update(l - buffered - i);
139-
} else {
140-
data.copy(mem, buffered, 0, l - buffered);
141-
exports.update(l);
142-
}
143-
144-
const newBuffered = length + buffered - l;
145-
146-
this.buffered = newBuffered;
147-
148-
if (newBuffered > 0) {
149-
data.copy(mem, 0, length - newBuffered, length);
150-
}
151-
}
152-
}
153-
154-
digest() {
155-
const { exports, buffered, mem } = this;
156-
157-
exports.final(buffered);
158-
instancesPool.push(this);
159-
160-
return mem.toString("latin1", 0, 16);
161-
}
162-
}
163-
164-
const instancesPool = [];
165-
1663
const baseEncodeTables = {
1674
26: "abcdefghijklmnopqrstuvwxyz",
1685
32: "123456789abcdefghjkmnpqrstuvwxyz", // no 0lio
@@ -205,17 +42,9 @@ function encodeBufferToBase(buffer, base) {
20542
return output;
20643
}
20744

208-
const create = () => {
209-
if (instancesPool.length > 0) {
210-
const old = instancesPool.pop();
211-
212-
old.reset();
213-
214-
return old;
215-
} else {
216-
return new XxHash64(new WebAssembly.Instance(xxhash64));
217-
}
218-
};
45+
let crypto = undefined;
46+
let createXXHash64 = undefined;
47+
let createMd4 = undefined;
21948

22049
function getHashDigest(buffer, hashType, digestType, maxLength) {
22150
hashType = hashType || "xxhash64";
@@ -224,9 +53,29 @@ function getHashDigest(buffer, hashType, digestType, maxLength) {
22453
let hash;
22554

22655
if (hashType === "xxhash64") {
227-
hash = create(maxLength);
56+
if (createXXHash64 === undefined) {
57+
createXXHash64 = require("./hash/xxhash64");
58+
}
59+
60+
hash = createXXHash64();
61+
} else if (hashType === "md4") {
62+
if (createMd4 === undefined) {
63+
createMd4 = require("./hash/md4");
64+
}
65+
66+
hash = createMd4();
67+
} else if (hashType === "native-md4") {
68+
if (typeof crypto === "undefined") {
69+
crypto = require("crypto");
70+
}
71+
72+
hash = crypto.createHash("md4");
22873
} else {
229-
hash = require("crypto").createHash(hashType);
74+
if (typeof crypto === "undefined") {
75+
crypto = require("crypto");
76+
}
77+
78+
hash = crypto.createHash(hashType);
23079
}
23180

23281
hash.update(buffer);
@@ -241,10 +90,10 @@ function getHashDigest(buffer, hashType, digestType, maxLength) {
24190
digestType === "base62" ||
24291
digestType === "base64"
24392
) {
244-
return encodeBufferToBase(
245-
hashType === "xxhash64" ? Buffer.from(hash.digest()) : hash.digest(),
246-
digestType.substr(4)
247-
).substr(0, maxLength);
93+
return encodeBufferToBase(hash.digest(), digestType.substr(4)).substr(
94+
0,
95+
maxLength
96+
);
24897
} else {
24998
return hash.digest(digestType || "hex").substr(0, maxLength);
25099
}

lib/hash/md4.js

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy