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