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 uint64 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 >> 24) | ((*t >> 8) & 0xff00) | ((*t & 0xff00) << 8) | (*t << 24); 96 } 97 98 const int SecureHashAlgorithm::kDigestSizeBytes = 20; 99 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 115 void SecureHashAlgorithm::Final() { 116 Pad(); 117 Process(); 118 119 for (int t = 0; t < 5; ++t) 120 swapends(&H[t]); 121 } 122 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 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 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 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 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