Sirikata
|
00001 // boost/uuid/sha1.hpp header file ----------------------------------------------// 00002 00003 // Copyright 2007 Andy Tompkins. 00004 // Distributed under the Boost Software License, Version 1.0. (See 00005 // accompanying file LICENSE_1_0.txt or copy at 00006 // http://www.boost.org/LICENSE_1_0.txt) 00007 00008 // Revision History 00009 // 29 May 2007 - Initial Revision 00010 00011 // This is a byte oriented implementation 00012 // Note: this implementation does not handle message longer than 00013 // 2^32 bytes. 00014 00015 #ifndef BOOST_UUID_SHA1_H 00016 #define BOOST_UUID_SHA1_H 00017 00018 #include <boost/static_assert.hpp> 00019 00020 namespace boost_ { 00021 namespace detail { 00022 00023 BOOST_STATIC_ASSERT(sizeof(unsigned char)*8 == 8); 00024 BOOST_STATIC_ASSERT(sizeof(unsigned int)*8 == 32); 00025 00026 inline unsigned int left_rotate(unsigned int x, size_t n) 00027 { 00028 return (x<<n) ^ (x>> (32-n)); 00029 } 00030 00031 class sha1 00032 { 00033 public: 00034 typedef unsigned int(&digest_type)[5]; 00035 public: 00036 sha1(); 00037 00038 void reset(); 00039 00040 void process_byte(unsigned char byte); 00041 void process_block(void const* bytes_begin, void const* bytes_end); 00042 void process_bytes(void const* buffer, std::size_t byte_count); 00043 00044 void get_digest(digest_type digest); 00045 00046 private: 00047 void process_block(); 00048 00049 private: 00050 unsigned int h_[5]; 00051 00052 unsigned char block_[64]; 00053 00054 size_t block_byte_index_; 00055 size_t byte_count_; 00056 }; 00057 00058 inline sha1::sha1() 00059 { 00060 reset(); 00061 } 00062 00063 inline void sha1::reset() 00064 { 00065 h_[0] = 0x67452301; 00066 h_[1] = 0xEFCDAB89; 00067 h_[2] = 0x98BADCFE; 00068 h_[3] = 0x10325476; 00069 h_[4] = 0xC3D2E1F0; 00070 00071 block_byte_index_ = 0; 00072 byte_count_ = 0; 00073 } 00074 00075 inline void sha1::process_byte(unsigned char byte) 00076 { 00077 block_[block_byte_index_++] = byte; 00078 ++byte_count_; 00079 if (block_byte_index_ == 64) { 00080 block_byte_index_ = 0; 00081 process_block(); 00082 } 00083 } 00084 00085 inline void sha1::process_block(void const* bytes_begin, void const* bytes_end) 00086 { 00087 unsigned char const* begin = static_cast<unsigned char const*>(bytes_begin); 00088 unsigned char const* end = static_cast<unsigned char const*>(bytes_end); 00089 for(; begin != end; ++begin) { 00090 process_byte(*begin); 00091 } 00092 } 00093 00094 inline void sha1::process_bytes(void const* buffer, std::size_t byte_count) 00095 { 00096 unsigned char const* b = static_cast<unsigned char const*>(buffer); 00097 process_block(b, b+byte_count); 00098 } 00099 00100 inline void sha1::process_block() 00101 { 00102 unsigned int w[80]; 00103 for (size_t i=0; i<16; ++i) { 00104 w[i] = (block_[i*4 + 0] << 24); 00105 w[i] |= (block_[i*4 + 1] << 16); 00106 w[i] |= (block_[i*4 + 2] << 8); 00107 w[i] |= (block_[i*4 + 3]); 00108 } 00109 for (size_t i=16; i<80; ++i) { 00110 w[i] = left_rotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1); 00111 } 00112 00113 unsigned int a = h_[0]; 00114 unsigned int b = h_[1]; 00115 unsigned int c = h_[2]; 00116 unsigned int d = h_[3]; 00117 unsigned int e = h_[4]; 00118 00119 for (size_t i=0; i<80; ++i) { 00120 unsigned int f; 00121 unsigned int k; 00122 00123 if (i<20) { 00124 f = (b & c) | (~b & d); 00125 k = 0x5A827999; 00126 } else if (i<40) { 00127 f = b ^ c ^ d; 00128 k = 0x6ED9EBA1; 00129 } else if (i<60) { 00130 f = (b & c) | (b & d) | (c & d); 00131 k = 0x8F1BBCDC; 00132 } else { 00133 f = b ^ c ^ d; 00134 k = 0xCA62C1D6; 00135 } 00136 00137 unsigned temp = left_rotate(a, 5) + f + e + k + w[i]; 00138 e = d; 00139 d = c; 00140 c = left_rotate(b, 30); 00141 b = a; 00142 a = temp; 00143 } 00144 00145 h_[0] += a; 00146 h_[1] += b; 00147 h_[2] += c; 00148 h_[3] += d; 00149 h_[4] += e; 00150 } 00151 00152 inline void sha1::get_digest(digest_type digest) 00153 { 00154 size_t bit_count = byte_count_*8; 00155 00156 // append the bit '1' to the message 00157 process_byte(0x80); 00158 00159 // append k bits '0', where k is the minimum number >= 0 00160 // such that the resulting message length is congruent to 56 (mod 64) 00161 // check if there is enough space for padding and bit_count 00162 if (block_byte_index_ > 56) { 00163 // finish this block 00164 while (block_byte_index_ != 0) { 00165 process_byte(0); 00166 } 00167 00168 // one more block 00169 while (block_byte_index_ < 56) { 00170 process_byte(0); 00171 } 00172 } else { 00173 while (block_byte_index_ < 56) { 00174 process_byte(0); 00175 } 00176 } 00177 00178 // append length of message (before pre-processing) 00179 // as a 64-bit big-endian integer 00180 process_byte(0); 00181 process_byte(0); 00182 process_byte(0); 00183 process_byte(0); 00184 process_byte( static_cast<unsigned char>((bit_count>>24) & 0xFF)); 00185 process_byte( static_cast<unsigned char>((bit_count>>16) & 0xFF)); 00186 process_byte( static_cast<unsigned char>((bit_count>>8 ) & 0xFF)); 00187 process_byte( static_cast<unsigned char>((bit_count) & 0xFF)); 00188 00189 // get final digest 00190 digest[0] = h_[0]; 00191 digest[1] = h_[1]; 00192 digest[2] = h_[2]; 00193 digest[3] = h_[3]; 00194 digest[4] = h_[4]; 00195 } 00196 00197 00198 } // namespace detail 00199 } // namespace boost 00200 00201 #endif