ts-md5
Version:
TypeScript MD5 implementation
270 lines (269 loc) • 13.3 kB
JavaScript
const c = new Int32Array(4);
class h {
static hashStr(i, a = !1) {
return this.onePassHasher.start().appendStr(i).end(a);
}
static hashAsciiStr(i, a = !1) {
return this.onePassHasher.start().appendAsciiStr(i).end(a);
}
// Private Static Variables
static stateIdentity = new Int32Array([
1732584193,
-271733879,
-1732584194,
271733878
]);
static buffer32Identity = new Int32Array([
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
]);
static hexChars = "0123456789abcdef";
static hexOut = [];
// Permanent instance is to use for one-call hashing
static onePassHasher = new h();
static _hex(i) {
const a = h.hexChars, t = h.hexOut;
let e, s, r, n;
for (n = 0; n < 4; n += 1)
for (s = n * 8, e = i[n], r = 0; r < 8; r += 2)
t[s + 1 + r] = a.charAt(e & 15), e >>>= 4, t[s + 0 + r] = a.charAt(e & 15), e >>>= 4;
return t.join("");
}
static _md5cycle(i, a) {
let t = i[0], e = i[1], s = i[2], r = i[3];
t += (e & s | ~e & r) + a[0] - 680876936 | 0, t = (t << 7 | t >>> 25) + e | 0, r += (t & e | ~t & s) + a[1] - 389564586 | 0, r = (r << 12 | r >>> 20) + t | 0, s += (r & t | ~r & e) + a[2] + 606105819 | 0, s = (s << 17 | s >>> 15) + r | 0, e += (s & r | ~s & t) + a[3] - 1044525330 | 0, e = (e << 22 | e >>> 10) + s | 0, t += (e & s | ~e & r) + a[4] - 176418897 | 0, t = (t << 7 | t >>> 25) + e | 0, r += (t & e | ~t & s) + a[5] + 1200080426 | 0, r = (r << 12 | r >>> 20) + t | 0, s += (r & t | ~r & e) + a[6] - 1473231341 | 0, s = (s << 17 | s >>> 15) + r | 0, e += (s & r | ~s & t) + a[7] - 45705983 | 0, e = (e << 22 | e >>> 10) + s | 0, t += (e & s | ~e & r) + a[8] + 1770035416 | 0, t = (t << 7 | t >>> 25) + e | 0, r += (t & e | ~t & s) + a[9] - 1958414417 | 0, r = (r << 12 | r >>> 20) + t | 0, s += (r & t | ~r & e) + a[10] - 42063 | 0, s = (s << 17 | s >>> 15) + r | 0, e += (s & r | ~s & t) + a[11] - 1990404162 | 0, e = (e << 22 | e >>> 10) + s | 0, t += (e & s | ~e & r) + a[12] + 1804603682 | 0, t = (t << 7 | t >>> 25) + e | 0, r += (t & e | ~t & s) + a[13] - 40341101 | 0, r = (r << 12 | r >>> 20) + t | 0, s += (r & t | ~r & e) + a[14] - 1502002290 | 0, s = (s << 17 | s >>> 15) + r | 0, e += (s & r | ~s & t) + a[15] + 1236535329 | 0, e = (e << 22 | e >>> 10) + s | 0, t += (e & r | s & ~r) + a[1] - 165796510 | 0, t = (t << 5 | t >>> 27) + e | 0, r += (t & s | e & ~s) + a[6] - 1069501632 | 0, r = (r << 9 | r >>> 23) + t | 0, s += (r & e | t & ~e) + a[11] + 643717713 | 0, s = (s << 14 | s >>> 18) + r | 0, e += (s & t | r & ~t) + a[0] - 373897302 | 0, e = (e << 20 | e >>> 12) + s | 0, t += (e & r | s & ~r) + a[5] - 701558691 | 0, t = (t << 5 | t >>> 27) + e | 0, r += (t & s | e & ~s) + a[10] + 38016083 | 0, r = (r << 9 | r >>> 23) + t | 0, s += (r & e | t & ~e) + a[15] - 660478335 | 0, s = (s << 14 | s >>> 18) + r | 0, e += (s & t | r & ~t) + a[4] - 405537848 | 0, e = (e << 20 | e >>> 12) + s | 0, t += (e & r | s & ~r) + a[9] + 568446438 | 0, t = (t << 5 | t >>> 27) + e | 0, r += (t & s | e & ~s) + a[14] - 1019803690 | 0, r = (r << 9 | r >>> 23) + t | 0, s += (r & e | t & ~e) + a[3] - 187363961 | 0, s = (s << 14 | s >>> 18) + r | 0, e += (s & t | r & ~t) + a[8] + 1163531501 | 0, e = (e << 20 | e >>> 12) + s | 0, t += (e & r | s & ~r) + a[13] - 1444681467 | 0, t = (t << 5 | t >>> 27) + e | 0, r += (t & s | e & ~s) + a[2] - 51403784 | 0, r = (r << 9 | r >>> 23) + t | 0, s += (r & e | t & ~e) + a[7] + 1735328473 | 0, s = (s << 14 | s >>> 18) + r | 0, e += (s & t | r & ~t) + a[12] - 1926607734 | 0, e = (e << 20 | e >>> 12) + s | 0, t += (e ^ s ^ r) + a[5] - 378558 | 0, t = (t << 4 | t >>> 28) + e | 0, r += (t ^ e ^ s) + a[8] - 2022574463 | 0, r = (r << 11 | r >>> 21) + t | 0, s += (r ^ t ^ e) + a[11] + 1839030562 | 0, s = (s << 16 | s >>> 16) + r | 0, e += (s ^ r ^ t) + a[14] - 35309556 | 0, e = (e << 23 | e >>> 9) + s | 0, t += (e ^ s ^ r) + a[1] - 1530992060 | 0, t = (t << 4 | t >>> 28) + e | 0, r += (t ^ e ^ s) + a[4] + 1272893353 | 0, r = (r << 11 | r >>> 21) + t | 0, s += (r ^ t ^ e) + a[7] - 155497632 | 0, s = (s << 16 | s >>> 16) + r | 0, e += (s ^ r ^ t) + a[10] - 1094730640 | 0, e = (e << 23 | e >>> 9) + s | 0, t += (e ^ s ^ r) + a[13] + 681279174 | 0, t = (t << 4 | t >>> 28) + e | 0, r += (t ^ e ^ s) + a[0] - 358537222 | 0, r = (r << 11 | r >>> 21) + t | 0, s += (r ^ t ^ e) + a[3] - 722521979 | 0, s = (s << 16 | s >>> 16) + r | 0, e += (s ^ r ^ t) + a[6] + 76029189 | 0, e = (e << 23 | e >>> 9) + s | 0, t += (e ^ s ^ r) + a[9] - 640364487 | 0, t = (t << 4 | t >>> 28) + e | 0, r += (t ^ e ^ s) + a[12] - 421815835 | 0, r = (r << 11 | r >>> 21) + t | 0, s += (r ^ t ^ e) + a[15] + 530742520 | 0, s = (s << 16 | s >>> 16) + r | 0, e += (s ^ r ^ t) + a[2] - 995338651 | 0, e = (e << 23 | e >>> 9) + s | 0, t += (s ^ (e | ~r)) + a[0] - 198630844 | 0, t = (t << 6 | t >>> 26) + e | 0, r += (e ^ (t | ~s)) + a[7] + 1126891415 | 0, r = (r << 10 | r >>> 22) + t | 0, s += (t ^ (r | ~e)) + a[14] - 1416354905 | 0, s = (s << 15 | s >>> 17) + r | 0, e += (r ^ (s | ~t)) + a[5] - 57434055 | 0, e = (e << 21 | e >>> 11) + s | 0, t += (s ^ (e | ~r)) + a[12] + 1700485571 | 0, t = (t << 6 | t >>> 26) + e | 0, r += (e ^ (t | ~s)) + a[3] - 1894986606 | 0, r = (r << 10 | r >>> 22) + t | 0, s += (t ^ (r | ~e)) + a[10] - 1051523 | 0, s = (s << 15 | s >>> 17) + r | 0, e += (r ^ (s | ~t)) + a[1] - 2054922799 | 0, e = (e << 21 | e >>> 11) + s | 0, t += (s ^ (e | ~r)) + a[8] + 1873313359 | 0, t = (t << 6 | t >>> 26) + e | 0, r += (e ^ (t | ~s)) + a[15] - 30611744 | 0, r = (r << 10 | r >>> 22) + t | 0, s += (t ^ (r | ~e)) + a[6] - 1560198380 | 0, s = (s << 15 | s >>> 17) + r | 0, e += (r ^ (s | ~t)) + a[13] + 1309151649 | 0, e = (e << 21 | e >>> 11) + s | 0, t += (s ^ (e | ~r)) + a[4] - 145523070 | 0, t = (t << 6 | t >>> 26) + e | 0, r += (e ^ (t | ~s)) + a[11] - 1120210379 | 0, r = (r << 10 | r >>> 22) + t | 0, s += (t ^ (r | ~e)) + a[2] + 718787259 | 0, s = (s << 15 | s >>> 17) + r | 0, e += (r ^ (s | ~t)) + a[9] - 343485551 | 0, e = (e << 21 | e >>> 11) + s | 0, i[0] = t + i[0] | 0, i[1] = e + i[1] | 0, i[2] = s + i[2] | 0, i[3] = r + i[3] | 0;
}
_dataLength = 0;
_bufferLength = 0;
_state = new Int32Array(4);
_buffer = new ArrayBuffer(68);
_buffer8;
_buffer32;
constructor() {
this._buffer8 = new Uint8Array(this._buffer, 0, 68), this._buffer32 = new Uint32Array(this._buffer, 0, 17), this.start();
}
/**
* Initialise buffer to be hashed
*/
start() {
return this._dataLength = 0, this._bufferLength = 0, this._state.set(h.stateIdentity), this;
}
// Char to code point to to array conversion:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt
// #Example.3A_Fixing_charCodeAt_to_handle_non-Basic-Multilingual-Plane_characters_if_their_presence_earlier_in_the_string_is_unknown
/**
* Append a UTF-8 string to the hash buffer
* @param str String to append
*/
appendStr(i) {
const a = this._buffer8, t = this._buffer32;
let e = this._bufferLength, s, r;
for (r = 0; r < i.length; r += 1) {
if (s = i.charCodeAt(r), s < 128)
a[e++] = s;
else if (s < 2048)
a[e++] = (s >>> 6) + 192, a[e++] = s & 63 | 128;
else if (s < 55296 || s > 56319)
a[e++] = (s >>> 12) + 224, a[e++] = s >>> 6 & 63 | 128, a[e++] = s & 63 | 128;
else {
if (s = (s - 55296) * 1024 + (i.charCodeAt(++r) - 56320) + 65536, s > 1114111)
throw new Error(
"Unicode standard supports code points up to U+10FFFF"
);
a[e++] = (s >>> 18) + 240, a[e++] = s >>> 12 & 63 | 128, a[e++] = s >>> 6 & 63 | 128, a[e++] = s & 63 | 128;
}
e >= 64 && (this._dataLength += 64, h._md5cycle(this._state, t), e -= 64, t[0] = t[16]);
}
return this._bufferLength = e, this;
}
/**
* Append an ASCII string to the hash buffer
* @param str String to append
*/
appendAsciiStr(i) {
const a = this._buffer8, t = this._buffer32;
let e = this._bufferLength, s, r = 0;
for (; ; ) {
for (s = Math.min(i.length - r, 64 - e); s--; )
a[e++] = i.charCodeAt(r++);
if (e < 64)
break;
this._dataLength += 64, h._md5cycle(this._state, t), e = 0;
}
return this._bufferLength = e, this;
}
/**
* Append a byte array to the hash buffer
* @param input array to append
*/
appendByteArray(i) {
const a = this._buffer8, t = this._buffer32;
let e = this._bufferLength, s, r = 0;
for (; ; ) {
for (s = Math.min(i.length - r, 64 - e); s--; )
a[e++] = i[r++];
if (e < 64)
break;
this._dataLength += 64, h._md5cycle(this._state, t), e = 0;
}
return this._bufferLength = e, this;
}
/**
* Get the state of the hash buffer
*/
getState() {
const i = this._state;
return {
buffer: String.fromCharCode.apply(null, Array.from(this._buffer8)),
buflen: this._bufferLength,
length: this._dataLength,
state: [i[0], i[1], i[2], i[3]]
};
}
/**
* Override the current state of the hash buffer
* @param state New hash buffer state
*/
setState(i) {
const a = i.buffer, t = i.state, e = this._state;
let s;
for (this._dataLength = i.length, this._bufferLength = i.buflen, e[0] = t[0], e[1] = t[1], e[2] = t[2], e[3] = t[3], s = 0; s < a.length; s += 1)
this._buffer8[s] = a.charCodeAt(s);
}
/**
* Hash the current state of the hash buffer and return the result
* @param raw Whether to return the value as an `Int32Array`
*/
end(i = !1) {
const a = this._bufferLength, t = this._buffer8, e = this._buffer32, s = (a >> 2) + 1;
this._dataLength += a;
const r = this._dataLength * 8;
if (t[a] = 128, t[a + 1] = t[a + 2] = t[a + 3] = 0, e.set(h.buffer32Identity.subarray(s), s), a > 55 && (h._md5cycle(this._state, e), e.set(h.buffer32Identity)), r <= 4294967295)
e[14] = r;
else {
const n = r.toString(16).match(/(.*?)(.{0,8})$/);
if (n === null) return i ? c : "";
const o = parseInt(n[2], 16), _ = parseInt(n[1], 16) || 0;
e[14] = o, e[15] = _;
}
return h._md5cycle(this._state, e), i ? this._state : h._hex(this._state);
}
}
if (h.hashStr("hello") !== "5d41402abc4b2a76b9719d911017c592")
throw new Error("Md5 self test failed.");
class l {
constructor(i, a = !0, t = 1048576) {
this._callback = i, this._async = a, this._partSize = t, this._configureReader();
}
_reader;
_md5;
_part;
// private _length!: number;
_blob;
/**
* Hash a blob of data in the worker
* @param blob Data to hash
*/
hash(i) {
const a = this;
a._blob = i, a._part = 0, a._md5 = new h(), a._processPart();
}
_fail() {
this._callback({
success: !1,
result: "data read failed"
});
}
_hashData(i) {
let a = this;
a._md5.appendByteArray(new Uint8Array(i.target.result)), a._part * a._partSize >= a._blob.size ? a._callback({
success: !0,
result: a._md5.end()
}) : a._processPart();
}
_processPart() {
const i = this;
let a = 0, t;
i._part += 1, i._blob.size > i._partSize ? (a = i._part * i._partSize, a > i._blob.size && (a = i._blob.size), t = i._blob.slice(
(i._part - 1) * i._partSize,
a
)) : t = i._blob, i._async ? i._reader.readAsArrayBuffer(t) : setTimeout(() => {
try {
i._hashData({
target: {
result: i._reader.readAsArrayBuffer(
t
)
}
});
} catch {
i._fail();
}
}, 0);
}
_configureReader() {
const i = this;
i._async ? (i._reader = new FileReader(), i._reader.onload = i._hashData.bind(i), i._reader.onerror = i._fail.bind(i), i._reader.onabort = i._fail.bind(i)) : i._reader = new FileReaderSync();
}
}
class u {
_queue = [];
_hashWorker;
_processing;
_ready = !0;
constructor(i, a) {
const t = this;
Worker ? (t._hashWorker = new Worker(i, a), t._hashWorker.onmessage = t._recievedMessage.bind(t), t._hashWorker.onerror = (e) => {
t._ready = !1, console.error("Hash worker failure", e);
}) : (t._ready = !1, console.error("Web Workers are not supported in this browser"));
}
/**
* Hash a blob of data in the worker
* @param blob Data to hash
* @returns Promise of the Hashed result
*/
hash(i) {
const a = this;
let t;
return t = new Promise((e, s) => {
a._queue.push({
blob: i,
resolve: e,
reject: s
}), a._processNext();
}), t;
}
/** Terminate any existing hash requests */
terminate() {
this._ready = !1, this._hashWorker.terminate();
}
// Processes the next item in the queue
_processNext() {
this._ready && !this._processing && this._queue.length > 0 && (this._processing = this._queue.pop(), this._hashWorker.postMessage(this._processing.blob));
}
// Hash result is returned from the worker
_recievedMessage(i) {
const a = i.data;
a.success ? this._processing?.resolve(a.result) : this._processing?.reject(a.result), this._processing = void 0, this._processNext();
}
}
export {
h as Md5,
l as Md5FileHasher,
u as ParallelHasher
};
//# sourceMappingURL=index.es.js.map