1
2
3
4
5
6 using System;
7 using System.Collections;
8 using System.IO;
9
10 namespace System.Security
11 {
12 public inline nothrow uint LeftRotate(uint x, uint n)
13 {
14 return (x << n) ^ (x >> (32u - n));
15 }
16
17 public class Sha1
18 {
19 public nothrow Sha1()
20 {
21 Reset();
22 }
23 public nothrow void Reset()
24 {
25 digest[0] = 0x67452301u;
26 digest[1] = 0xEFCDAB89u;
27 digest[2] = 0x98BADCFEu;
28 digest[3] = 0x10325476u;
29 digest[4] = 0xC3D2E1F0u;
30 byteIndex = 0u;
31 bitCount = 0u;
32 }
33 public nothrow void Process(byte x)
34 {
35 ProcessByte(x);
36 bitCount = bitCount + 8u;
37 }
38 public nothrow void Process(byte* begin, byte* end)
39 {
40 while (begin != end)
41 {
42 Process(*begin);
43 ++begin;
44 }
45 }
46 public nothrow void Process(byte* buf, long count)
47 {
48 Process(buf, buf + count);
49 }
50 public nothrow string GetDigest()
51 {
52 ProcessByte(0x80u);
53 if (byteIndex > 56u)
54 {
55 while (byteIndex != 0u)
56 {
57 ProcessByte(0u);
58 }
59 while (byteIndex < 56u)
60 {
61 ProcessByte(0u);
62 }
63 }
64 else
65 {
66 while (byteIndex < 56u)
67 {
68 ProcessByte(0u);
69 }
70 }
71 ProcessByte(cast<byte>((bitCount >> 56u) & 0xFFu));
72 ProcessByte(cast<byte>((bitCount >> 48u) & 0xFFu));
73 ProcessByte(cast<byte>((bitCount >> 40u) & 0xFFu));
74 ProcessByte(cast<byte>((bitCount >> 32u) & 0xFFu));
75 ProcessByte(cast<byte>((bitCount >> 24u) & 0xFFu));
76 ProcessByte(cast<byte>((bitCount >> 16u) & 0xFFu));
77 ProcessByte(cast<byte>((bitCount >> 8u) & 0xFFu));
78 ProcessByte(cast<byte>(bitCount & 0xFFu));
79 string s = ToHexString(digest[0]);
80 s.Append(ToHexString(digest[1]));
81 s.Append(ToHexString(digest[2]));
82 s.Append(ToHexString(digest[3]));
83 s.Append(ToHexString(digest[4]));
84 return s;
85 }
86 private nothrow void ProcessByte(byte x)
87 {
88 block[byteIndex++] = x;
89 if (byteIndex == 64u)
90 {
91 byteIndex = 0u;
92 ProcessBlock();
93 }
94 }
95 private nothrow void ProcessBlock()
96 {
97 uint[80] w;
98 for (int i = 0; i < 16; ++i;)
99 {
100 w[i] = cast<uint>(block[4 * i]) << 24u;
101 w[i] = w[i] | cast<uint>(block[4 * i + 1]) << 16u;
102 w[i] = w[i] | cast<uint>(block[4 * i + 2]) << 8u;
103 w[i] = w[i] | cast<uint>(block[4 * i + 3]);
104 }
105 for (int i = 16; i < 80; ++i;)
106 {
107 w[i] = LeftRotate(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1u);
108 }
109 uint a = digest[0];
110 uint b = digest[1];
111 uint c = digest[2];
112 uint d = digest[3];
113 uint e = digest[4];
114 for (int i = 0; i < 80; ++i;)
115 {
116 uint f;
117 uint k;
118 if (i < 20)
119 {
120 f = (b & c) | (~b & d);
121 k = 0x5A827999u;
122 }
123 else if (i < 40)
124 {
125 f = b ^ c ^ d;
126 k = 0x6ED9EBA1u;
127 }
128 else if (i < 60)
129 {
130 f = (b & c) | (b & d) | (c & d);
131 k = 0x8F1BBCDCu;
132 }
133 else
134 {
135 f = b ^ c ^ d;
136 k = 0xCA62C1D6u;
137 }
138 uint temp = LeftRotate(a, 5u) + f + e + k + w[i];
139 e = d;
140 d = c;
141 c = LeftRotate(b, 30u);
142 b = a;
143 a = temp;
144 }
145 digest[0] = digest[0] + a;
146 digest[1] = digest[1] + b;
147 digest[2] = digest[2] + c;
148 digest[3] = digest[3] + d;
149 digest[4] = digest[4] + e;
150 }
151 private uint[5] digest;
152 private byte[64] block;
153 private byte byteIndex;
154 private ulong bitCount;
155 }
156
157 public nothrow string GetSha1MessageDigest(const string& message)
158 {
159 byte* data = cast<byte*>(cast<void*>(message.Chars()));
160 long count = message.Length();
161 return GetSha1MessageDigest(data, count);
162 }
163
164 public nothrow string GetSha1MessageDigest(byte* data, long count)
165 {
166 Sha1 sha1;
167 sha1.Process(data, count);
168 return sha1.GetDigest();
169 }
170
171 public string GetSha1FileDigest(const string& filePath)
172 {
173 Sha1 sha1;
174 long n = File.Size(filePath);
175 if (n > 0)
176 {
177 BinaryReader reader = File.OpenBinary(filePath);
178 for (long i = 0; i < n; ++i;)
179 {
180 sha1.Process(reader.ReadByte());
181 }
182 }
183 return sha1.GetDigest();
184 }
185
186 public string GetCumulativeSha1FileDigest(const List<string>& filePaths)
187 {
188 Sha1 sha1;
189 for (const string& filePath : filePaths)
190 {
191 long n = File.Size(filePath);
192 if (n > 0)
193 {
194 BinaryReader reader = File.OpenBinary(filePath);
195 for (long i = 0; i < n; ++i;)
196 {
197 sha1.Process(reader.ReadByte());
198 }
199 }
200 }
201 return sha1.GetDigest();
202 }
203 }