This repository was archived by the owner on Dec 17, 2025. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 188
Expand file tree
/
Copy pathgetHashDigest.ts
More file actions
159 lines (133 loc) · 4.55 KB
/
getHashDigest.ts
File metadata and controls
159 lines (133 loc) · 4.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import { Hash } from "crypto";
const baseEncodeTables = {
26: "abcdefghijklmnopqrstuvwxyz",
32: "123456789abcdefghjkmnpqrstuvwxyz", // no 0lio
36: "0123456789abcdefghijklmnopqrstuvwxyz",
49: "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ", // no lIO
52: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
58: "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ", // no 0lIO
62: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
64: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_",
};
type DigestTypes =
| "base26"
| "base32"
| "base36"
| "base49"
| "base52"
| "base58"
| "base62"
| "base64";
type BaseEncodings = 26 | 32 | 36 | 49 | 52 | 58 | 62 | 64;
/**
* @param {Uint32Array} uint32Array Treated as a long base-0x100000000 number, little endian
* @param {number} divisor The divisor
* @return {number} Modulo (remainder) of the division
*/
function divmod32(uint32Array: Uint32Array, divisor: number): number {
let carry = 0;
for (let i = uint32Array.length - 1; i >= 0; i--) {
const value = carry * 0x100000000 + uint32Array[i];
carry = value % divisor;
uint32Array[i] = Math.floor(value / divisor);
}
return carry;
}
function encodeBufferToBase(
buffer: Buffer,
base: BaseEncodings | number,
length: number
) {
const encodeTable = baseEncodeTables[base as keyof typeof baseEncodeTables];
if (!encodeTable) {
throw new Error("Unknown encoding base" + base);
}
// Input bits are only enough to generate this many characters
const limit = Math.ceil((buffer.length * 8) / Math.log2(base));
length = Math.min(length, limit);
// Most of the crypto digests (if not all) has length a multiple of 4 bytes.
// Fewer numbers in the array means faster math.
const uint32Array = new Uint32Array(Math.ceil(buffer.length / 4));
// Make sure the input buffer data is copied and is not mutated by reference.
// divmod32() would corrupt the BulkUpdateDecorator cache otherwise.
buffer.copy(Buffer.from(uint32Array.buffer));
let output = "";
for (let i = 0; i < length; i++) {
output = encodeTable[divmod32(uint32Array, base)] + output;
}
return output;
}
let crypto: typeof import("crypto");
let createXXHash64: typeof import("./hash/xxhash64").default;
let createMd4: typeof import("./hash/md4").default;
let BatchedHash: typeof import("./hash/BatchedHash").default;
let BulkUpdateDecorator: typeof import("./hash/BulkUpdateDecorator").default;
export default function getHashDigest(
buffer: Buffer,
algorithm: string | "xxhash64" | "md4" | "native-md4",
digestType: DigestTypes | string,
maxLength: number
) {
algorithm = algorithm || "xxhash64";
maxLength = maxLength || 9999;
let hash;
if (algorithm === "xxhash64") {
if (createXXHash64 === undefined) {
createXXHash64 = require("./hash/xxhash64").default;
if (BatchedHash === undefined) {
BatchedHash = require("./hash/BatchedHash").default;
}
}
hash = new BatchedHash(createXXHash64() as unknown as Hash);
} else if (algorithm === "md4") {
if (createMd4 === undefined) {
createMd4 = require("./hash/md4").default;
if (BatchedHash === undefined) {
BatchedHash = require("./hash/BatchedHash").default;
}
}
hash = new BatchedHash(createMd4() as unknown as Hash);
} else if (algorithm === "native-md4") {
if (typeof crypto === "undefined") {
crypto = require("crypto");
if (BulkUpdateDecorator === undefined) {
BulkUpdateDecorator = require("./hash/BulkUpdateDecorator").default;
}
}
hash = new BulkUpdateDecorator(() => crypto.createHash("md4"), "md4");
} else {
if (typeof crypto === "undefined") {
crypto = require("crypto");
if (BulkUpdateDecorator === undefined) {
BulkUpdateDecorator = require("./hash/BulkUpdateDecorator").default;
}
}
hash = new BulkUpdateDecorator(
() => crypto.createHash(algorithm),
algorithm
);
}
hash.update(buffer);
if (
digestType === "base26" ||
digestType === "base32" ||
digestType === "base36" ||
digestType === "base49" ||
digestType === "base52" ||
digestType === "base58" ||
digestType === "base62"
) {
const digestTypeToDigest: number = digestType.substr(
4
) as unknown as number;
return encodeBufferToBase(
hash.digest() as Buffer,
digestTypeToDigest,
maxLength
);
} else {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return hash.digest(digestType || "hex").substr(0, maxLength);
}
}