// @ts-nocheck export class Sha1Stream { readonly Sha1BlockSize = 64; readonly Sha1DigestSize = 20; private readonly _padding = Buffer.concat([Buffer.from([0x80]), Buffer.alloc(63)]); private readonly _state = new Uint32Array(5); private readonly _count = new Uint32Array(2); private readonly _buffer = Buffer.allocUnsafe(this.Sha1BlockSize); private readonly _w = new Uint32Array(80); constructor () { this.reset(); } private reset (): void { this._state[0] = 0x67452301; this._state[1] = 0xEFCDAB89; this._state[2] = 0x98BADCFE; this._state[3] = 0x10325476; this._state[4] = 0xC3D2E1F0; this._count[0] = 0; this._count[1] = 0; this._buffer.fill(0); } private rotateLeft (v: number, o: number): number { return ((v << o) | (v >>> (32 - o))) >>> 0; } private transform (chunk: Buffer, offset: number): void { const w = this._w; const view = new DataView(chunk.buffer, chunk.byteOffset + offset, 64); for (let i = 0; i < 16; i++) { w[i] = view.getUint32(i * 4, false); } for (let i = 16; i < 80; i++) { w[i] = this.rotateLeft(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1) >>> 0; } let a = this._state[0]; let b = this._state[1]; let c = this._state[2]; let d = this._state[3]; let e = this._state[4]; for (let i = 0; i < 80; i++) { let temp; if (i < 20) { temp = ((b & c) | (~b & d)) + 0x5A827999; } else if (i < 40) { temp = (b ^ c ^ d) + 0x6ED9EBA1; } else if (i < 60) { temp = ((b & c) | (b & d) | (c & d)) + 0x8F1BBCDC; } else { temp = (b ^ c ^ d) + 0xCA62C1D6; } temp += ((this.rotateLeft(a, 5) + e + w[i]) >>> 0); e = d; d = c; c = this.rotateLeft(b, 30) >>> 0; b = a; a = temp; } this._state[0] = (this._state[0] + a) >>> 0; this._state[1] = (this._state[1] + b) >>> 0; this._state[2] = (this._state[2] + c) >>> 0; this._state[3] = (this._state[3] + d) >>> 0; this._state[4] = (this._state[4] + e) >>> 0; } public update (data: Buffer, len?: number): void { let index = ((this._count[0] >>> 3) & 0x3F) >>> 0; const dataLen = len ?? data.length; this._count[0] = (this._count[0] + (dataLen << 3)) >>> 0; if (this._count[0] < (dataLen << 3)) this._count[1] = (this._count[1] + 1) >>> 0; this._count[1] = (this._count[1] + (dataLen >>> 29)) >>> 0; const partLen = (this.Sha1BlockSize - index) >>> 0; let i = 0; if (dataLen >= partLen) { data.copy(this._buffer, index, 0, partLen); this.transform(this._buffer, 0); for (i = partLen; (i + this.Sha1BlockSize) <= dataLen; i = (i + this.Sha1BlockSize) >>> 0) { this.transform(data, i); } index = 0; } data.copy(this._buffer, index, i, dataLen); } public hash (bigEndian: boolean = true): Buffer { const digest = Buffer.allocUnsafe(this.Sha1DigestSize); if (bigEndian) { for (let i = 0; i < 5; i++) digest.writeUInt32BE(this._state[i], i * 4); } else { for (let i = 0; i < 5; i++) digest.writeUInt32LE(this._state[i], i * 4); } return digest; } public final (): Buffer { const digest = Buffer.allocUnsafe(this.Sha1DigestSize); const bits = Buffer.allocUnsafe(8); bits.writeUInt32BE(this._count[1], 0); bits.writeUInt32BE(this._count[0], 4); const index = ((this._count[0] >>> 3) & 0x3F) >>> 0; const padLen = ((index < 56) ? (56 - index) : (120 - index)) >>> 0; this.update(this._padding, padLen); this.update(bits); for (let i = 0; i < 5; i++) { digest.writeUInt32BE(this._state[i], i * 4); } return digest; } }