1 // Copyright (c) 2009 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 "base/basictypes.h" 8 9 namespace base { 10 11 // Implementation of SHA-1. Only handles data in byte-sized blocks, 12 // which simplifies the code a fair bit. 13 14 // This file also contains an HMAC implementation using SHA-1 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. 32 33 class SecureHashAlgorithm { 34 public: 35 SecureHashAlgorithm() { Init(); } 36 37 static const int kDigestSizeBytes; 38 39 void Init(); 40 void Update(const void* data, size_t nbytes); 41 void Final(); 42 43 // 20 bytes of message digest. 44 const unsigned char* Digest() const { 45 return reinterpret_cast<const unsigned char*>(H); 46 } 47 48 private: 49 void Pad(); 50 void Process(); 51 52 uint32 A, B, C, D, E; 53 54 uint32 H[5]; 55 56 union { 57 uint32 W[80]; 58 uint8 M[64]; 59 }; 60 61 uint32 cursor; 62 uint32 l; 63 }; 64 65 static inline uint32 f(uint32 t, uint32 B, uint32 C, uint32 D) { 66 if (t < 20) { 67 return (B & C) | ((~B) & D); 68 } else if (t < 40) { 69 return B ^ C ^ D; 70 } else if (t < 60) { 71 return (B & C) | (B & D) | (C & D); 72 } else { 73 return B ^ C ^ D; 74 } 75 } 76 77 static inline uint32 S(uint32 n, uint32 X) { 78 return (X << n) | (X >> (32-n)); 79 } 80 81 static inline uint32 K(uint32 t) { 82 if (t < 20) { 83 return 0x5a827999; 84 } else if (t < 40) { 85 return 0x6ed9eba1; 86 } else if (t < 60) { 87 return 0x8f1bbcdc; 88 } else { 89 return 0xca62c1d6; 90 } 91 } 92 93 static inline void swapends(uint32& t) { 94 t = ((t & 0xff000000) >> 24) | 95 ((t & 0xff0000) >> 8) | 96 ((t & 0xff00) << 8) | 97 ((t & 0xff) << 24); 98 } 99 100 const int SecureHashAlgorithm::kDigestSizeBytes = 20; 101 102 void SecureHashAlgorithm::Init() { 103 cursor = 0; 104 l = 0; 105 H[0] = 0x67452301; 106 H[1] = 0xefcdab89; 107 H[2] = 0x98badcfe; 108 H[3] = 0x10325476; 109 H[4] = 0xc3d2e1f0; 110 } 111 112 void SecureHashAlgorithm::Final() { 113 Pad(); 114 Process(); 115 116 for (int t = 0; t < 5; ++t) 117 swapends(H[t]); 118 } 119 120 void SecureHashAlgorithm::Update(const void* data, size_t nbytes) { 121 const uint8* d = reinterpret_cast<const uint8*>(data); 122 while (nbytes--) { 123 M[cursor++] = *d++; 124 if (cursor >= 64) 125 Process(); 126 l += 8; 127 } 128 } 129 130 void SecureHashAlgorithm::Pad() { 131 M[cursor++] = 0x80; 132 133 if (cursor > 64-8) { 134 // pad out to next block 135 while (cursor < 64) 136 M[cursor++] = 0; 137 138 Process(); 139 } 140 141 while (cursor < 64-4) 142 M[cursor++] = 0; 143 144 M[64-4] = (l & 0xff000000) >> 24; 145 M[64-3] = (l & 0xff0000) >> 16; 146 M[64-2] = (l & 0xff00) >> 8; 147 M[64-1] = (l & 0xff); 148 } 149 150 void SecureHashAlgorithm::Process() { 151 uint32 t; 152 153 // Each a...e corresponds to a section in the FIPS 180-3 algorithm. 154 155 // a. 156 // 157 // W and M are in a union, so no need to memcpy. 158 // memcpy(W, M, sizeof(M)); 159 for (t = 0; t < 16; ++t) 160 swapends(W[t]); 161 162 // b. 163 for (t = 16; t < 80; ++t) 164 W[t] = S(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]); 165 166 // c. 167 A = H[0]; 168 B = H[1]; 169 C = H[2]; 170 D = H[3]; 171 E = H[4]; 172 173 // d. 174 for (t = 0; t < 80; ++t) { 175 uint32 TEMP = S(5, A) + f(t, B, C, D) + E + W[t] + K(t); 176 E = D; 177 D = C; 178 C = S(30, B); 179 B = A; 180 A = TEMP; 181 } 182 183 // e. 184 H[0] += A; 185 H[1] += B; 186 H[2] += C; 187 H[3] += D; 188 H[4] += E; 189 190 cursor = 0; 191 } 192 193 std::string SHA1HashString(const std::string& str) { 194 SecureHashAlgorithm sha; 195 sha.Update(str.c_str(), str.length()); 196 sha.Final(); 197 std::string out(reinterpret_cast<const char*>(sha.Digest()), 198 SecureHashAlgorithm::kDigestSizeBytes); 199 return out; 200 } 201 202 } // namespace base 203