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: 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. 45 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 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 78 static inline uint32 S(uint32 n, uint32 X) { 79 return (X << n) | (X >> (32-n)); 80 } 81 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 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 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 118 void SecureHashAlgorithm::Final() { 119 Pad(); 120 Process(); 121 122 for (int t = 0; t < 5; ++t) 123 swapends(&H[t]); 124 } 125 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 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 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 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 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