This repository has been archived by the owner on Sep 16, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathsha1.ts
110 lines (99 loc) · 2.71 KB
/
sha1.ts
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
import { HashAlgorithm } from "./hash.ts";
/*
* Calculate the SHA-1 of an array of big-endian words, and a bit length
*/
function binb_sha1(x: number[], len: number): number[] {
/* append padding */
x[len >> 5] |= 0x80 << (24 - (len % 32));
x[(((len + 64) >> 9) << 4) + 15] = len;
const w: number[] = [];
let a = 1732584193;
let b = -271733879;
let c = -1732584194;
let d = 271733878;
let e = -1009589776;
for (let i = 0; i < x.length; i += 16) {
const olda = a;
const oldb = b;
const oldc = c;
const oldd = d;
const olde = e;
for (let j = 0; j < 80; j++) {
if (j < 16) w[j] = x[i + j];
else w[j] = bit_rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
var t = safe_add(
safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)),
safe_add(safe_add(e, w[j]), sha1_kt(j)),
);
e = d;
d = c;
c = bit_rol(b, 30);
b = a;
a = t;
}
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
e = safe_add(e, olde);
}
return [a, b, c, d, e];
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
function sha1_ft(t: number, b: number, c: number, d: number): number {
if (t < 20) return (b & c) | (~b & d);
if (t < 40) return b ^ c ^ d;
if (t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
/*
* Determine the appropriate additive constant for the current iteration
*/
function sha1_kt(t: number): number {
return t < 20
? 1518500249
: t < 40
? 1859775393
: t < 60
? -1894007588
: -899497514;
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x: number, y: number): number {
const lsw = (x & 0xffff) + (y & 0xffff);
const msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xffff);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function bit_rol(num: number, cnt: number): number {
return (num << cnt) | (num >>> (32 - cnt));
}
export class Sha1Hash implements HashAlgorithm {
digest(bytes: Uint8Array): Uint8Array {
let data: number[] = [];
for (var i = 0; i < bytes.length * 8; i += 8) {
data[i >> 5] |= (bytes[i / 8] & 0xff) << (24 - (i % 32));
}
data = binb_sha1(data, bytes.length * 8);
return this.toStrBytes(data);
}
/*
* Convert an array of big-endian words to a string
*/
private toStrBytes(input: number[]): Uint8Array {
let pos = 0;
const data = new Uint8Array(input.length * 4);
for (let i = 0; i < input.length * 32; i += 8) {
data[pos++] = (input[i >> 5] >> (24 - (i % 32))) & 0xff;
}
return data;
}
}