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