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