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