OLD | NEW |
(Empty) | |
| 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 |
OLD | NEW |