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