• 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   uint64 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 >> 24) | ((*t >> 8) & 0xff00) | ((*t & 0xff00) << 8) | (*t << 24);
96 }
97 
98 const int SecureHashAlgorithm::kDigestSizeBytes = 20;
99 
Init()100 void SecureHashAlgorithm::Init() {
101   A = 0;
102   B = 0;
103   C = 0;
104   D = 0;
105   E = 0;
106   cursor = 0;
107   l = 0;
108   H[0] = 0x67452301;
109   H[1] = 0xefcdab89;
110   H[2] = 0x98badcfe;
111   H[3] = 0x10325476;
112   H[4] = 0xc3d2e1f0;
113 }
114 
Final()115 void SecureHashAlgorithm::Final() {
116   Pad();
117   Process();
118 
119   for (int t = 0; t < 5; ++t)
120     swapends(&H[t]);
121 }
122 
Update(const void * data,size_t nbytes)123 void SecureHashAlgorithm::Update(const void* data, size_t nbytes) {
124   const uint8* d = reinterpret_cast<const uint8*>(data);
125   while (nbytes--) {
126     M[cursor++] = *d++;
127     if (cursor >= 64)
128       Process();
129     l += 8;
130   }
131 }
132 
Pad()133 void SecureHashAlgorithm::Pad() {
134   M[cursor++] = 0x80;
135 
136   if (cursor > 64-8) {
137     // pad out to next block
138     while (cursor < 64)
139       M[cursor++] = 0;
140 
141     Process();
142   }
143 
144   while (cursor < 64-8)
145     M[cursor++] = 0;
146 
147   M[cursor++] = (l >> 56) & 0xff;
148   M[cursor++] = (l >> 48) & 0xff;
149   M[cursor++] = (l >> 40) & 0xff;
150   M[cursor++] = (l >> 32) & 0xff;
151   M[cursor++] = (l >> 24) & 0xff;
152   M[cursor++] = (l >> 16) & 0xff;
153   M[cursor++] = (l >> 8) & 0xff;
154   M[cursor++] = l & 0xff;
155 }
156 
Process()157 void SecureHashAlgorithm::Process() {
158   uint32 t;
159 
160   // Each a...e corresponds to a section in the FIPS 180-3 algorithm.
161 
162   // a.
163   //
164   // W and M are in a union, so no need to memcpy.
165   // memcpy(W, M, sizeof(M));
166   for (t = 0; t < 16; ++t)
167     swapends(&W[t]);
168 
169   // b.
170   for (t = 16; t < 80; ++t)
171     W[t] = S(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]);
172 
173   // c.
174   A = H[0];
175   B = H[1];
176   C = H[2];
177   D = H[3];
178   E = H[4];
179 
180   // d.
181   for (t = 0; t < 80; ++t) {
182     uint32 TEMP = S(5, A) + f(t, B, C, D) + E + W[t] + K(t);
183     E = D;
184     D = C;
185     C = S(30, B);
186     B = A;
187     A = TEMP;
188   }
189 
190   // e.
191   H[0] += A;
192   H[1] += B;
193   H[2] += C;
194   H[3] += D;
195   H[4] += E;
196 
197   cursor = 0;
198 }
199 
SHA1HashString(const std::string & str)200 std::string SHA1HashString(const std::string& str) {
201   char hash[SecureHashAlgorithm::kDigestSizeBytes];
202   SHA1HashBytes(reinterpret_cast<const unsigned char*>(str.c_str()),
203                 str.length(), reinterpret_cast<unsigned char*>(hash));
204   return std::string(hash, SecureHashAlgorithm::kDigestSizeBytes);
205 }
206 
SHA1HashBytes(const unsigned char * data,size_t len,unsigned char * hash)207 void SHA1HashBytes(const unsigned char* data, size_t len,
208                    unsigned char* hash) {
209   SecureHashAlgorithm sha;
210   sha.Update(data, len);
211   sha.Final();
212 
213   memcpy(hash, sha.Digest(), SecureHashAlgorithm::kDigestSizeBytes);
214 }
215 
216 }  // namespace base
217