OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "base/sha1.h" | |
6 | |
7 #include <stddef.h> | |
8 #include <stdint.h> | |
9 #include <string.h> | |
10 | |
11 | |
12 namespace base { | |
13 | |
14 // Implementation of SHA-1. Only handles data in byte-sized blocks, | |
15 // which simplifies the code a fair bit. | |
16 | |
17 // Identifier names follow notation in FIPS PUB 180-3, where you'll | |
18 // also find a description of the algorithm: | |
19 // http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf | |
20 | |
21 // Usage example: | |
22 // | |
23 // SecureHashAlgorithm sha; | |
24 // while(there is data to hash) | |
25 // sha.Update(moredata, size of data); | |
26 // sha.Final(); | |
27 // memcpy(somewhere, sha.Digest(), 20); | |
28 // | |
29 // to reuse the instance of sha, call sha.Init(); | |
30 | |
31 // TODO(jhawkins): Replace this implementation with a per-platform | |
32 // implementation using each platform's crypto library. See | |
33 // http://crbug.com/47218 | |
34 | |
35 class SecureHashAlgorithm { | |
36 public: | |
37 SecureHashAlgorithm() { Init(); } | |
38 | |
39 static const int kDigestSizeBytes; | |
40 | |
41 void Init(); | |
42 void Update(const void* data, size_t nbytes); | |
43 void Final(); | |
44 | |
45 // 20 bytes of message digest. | |
46 const unsigned char* Digest() const { | |
47 return reinterpret_cast<const unsigned char*>(H); | |
48 } | |
49 | |
50 private: | |
51 void Pad(); | |
52 void Process(); | |
53 | |
54 uint32_t A, B, C, D, E; | |
55 | |
56 uint32_t H[5]; | |
57 | |
58 union { | |
59 uint32_t W[80]; | |
60 uint8_t M[64]; | |
61 }; | |
62 | |
63 uint32_t cursor; | |
64 uint64_t l; | |
65 }; | |
66 | |
67 static inline uint32_t f(uint32_t t, uint32_t B, uint32_t C, uint32_t D) { | |
68 if (t < 20) { | |
69 return (B & C) | ((~B) & D); | |
70 } else if (t < 40) { | |
71 return B ^ C ^ D; | |
72 } else if (t < 60) { | |
73 return (B & C) | (B & D) | (C & D); | |
74 } else { | |
75 return B ^ C ^ D; | |
76 } | |
77 } | |
78 | |
79 static inline uint32_t S(uint32_t n, uint32_t X) { | |
80 return (X << n) | (X >> (32-n)); | |
81 } | |
82 | |
83 static inline uint32_t K(uint32_t t) { | |
84 if (t < 20) { | |
85 return 0x5a827999; | |
86 } else if (t < 40) { | |
87 return 0x6ed9eba1; | |
88 } else if (t < 60) { | |
89 return 0x8f1bbcdc; | |
90 } else { | |
91 return 0xca62c1d6; | |
92 } | |
93 } | |
94 | |
95 static inline void swapends(uint32_t* t) { | |
96 *t = (*t >> 24) | ((*t >> 8) & 0xff00) | ((*t & 0xff00) << 8) | (*t << 24); | |
97 } | |
98 | |
99 const int SecureHashAlgorithm::kDigestSizeBytes = 20; | |
100 | |
101 void SecureHashAlgorithm::Init() { | |
102 A = 0; | |
103 B = 0; | |
104 C = 0; | |
105 D = 0; | |
106 E = 0; | |
107 cursor = 0; | |
108 l = 0; | |
109 H[0] = 0x67452301; | |
110 H[1] = 0xefcdab89; | |
111 H[2] = 0x98badcfe; | |
112 H[3] = 0x10325476; | |
113 H[4] = 0xc3d2e1f0; | |
114 } | |
115 | |
116 void SecureHashAlgorithm::Final() { | |
117 Pad(); | |
118 Process(); | |
119 | |
120 for (int t = 0; t < 5; ++t) | |
121 swapends(&H[t]); | |
122 } | |
123 | |
124 void SecureHashAlgorithm::Update(const void* data, size_t nbytes) { | |
125 const uint8_t* d = reinterpret_cast<const uint8_t*>(data); | |
126 while (nbytes--) { | |
127 M[cursor++] = *d++; | |
128 if (cursor >= 64) | |
129 Process(); | |
130 l += 8; | |
131 } | |
132 } | |
133 | |
134 void SecureHashAlgorithm::Pad() { | |
135 M[cursor++] = 0x80; | |
136 | |
137 if (cursor > 64-8) { | |
138 // pad out to next block | |
139 while (cursor < 64) | |
140 M[cursor++] = 0; | |
141 | |
142 Process(); | |
143 } | |
144 | |
145 while (cursor < 64-8) | |
146 M[cursor++] = 0; | |
147 | |
148 M[cursor++] = (l >> 56) & 0xff; | |
149 M[cursor++] = (l >> 48) & 0xff; | |
150 M[cursor++] = (l >> 40) & 0xff; | |
151 M[cursor++] = (l >> 32) & 0xff; | |
152 M[cursor++] = (l >> 24) & 0xff; | |
153 M[cursor++] = (l >> 16) & 0xff; | |
154 M[cursor++] = (l >> 8) & 0xff; | |
155 M[cursor++] = l & 0xff; | |
156 } | |
157 | |
158 void SecureHashAlgorithm::Process() { | |
159 uint32_t t; | |
160 | |
161 // Each a...e corresponds to a section in the FIPS 180-3 algorithm. | |
162 | |
163 // a. | |
164 // | |
165 // W and M are in a union, so no need to memcpy. | |
166 // memcpy(W, M, sizeof(M)); | |
167 for (t = 0; t < 16; ++t) | |
168 swapends(&W[t]); | |
169 | |
170 // b. | |
171 for (t = 16; t < 80; ++t) | |
172 W[t] = S(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]); | |
173 | |
174 // c. | |
175 A = H[0]; | |
176 B = H[1]; | |
177 C = H[2]; | |
178 D = H[3]; | |
179 E = H[4]; | |
180 | |
181 // d. | |
182 for (t = 0; t < 80; ++t) { | |
183 uint32_t TEMP = S(5, A) + f(t, B, C, D) + E + W[t] + K(t); | |
184 E = D; | |
185 D = C; | |
186 C = S(30, B); | |
187 B = A; | |
188 A = TEMP; | |
189 } | |
190 | |
191 // e. | |
192 H[0] += A; | |
193 H[1] += B; | |
194 H[2] += C; | |
195 H[3] += D; | |
196 H[4] += E; | |
197 | |
198 cursor = 0; | |
199 } | |
200 | |
201 std::string SHA1HashString(const std::string& str) { | |
202 char hash[SecureHashAlgorithm::kDigestSizeBytes]; | |
203 SHA1HashBytes(reinterpret_cast<const unsigned char*>(str.c_str()), | |
204 str.length(), reinterpret_cast<unsigned char*>(hash)); | |
205 return std::string(hash, SecureHashAlgorithm::kDigestSizeBytes); | |
206 } | |
207 | |
208 void SHA1HashBytes(const unsigned char* data, size_t len, | |
209 unsigned char* hash) { | |
210 SecureHashAlgorithm sha; | |
211 sha.Update(data, len); | |
212 sha.Final(); | |
213 | |
214 memcpy(hash, sha.Digest(), SecureHashAlgorithm::kDigestSizeBytes); | |
215 } | |
216 | |
217 } // namespace base | |
OLD | NEW |