|  | // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "base/sha1.h" | 
|  |  | 
|  | #include <string.h> | 
|  |  | 
|  | #include "base/basictypes.h" | 
|  |  | 
|  | namespace base { | 
|  |  | 
|  | // Implementation of SHA-1. Only handles data in byte-sized blocks, | 
|  | // which simplifies the code a fair bit. | 
|  |  | 
|  | // Identifier names follow notation in FIPS PUB 180-3, where you'll | 
|  | // also find a description of the algorithm: | 
|  | // http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf | 
|  |  | 
|  | // Usage example: | 
|  | // | 
|  | // SecureHashAlgorithm sha; | 
|  | // while(there is data to hash) | 
|  | //   sha.Update(moredata, size of data); | 
|  | // sha.Final(); | 
|  | // memcpy(somewhere, sha.Digest(), 20); | 
|  | // | 
|  | // to reuse the instance of sha, call sha.Init(); | 
|  |  | 
|  | // TODO(jhawkins): Replace this implementation with a per-platform | 
|  | // implementation using each platform's crypto library.  See | 
|  | // http://crbug.com/47218 | 
|  |  | 
|  | class SecureHashAlgorithm { | 
|  | public: | 
|  | SecureHashAlgorithm() { Init(); } | 
|  |  | 
|  | static const int kDigestSizeBytes; | 
|  |  | 
|  | void Init(); | 
|  | void Update(const void* data, size_t nbytes); | 
|  | void Final(); | 
|  |  | 
|  | // 20 bytes of message digest. | 
|  | const unsigned char* Digest() const { | 
|  | return reinterpret_cast<const unsigned char*>(H); | 
|  | } | 
|  |  | 
|  | private: | 
|  | void Pad(); | 
|  | void Process(); | 
|  |  | 
|  | uint32 A, B, C, D, E; | 
|  |  | 
|  | uint32 H[5]; | 
|  |  | 
|  | union { | 
|  | uint32 W[80]; | 
|  | uint8 M[64]; | 
|  | }; | 
|  |  | 
|  | uint32 cursor; | 
|  | uint32 l; | 
|  | }; | 
|  |  | 
|  | static inline uint32 f(uint32 t, uint32 B, uint32 C, uint32 D) { | 
|  | if (t < 20) { | 
|  | return (B & C) | ((~B) & D); | 
|  | } else if (t < 40) { | 
|  | return B ^ C ^ D; | 
|  | } else if (t < 60) { | 
|  | return (B & C) | (B & D) | (C & D); | 
|  | } else { | 
|  | return B ^ C ^ D; | 
|  | } | 
|  | } | 
|  |  | 
|  | static inline uint32 S(uint32 n, uint32 X) { | 
|  | return (X << n) | (X >> (32-n)); | 
|  | } | 
|  |  | 
|  | static inline uint32 K(uint32 t) { | 
|  | if (t < 20) { | 
|  | return 0x5a827999; | 
|  | } else if (t < 40) { | 
|  | return 0x6ed9eba1; | 
|  | } else if (t < 60) { | 
|  | return 0x8f1bbcdc; | 
|  | } else { | 
|  | return 0xca62c1d6; | 
|  | } | 
|  | } | 
|  |  | 
|  | static inline void swapends(uint32* t) { | 
|  | #if defined(ARCH_CPU_LITTLE_ENDIAN) | 
|  | *t = ((*t & 0xff000000) >> 24) | | 
|  | ((*t & 0xff0000) >> 8) | | 
|  | ((*t & 0xff00) << 8) | | 
|  | ((*t & 0xff) << 24); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | const int SecureHashAlgorithm::kDigestSizeBytes = 20; | 
|  |  | 
|  | void SecureHashAlgorithm::Init() { | 
|  | A = 0; | 
|  | B = 0; | 
|  | C = 0; | 
|  | D = 0; | 
|  | E = 0; | 
|  | cursor = 0; | 
|  | l = 0; | 
|  | H[0] = 0x67452301; | 
|  | H[1] = 0xefcdab89; | 
|  | H[2] = 0x98badcfe; | 
|  | H[3] = 0x10325476; | 
|  | H[4] = 0xc3d2e1f0; | 
|  | } | 
|  |  | 
|  | void SecureHashAlgorithm::Final() { | 
|  | Pad(); | 
|  | Process(); | 
|  |  | 
|  | for (int t = 0; t < 5; ++t) | 
|  | swapends(&H[t]); | 
|  | } | 
|  |  | 
|  | void SecureHashAlgorithm::Update(const void* data, size_t nbytes) { | 
|  | const uint8* d = reinterpret_cast<const uint8*>(data); | 
|  | while (nbytes--) { | 
|  | M[cursor++] = *d++; | 
|  | if (cursor >= 64) | 
|  | Process(); | 
|  | l += 8; | 
|  | } | 
|  | } | 
|  |  | 
|  | void SecureHashAlgorithm::Pad() { | 
|  | M[cursor++] = 0x80; | 
|  |  | 
|  | if (cursor > 64-8) { | 
|  | // pad out to next block | 
|  | while (cursor < 64) | 
|  | M[cursor++] = 0; | 
|  |  | 
|  | Process(); | 
|  | } | 
|  |  | 
|  | while (cursor < 64-4) | 
|  | M[cursor++] = 0; | 
|  |  | 
|  | M[64-4] = (l & 0xff000000) >> 24; | 
|  | M[64-3] = (l & 0xff0000) >> 16; | 
|  | M[64-2] = (l & 0xff00) >> 8; | 
|  | M[64-1] = (l & 0xff); | 
|  | } | 
|  |  | 
|  | void SecureHashAlgorithm::Process() { | 
|  | uint32 t; | 
|  |  | 
|  | // Each a...e corresponds to a section in the FIPS 180-3 algorithm. | 
|  |  | 
|  | // a. | 
|  | // | 
|  | // W and M are in a union, so no need to memcpy. | 
|  | // memcpy(W, M, sizeof(M)); | 
|  | for (t = 0; t < 16; ++t) | 
|  | swapends(&W[t]); | 
|  |  | 
|  | // b. | 
|  | for (t = 16; t < 80; ++t) | 
|  | W[t] = S(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]); | 
|  |  | 
|  | // c. | 
|  | A = H[0]; | 
|  | B = H[1]; | 
|  | C = H[2]; | 
|  | D = H[3]; | 
|  | E = H[4]; | 
|  |  | 
|  | // d. | 
|  | for (t = 0; t < 80; ++t) { | 
|  | uint32 TEMP = S(5, A) + f(t, B, C, D) + E + W[t] + K(t); | 
|  | E = D; | 
|  | D = C; | 
|  | C = S(30, B); | 
|  | B = A; | 
|  | A = TEMP; | 
|  | } | 
|  |  | 
|  | // e. | 
|  | H[0] += A; | 
|  | H[1] += B; | 
|  | H[2] += C; | 
|  | H[3] += D; | 
|  | H[4] += E; | 
|  |  | 
|  | cursor = 0; | 
|  | } | 
|  |  | 
|  | std::string SHA1HashString(const std::string& str) { | 
|  | char hash[SecureHashAlgorithm::kDigestSizeBytes]; | 
|  | SHA1HashBytes(reinterpret_cast<const unsigned char*>(str.c_str()), | 
|  | str.length(), reinterpret_cast<unsigned char*>(hash)); | 
|  | return std::string(hash, SecureHashAlgorithm::kDigestSizeBytes); | 
|  | } | 
|  |  | 
|  | void SHA1HashBytes(const unsigned char* data, size_t len, | 
|  | unsigned char* hash) { | 
|  | SecureHashAlgorithm sha; | 
|  | sha.Update(data, len); | 
|  | sha.Final(); | 
|  |  | 
|  | memcpy(hash, sha.Digest(), SecureHashAlgorithm::kDigestSizeBytes); | 
|  | } | 
|  |  | 
|  | }  // namespace base |