Project revived from Feb2017
[EroSomnia.git] / deps / boost_1_63_0 / boost / uuid / sha1.hpp
blobe695e13b21379b5694ad3856132088db961042a4
1 // boost/uuid/sha1.hpp header file ----------------------------------------------//
3 // Copyright 2007 Andy Tompkins.
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
8 // Revision History
9 // 29 May 2007 - Initial Revision
10 // 25 Feb 2008 - moved to namespace boost::uuids::detail
11 // 10 Jan 2012 - can now handle the full size of messages (2^64 - 1 bits)
13 // This is a byte oriented implementation
15 #ifndef BOOST_UUID_SHA1_H
16 #define BOOST_UUID_SHA1_H
18 #include <boost/static_assert.hpp>
19 #include <stdexcept>
20 #include <boost/throw_exception.hpp>
21 #include <cstddef>
22 #include <string>
24 #ifdef BOOST_NO_STDC_NAMESPACE
25 namespace std {
26 using ::size_t;
27 } // namespace std
28 #endif
30 namespace boost {
31 namespace uuids {
32 namespace detail {
34 BOOST_STATIC_ASSERT(sizeof(unsigned char)*8 == 8);
35 BOOST_STATIC_ASSERT(sizeof(unsigned int)*8 == 32);
37 inline unsigned int left_rotate(unsigned int x, std::size_t n)
39 return (x<<n) ^ (x>> (32-n));
42 class sha1
44 public:
45 typedef unsigned int(&digest_type)[5];
46 public:
47 sha1();
49 void reset();
51 void process_byte(unsigned char byte);
52 void process_block(void const* bytes_begin, void const* bytes_end);
53 void process_bytes(void const* buffer, std::size_t byte_count);
55 void get_digest(digest_type digest);
57 private:
58 void process_block();
59 void process_byte_impl(unsigned char byte);
61 private:
62 unsigned int h_[5];
64 unsigned char block_[64];
66 std::size_t block_byte_index_;
67 std::size_t bit_count_low;
68 std::size_t bit_count_high;
71 inline sha1::sha1()
73 reset();
76 inline void sha1::reset()
78 h_[0] = 0x67452301;
79 h_[1] = 0xEFCDAB89;
80 h_[2] = 0x98BADCFE;
81 h_[3] = 0x10325476;
82 h_[4] = 0xC3D2E1F0;
84 block_byte_index_ = 0;
85 bit_count_low = 0;
86 bit_count_high = 0;
89 inline void sha1::process_byte(unsigned char byte)
91 process_byte_impl(byte);
93 // size_t max value = 0xFFFFFFFF
94 //if (bit_count_low + 8 >= 0x100000000) { // would overflow
95 //if (bit_count_low >= 0x100000000-8) {
96 if (bit_count_low < 0xFFFFFFF8) {
97 bit_count_low += 8;
98 } else {
99 bit_count_low = 0;
101 if (bit_count_high <= 0xFFFFFFFE) {
102 ++bit_count_high;
103 } else {
104 BOOST_THROW_EXCEPTION(std::runtime_error("sha1 too many bytes"));
109 inline void sha1::process_byte_impl(unsigned char byte)
111 block_[block_byte_index_++] = byte;
113 if (block_byte_index_ == 64) {
114 block_byte_index_ = 0;
115 process_block();
119 inline void sha1::process_block(void const* bytes_begin, void const* bytes_end)
121 unsigned char const* begin = static_cast<unsigned char const*>(bytes_begin);
122 unsigned char const* end = static_cast<unsigned char const*>(bytes_end);
123 for(; begin != end; ++begin) {
124 process_byte(*begin);
128 inline void sha1::process_bytes(void const* buffer, std::size_t byte_count)
130 unsigned char const* b = static_cast<unsigned char const*>(buffer);
131 process_block(b, b+byte_count);
134 inline void sha1::process_block()
136 unsigned int w[80];
137 for (std::size_t i=0; i<16; ++i) {
138 w[i] = (block_[i*4 + 0] << 24);
139 w[i] |= (block_[i*4 + 1] << 16);
140 w[i] |= (block_[i*4 + 2] << 8);
141 w[i] |= (block_[i*4 + 3]);
143 for (std::size_t i=16; i<80; ++i) {
144 w[i] = left_rotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1);
147 unsigned int a = h_[0];
148 unsigned int b = h_[1];
149 unsigned int c = h_[2];
150 unsigned int d = h_[3];
151 unsigned int e = h_[4];
153 for (std::size_t i=0; i<80; ++i) {
154 unsigned int f;
155 unsigned int k;
157 if (i<20) {
158 f = (b & c) | (~b & d);
159 k = 0x5A827999;
160 } else if (i<40) {
161 f = b ^ c ^ d;
162 k = 0x6ED9EBA1;
163 } else if (i<60) {
164 f = (b & c) | (b & d) | (c & d);
165 k = 0x8F1BBCDC;
166 } else {
167 f = b ^ c ^ d;
168 k = 0xCA62C1D6;
171 unsigned temp = left_rotate(a, 5) + f + e + k + w[i];
172 e = d;
173 d = c;
174 c = left_rotate(b, 30);
175 b = a;
176 a = temp;
179 h_[0] += a;
180 h_[1] += b;
181 h_[2] += c;
182 h_[3] += d;
183 h_[4] += e;
186 inline void sha1::get_digest(digest_type digest)
188 // append the bit '1' to the message
189 process_byte_impl(0x80);
191 // append k bits '0', where k is the minimum number >= 0
192 // such that the resulting message length is congruent to 56 (mod 64)
193 // check if there is enough space for padding and bit_count
194 if (block_byte_index_ > 56) {
195 // finish this block
196 while (block_byte_index_ != 0) {
197 process_byte_impl(0);
200 // one more block
201 while (block_byte_index_ < 56) {
202 process_byte_impl(0);
204 } else {
205 while (block_byte_index_ < 56) {
206 process_byte_impl(0);
210 // append length of message (before pre-processing)
211 // as a 64-bit big-endian integer
212 process_byte_impl( static_cast<unsigned char>((bit_count_high>>24) & 0xFF) );
213 process_byte_impl( static_cast<unsigned char>((bit_count_high>>16) & 0xFF) );
214 process_byte_impl( static_cast<unsigned char>((bit_count_high>>8 ) & 0xFF) );
215 process_byte_impl( static_cast<unsigned char>((bit_count_high) & 0xFF) );
216 process_byte_impl( static_cast<unsigned char>((bit_count_low>>24) & 0xFF) );
217 process_byte_impl( static_cast<unsigned char>((bit_count_low>>16) & 0xFF) );
218 process_byte_impl( static_cast<unsigned char>((bit_count_low>>8 ) & 0xFF) );
219 process_byte_impl( static_cast<unsigned char>((bit_count_low) & 0xFF) );
221 // get final digest
222 digest[0] = h_[0];
223 digest[1] = h_[1];
224 digest[2] = h_[2];
225 digest[3] = h_[3];
226 digest[4] = h_[4];
229 }}} // namespace boost::uuids::detail
231 #endif