Skip to content

Commit 8c2d24e

Browse files
fix: base64 generation and unicode characters (#197)
1 parent 5fb5562 commit 8c2d24e

5 files changed

+79
-11
lines changed

lib/getHashDigest.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ function encodeBufferToBase(buffer, base) {
4040
}
4141

4242
let createMd4 = undefined;
43+
let BatchedHash = undefined;
4344

4445
function getHashDigest(buffer, hashType, digestType, maxLength) {
4546
hashType = hashType || 'md4';
@@ -53,9 +54,13 @@ function getHashDigest(buffer, hashType, digestType, maxLength) {
5354
if (error.code === 'ERR_OSSL_EVP_UNSUPPORTED' && hashType === 'md4') {
5455
if (createMd4 === undefined) {
5556
createMd4 = require('./hash/md4');
57+
58+
if (BatchedHash === undefined) {
59+
BatchedHash = require('./hash/BatchedHash');
60+
}
5661
}
5762

58-
hash = createMd4();
63+
hash = new BatchedHash(createMd4());
5964
}
6065

6166
if (!hash) {
@@ -72,8 +77,7 @@ function getHashDigest(buffer, hashType, digestType, maxLength) {
7277
digestType === 'base49' ||
7378
digestType === 'base52' ||
7479
digestType === 'base58' ||
75-
digestType === 'base62' ||
76-
digestType === 'base64'
80+
digestType === 'base62'
7781
) {
7882
return encodeBufferToBase(hash.digest(), digestType.substr(4)).substr(
7983
0,

lib/hash/BatchedHash.js

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
const MAX_SHORT_STRING = require('./wasm-hash').MAX_SHORT_STRING;
2+
3+
class BatchedHash {
4+
constructor(hash) {
5+
this.string = undefined;
6+
this.encoding = undefined;
7+
this.hash = hash;
8+
}
9+
10+
/**
11+
* Update hash {@link https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding}
12+
* @param {string|Buffer} data data
13+
* @param {string=} inputEncoding data encoding
14+
* @returns {this} updated hash
15+
*/
16+
update(data, inputEncoding) {
17+
if (this.string !== undefined) {
18+
if (
19+
typeof data === 'string' &&
20+
inputEncoding === this.encoding &&
21+
this.string.length + data.length < MAX_SHORT_STRING
22+
) {
23+
this.string += data;
24+
25+
return this;
26+
}
27+
28+
this.hash.update(this.string, this.encoding);
29+
this.string = undefined;
30+
}
31+
32+
if (typeof data === 'string') {
33+
if (
34+
data.length < MAX_SHORT_STRING &&
35+
// base64 encoding is not valid since it may contain padding chars
36+
(!inputEncoding || !inputEncoding.startsWith('ba'))
37+
) {
38+
this.string = data;
39+
this.encoding = inputEncoding;
40+
} else {
41+
this.hash.update(data, inputEncoding);
42+
}
43+
} else {
44+
this.hash.update(data);
45+
}
46+
47+
return this;
48+
}
49+
50+
/**
51+
* Calculates the digest {@link https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding}
52+
* @param {string=} encoding encoding of the return value
53+
* @returns {string|Buffer} digest
54+
*/
55+
digest(encoding) {
56+
if (this.string !== undefined) {
57+
this.hash.update(this.string, this.encoding);
58+
}
59+
60+
return this.hash.digest(encoding);
61+
}
62+
}
63+
64+
module.exports = BatchedHash;

lib/hash/wasm-hash.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class WasmHash {
8282
endPos += 2;
8383
} else {
8484
// bail-out for weird chars
85-
endPos += mem.write(data.slice(endPos), endPos, encoding);
85+
endPos += mem.write(data.slice(i), endPos, encoding);
8686
break;
8787
}
8888
}

test/getHashDigest.test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ describe('getHashDigest()', () => {
1212
'6f8db599de986fab7a21625b7916589c',
1313
],
1414
['test string', 'md5', 'hex', 4, '6f8d'],
15-
['test string', 'md5', 'base64', undefined, '2sm1pVmS8xuGJLCdWpJoRL'],
15+
['test string', 'md5', 'base64', undefined, 'b421md6Yb6t6IWJbeRZYnA=='],
1616
['test string', 'md5', 'base52', undefined, 'dJnldHSAutqUacjgfBQGLQx'],
1717
['test string', 'md5', 'base26', 6, 'bhtsgu'],
1818
[
1919
'test string',
2020
'sha512',
2121
'base64',
2222
undefined,
23-
'2IS-kbfIPnVflXb9CzgoNESGCkvkb0urMmucPD9z8q6HuYz8RShY1-tzSUpm5-Ivx_u4H1MEzPgAhyhaZ7RKog',
23+
'EObWR69EYkRC84jCwUp4f/ixfmFluD12fsBHdo2MvLcaGjIm58x4Frx5wEJ9lKnaaIxBo5kse/Xk18w+C+XbrA==',
2424
],
2525
[
2626
'test string',

test/interpolateName.test.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,13 @@ describe('interpolateName()', () => {
6262
'/app/img/image.png',
6363
'[sha512:hash:base64:7].[ext]',
6464
'test content',
65-
'2BKDTjl.png',
65+
'DL9MrvO.png',
6666
],
6767
[
6868
'/app/img/image.png',
6969
'[sha512:contenthash:base64:7].[ext]',
7070
'test content',
71-
'2BKDTjl.png',
71+
'DL9MrvO.png',
7272
],
7373
[
7474
'/app/dir/file.png',
@@ -116,13 +116,13 @@ describe('interpolateName()', () => {
116116
'/lib/components/modal/modal.css',
117117
'[name].[md5:hash:base64:20].[ext]',
118118
'test content',
119-
'modal.1n8osQznuT8jOAwdzg_n.css',
119+
'modal.lHP90NiApDwht3eNNIch.css',
120120
],
121121
[
122122
'/lib/components/modal/modal.css',
123123
'[name].[md5:contenthash:base64:20].[ext]',
124124
'test content',
125-
'modal.1n8osQznuT8jOAwdzg_n.css',
125+
'modal.lHP90NiApDwht3eNNIch.css',
126126
],
127127
// Should not interpret without `hash` or `contenthash`
128128
[
@@ -265,7 +265,7 @@ describe('interpolateName()', () => {
265265
],
266266
[
267267
[{}, '[hash:base64]', { content: 'test string' }],
268-
'2LIG3oc1uBNmwOoL7kXgoK',
268+
'Lgbt1PFiMmjFpRcw2KCyrw==',
269269
'should interpolate [hash] token with options',
270270
],
271271
[

0 commit comments

Comments
 (0)