Home | History | Annotate | Download | only in base
      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