You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
		
		
		
		
		
			
		
			
				
					
					
						
							208 lines
						
					
					
						
							4.9 KiB
						
					
					
				
			
		
		
	
	
							208 lines
						
					
					
						
							4.9 KiB
						
					
					
				| // boost/uuid/sha1.hpp header file  ----------------------------------------------// | |
|  | |
| // Copyright 2007 Andy Tompkins. | |
| // Distributed under the Boost Software License, Version 1.0. (See | |
| // accompanying file LICENSE_1_0.txt or copy at | |
| // http://www.boost.org/LICENSE_1_0.txt) | |
|  | |
| // Revision History | |
| //  29 May 2007 - Initial Revision | |
| //  25 Feb 2008 - moved to namespace boost::uuids::detail | |
|  | |
| // This is a byte oriented implementation | |
| // Note: this implementation does not handle message longer than | |
| //       2^32 bytes. | |
|  | |
| #ifndef BOOST_UUID_SHA1_H | |
| #define BOOST_UUID_SHA1_H | |
|  | |
| #include <boost/static_assert.hpp> | |
| #include <cstddef> | |
|  | |
| #ifdef BOOST_NO_STDC_NAMESPACE | |
| namespace std { | |
|     using ::size_t; | |
| } // namespace std | |
| #endif | |
|  | |
| namespace boost { | |
| namespace uuids { | |
| namespace detail { | |
| 
 | |
| BOOST_STATIC_ASSERT(sizeof(unsigned char)*8 == 8); | |
| BOOST_STATIC_ASSERT(sizeof(unsigned int)*8 == 32); | |
| 
 | |
| inline unsigned int left_rotate(unsigned int x, std::size_t n) | |
| { | |
|     return (x<<n) ^ (x>> (32-n)); | |
| } | |
| 
 | |
| class sha1 | |
| { | |
| public: | |
|     typedef unsigned int(&digest_type)[5]; | |
| public: | |
|     sha1(); | |
| 
 | |
|     void reset(); | |
| 
 | |
|     void process_byte(unsigned char byte); | |
|     void process_block(void const* bytes_begin, void const* bytes_end); | |
|     void process_bytes(void const* buffer, std::size_t byte_count); | |
| 
 | |
|     void get_digest(digest_type digest); | |
| 
 | |
| private: | |
|     void process_block(); | |
| 
 | |
| private: | |
|     unsigned int h_[5]; | |
| 
 | |
|     unsigned char block_[64]; | |
| 
 | |
|     std::size_t block_byte_index_; | |
|     std::size_t byte_count_; | |
| }; | |
| 
 | |
| inline sha1::sha1() | |
| { | |
|     reset(); | |
| } | |
| 
 | |
| inline void sha1::reset() | |
| { | |
|     h_[0] = 0x67452301; | |
|     h_[1] = 0xEFCDAB89; | |
|     h_[2] = 0x98BADCFE; | |
|     h_[3] = 0x10325476; | |
|     h_[4] = 0xC3D2E1F0; | |
| 
 | |
|     block_byte_index_ = 0; | |
|     byte_count_ = 0; | |
| } | |
| 
 | |
| inline void sha1::process_byte(unsigned char byte) | |
| { | |
|     block_[block_byte_index_++] = byte; | |
|     ++byte_count_; | |
|     if (block_byte_index_ == 64) { | |
|         block_byte_index_ = 0; | |
|         process_block(); | |
|     } | |
| } | |
| 
 | |
| inline void sha1::process_block(void const* bytes_begin, void const* bytes_end) | |
| { | |
|     unsigned char const* begin = static_cast<unsigned char const*>(bytes_begin); | |
|     unsigned char const* end = static_cast<unsigned char const*>(bytes_end); | |
|     for(; begin != end; ++begin) { | |
|         process_byte(*begin); | |
|     } | |
| } | |
| 
 | |
| inline void sha1::process_bytes(void const* buffer, std::size_t byte_count) | |
| { | |
|     unsigned char const* b = static_cast<unsigned char const*>(buffer); | |
|     process_block(b, b+byte_count); | |
| } | |
| 
 | |
| inline void sha1::process_block() | |
| { | |
|     unsigned int w[80]; | |
|     for (std::size_t i=0; i<16; ++i) { | |
|         w[i]  = (block_[i*4 + 0] << 24); | |
|         w[i] |= (block_[i*4 + 1] << 16); | |
|         w[i] |= (block_[i*4 + 2] << 8); | |
|         w[i] |= (block_[i*4 + 3]); | |
|     } | |
|     for (std::size_t i=16; i<80; ++i) { | |
|         w[i] = left_rotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1); | |
|     } | |
| 
 | |
|     unsigned int a = h_[0]; | |
|     unsigned int b = h_[1]; | |
|     unsigned int c = h_[2]; | |
|     unsigned int d = h_[3]; | |
|     unsigned int e = h_[4]; | |
| 
 | |
|     for (std::size_t i=0; i<80; ++i) { | |
|         unsigned int f; | |
|         unsigned int k; | |
| 
 | |
|         if (i<20) { | |
|             f = (b & c) | (~b & d); | |
|             k = 0x5A827999; | |
|         } else if (i<40) { | |
|             f = b ^ c ^ d; | |
|             k = 0x6ED9EBA1; | |
|         } else if (i<60) { | |
|             f = (b & c) | (b & d) | (c & d); | |
|             k = 0x8F1BBCDC; | |
|         } else { | |
|             f = b ^ c ^ d; | |
|             k = 0xCA62C1D6; | |
|         } | |
| 
 | |
|         unsigned temp = left_rotate(a, 5) + f + e + k + w[i]; | |
|         e = d; | |
|         d = c; | |
|         c = left_rotate(b, 30); | |
|         b = a; | |
|         a = temp; | |
|     } | |
| 
 | |
|     h_[0] += a; | |
|     h_[1] += b; | |
|     h_[2] += c; | |
|     h_[3] += d; | |
|     h_[4] += e; | |
| } | |
| 
 | |
| inline void sha1::get_digest(digest_type digest) | |
| { | |
|     std::size_t bit_count = byte_count_*8; | |
| 
 | |
|     // append the bit '1' to the message | |
|     process_byte(0x80); | |
| 
 | |
|     // append k bits '0', where k is the minimum number >= 0 | |
|     // such that the resulting message length is congruent to 56 (mod 64) | |
|     // check if there is enough space for padding and bit_count | |
|     if (block_byte_index_ > 56) { | |
|         // finish this block | |
|         while (block_byte_index_ != 0) { | |
|             process_byte(0); | |
|         } | |
| 
 | |
|         // one more block | |
|         while (block_byte_index_ < 56) { | |
|             process_byte(0); | |
|         } | |
|     } else { | |
|         while (block_byte_index_ < 56) { | |
|             process_byte(0); | |
|         } | |
|     } | |
| 
 | |
|     // append length of message (before pre-processing)  | |
|     // as a 64-bit big-endian integer | |
|     process_byte(0); | |
|     process_byte(0); | |
|     process_byte(0); | |
|     process_byte(0); | |
|     process_byte( static_cast<unsigned char>((bit_count>>24) & 0xFF)); | |
|     process_byte( static_cast<unsigned char>((bit_count>>16) & 0xFF)); | |
|     process_byte( static_cast<unsigned char>((bit_count>>8 ) & 0xFF)); | |
|     process_byte( static_cast<unsigned char>((bit_count)     & 0xFF)); | |
| 
 | |
|     // get final digest | |
|     digest[0] = h_[0]; | |
|     digest[1] = h_[1]; | |
|     digest[2] = h_[2]; | |
|     digest[3] = h_[3]; | |
|     digest[4] = h_[4]; | |
| } | |
| 
 | |
| }}} // namespace boost::uuids::detail | |
|  | |
| #endif
 | |
| 
 |