-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathsha1.js
139 lines (122 loc) · 4.01 KB
/
sha1.js
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
/**
* @file This is a SHA-1 hash generator by JavaScript.
* @author Hsun
* @description For your convenience, the code comments have been translated by Google.
***/
// 消息填充位,补足长度。
// Message padding bits, complement the length.
function fillString(str) {
var blockAmount = ((str.length + 8) >> 6) + 1,
blocks = [],
i;
for (i = 0; i < blockAmount * 16; i++) {
blocks[i] = 0;
}
for (i = 0; i < str.length; i++) {
blocks[i >> 2] |= str.charCodeAt(i) << (24 - (i & 3) * 8);
}
blocks[i >> 2] |= 0x80 << (24 - (i & 3) * 8);
blocks[blockAmount * 16 - 1] = str.length * 8;
return blocks;
}
// 将输入的二进制数组转化为十六进制的字符串。
// Convert the input binary array to a hexadecimal string.
function binToHex(binArray) {
var hexString = "0123456789abcdef",
str = "",
i;
for (i = 0; i < binArray.length * 4; i++) {
str += hexString.charAt((binArray[i >> 2] >> ((3 - i % 4) * 8 + 4)) & 0xF) +
hexString.charAt((binArray[i >> 2] >> ((3 - i % 4) * 8)) & 0xF);
}
return str;
}
// 核心函数,输出为长度为5的number数组,对应160位的消息摘要。
// The core function, the output is a number array with a length of 5,
// corresponding to a 160-bit message digest.
function core(blockArray) {
var w = [],
a = 0x67452301,
b = 0xEFCDAB89,
c = 0x98BADCFE,
d = 0x10325476,
e = 0xC3D2E1F0,
olda,
oldb,
oldc,
oldd,
olde,
t,
i,
j;
for (i = 0; i < blockArray.length; i += 16) { //每次处理512位 16*32
olda = a;
oldb = b;
oldc = c;
oldd = d;
olde = e;
for (j = 0; j < 80; j++) { //对每个512位进行80步操作
if (j < 16) {
w[j] = blockArray[i + j];
} else {
w[j] = cyclicShift(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
}
t = modPlus(modPlus(cyclicShift(a, 5), ft(j, b, c, d)), modPlus(modPlus(e, w[j]), kt(j)));
e = d;
d = c;
c = cyclicShift(b, 30);
b = a;
a = t;
}
a = modPlus(a, olda);
b = modPlus(b, oldb);
c = modPlus(c, oldc);
d = modPlus(d, oldd);
e = modPlus(e, olde);
}
return [a, b, c, d, e];
}
// 根据t值返回相应得压缩函数中用到的f函数。
// According to the t value, return the corresponding f function used in
// the compression function.
function ft(t, b, c, d) {
if (t < 20) {
return (b & c) | ((~b) & d);
} else if (t < 40) {
return b ^ c ^ d;
} else if (t < 60) {
return (b & c) | (b & d) | (c & d);
} else {
return b ^ c ^ d;
}
}
// 根据t值返回相应得压缩函数中用到的K值。
// According to the t value, return the corresponding K value used in
// the compression function.
function kt(t) {
return (t < 20) ? 0x5A827999 :
(t < 40) ? 0x6ED9EBA1 :
(t < 60) ? 0x8F1BBCDC : 0xCA62C1D6;
}
// 模2的32次方加法,因为JavaScript的number是双精度浮点数表示,所以将32位数拆成高16位和低16位分别进行相加
// Modulo 2 to the 32nd power addition, because JavaScript's number is a
// double-precision floating-point number, so the 32-bit number is split
// into the upper 16 bits and the lower 16 bits are added separately.
function modPlus(x, y) {
var low = (x & 0xFFFF) + (y & 0xFFFF),
high = (x >> 16) + (y >> 16) + (low >> 16);
return (high << 16) | (low & 0xFFFF);
}
// 对输入的32位的num二进制数进行循环左移 ,因为JavaScript的number是双精度浮点数表示,所以移位需需要注意
// Rotate left of the input 32-bit num binary number, because JavaScript's
// number is a double-precision floating-point number, so you need to pay
// attention to the shift.
function cyclicShift(num, k) {
return (num << k) | (num >>> (32 - k));
}
// 主函数根据输入的消息字符串计算消息摘要,返回十六进制表示的消息摘要
// The main function calculates the message digest based on the input message
// string and returns the message digest in hexadecimal.
export default function sha1(s) {
return binToHex(core(fillString(s)));
}