]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/uuid/detail/sha1.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / uuid / detail / sha1.hpp
1 // boost/uuid/sha1.hpp header file ----------------------------------------------//
2
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)
7
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)
12
13 // This is a byte oriented implementation
14
15 #ifndef BOOST_UUID_SHA1_H
16 #define BOOST_UUID_SHA1_H
17
18 #include <boost/static_assert.hpp>
19 #include <boost/throw_exception.hpp>
20 #include <boost/uuid/uuid.hpp> // for version
21 #include <cstddef>
22 #include <stdexcept>
23 #include <string>
24
25 #ifdef BOOST_NO_STDC_NAMESPACE
26 namespace std {
27 using ::size_t;
28 } // namespace std
29 #endif
30
31 namespace boost {
32 namespace uuids {
33 namespace detail {
34
35 BOOST_STATIC_ASSERT(sizeof(unsigned char)*8 == 8);
36 BOOST_STATIC_ASSERT(sizeof(unsigned int)*8 == 32);
37
38 inline unsigned int left_rotate(unsigned int x, std::size_t n)
39 {
40 return (x<<n) ^ (x>> (32-n));
41 }
42
43 class sha1
44 {
45 public:
46 typedef unsigned int(digest_type)[5];
47 public:
48 sha1();
49
50 void reset();
51
52 void process_byte(unsigned char byte);
53 void process_block(void const* bytes_begin, void const* bytes_end);
54 void process_bytes(void const* buffer, std::size_t byte_count);
55
56 void get_digest(digest_type& digest);
57 unsigned char get_version() const;
58
59 private:
60 void process_block();
61 void process_byte_impl(unsigned char byte);
62
63 private:
64 unsigned int h_[5];
65
66 unsigned char block_[64];
67
68 std::size_t block_byte_index_;
69 std::size_t bit_count_low;
70 std::size_t bit_count_high;
71 };
72
73 inline sha1::sha1()
74 {
75 reset();
76 }
77
78 inline void sha1::reset()
79 {
80 h_[0] = 0x67452301;
81 h_[1] = 0xEFCDAB89;
82 h_[2] = 0x98BADCFE;
83 h_[3] = 0x10325476;
84 h_[4] = 0xC3D2E1F0;
85
86 block_byte_index_ = 0;
87 bit_count_low = 0;
88 bit_count_high = 0;
89 }
90
91 inline void sha1::process_byte(unsigned char byte)
92 {
93 process_byte_impl(byte);
94
95 // size_t max value = 0xFFFFFFFF
96 //if (bit_count_low + 8 >= 0x100000000) { // would overflow
97 //if (bit_count_low >= 0x100000000-8) {
98 if (bit_count_low < 0xFFFFFFF8) {
99 bit_count_low += 8;
100 } else {
101 bit_count_low = 0;
102
103 if (bit_count_high <= 0xFFFFFFFE) {
104 ++bit_count_high;
105 } else {
106 BOOST_THROW_EXCEPTION(std::runtime_error("sha1 too many bytes"));
107 }
108 }
109 }
110
111 inline void sha1::process_byte_impl(unsigned char byte)
112 {
113 block_[block_byte_index_++] = byte;
114
115 if (block_byte_index_ == 64) {
116 block_byte_index_ = 0;
117 process_block();
118 }
119 }
120
121 inline void sha1::process_block(void const* bytes_begin, void const* bytes_end)
122 {
123 unsigned char const* begin = static_cast<unsigned char const*>(bytes_begin);
124 unsigned char const* end = static_cast<unsigned char const*>(bytes_end);
125 for(; begin != end; ++begin) {
126 process_byte(*begin);
127 }
128 }
129
130 inline void sha1::process_bytes(void const* buffer, std::size_t byte_count)
131 {
132 unsigned char const* b = static_cast<unsigned char const*>(buffer);
133 process_block(b, b+byte_count);
134 }
135
136 inline void sha1::process_block()
137 {
138 unsigned int w[80];
139 for (std::size_t i=0; i<16; ++i) {
140 w[i] = (block_[i*4 + 0] << 24);
141 w[i] |= (block_[i*4 + 1] << 16);
142 w[i] |= (block_[i*4 + 2] << 8);
143 w[i] |= (block_[i*4 + 3]);
144 }
145 for (std::size_t i=16; i<80; ++i) {
146 w[i] = left_rotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1);
147 }
148
149 unsigned int a = h_[0];
150 unsigned int b = h_[1];
151 unsigned int c = h_[2];
152 unsigned int d = h_[3];
153 unsigned int e = h_[4];
154
155 for (std::size_t i=0; i<80; ++i) {
156 unsigned int f;
157 unsigned int k;
158
159 if (i<20) {
160 f = (b & c) | (~b & d);
161 k = 0x5A827999;
162 } else if (i<40) {
163 f = b ^ c ^ d;
164 k = 0x6ED9EBA1;
165 } else if (i<60) {
166 f = (b & c) | (b & d) | (c & d);
167 k = 0x8F1BBCDC;
168 } else {
169 f = b ^ c ^ d;
170 k = 0xCA62C1D6;
171 }
172
173 unsigned temp = left_rotate(a, 5) + f + e + k + w[i];
174 e = d;
175 d = c;
176 c = left_rotate(b, 30);
177 b = a;
178 a = temp;
179 }
180
181 h_[0] += a;
182 h_[1] += b;
183 h_[2] += c;
184 h_[3] += d;
185 h_[4] += e;
186 }
187
188 inline unsigned char sha1::get_version() const
189 {
190 // RFC 4122 Section 4.1.3
191 return uuid::version_name_based_sha1;
192 }
193
194 inline void sha1::get_digest(digest_type& digest)
195 {
196 // append the bit '1' to the message
197 process_byte_impl(0x80);
198
199 // append k bits '0', where k is the minimum number >= 0
200 // such that the resulting message length is congruent to 56 (mod 64)
201 // check if there is enough space for padding and bit_count
202 if (block_byte_index_ > 56) {
203 // finish this block
204 while (block_byte_index_ != 0) {
205 process_byte_impl(0);
206 }
207
208 // one more block
209 while (block_byte_index_ < 56) {
210 process_byte_impl(0);
211 }
212 } else {
213 while (block_byte_index_ < 56) {
214 process_byte_impl(0);
215 }
216 }
217
218 // append length of message (before pre-processing)
219 // as a 64-bit big-endian integer
220 process_byte_impl( static_cast<unsigned char>((bit_count_high>>24) & 0xFF) );
221 process_byte_impl( static_cast<unsigned char>((bit_count_high>>16) & 0xFF) );
222 process_byte_impl( static_cast<unsigned char>((bit_count_high>>8 ) & 0xFF) );
223 process_byte_impl( static_cast<unsigned char>((bit_count_high) & 0xFF) );
224 process_byte_impl( static_cast<unsigned char>((bit_count_low>>24) & 0xFF) );
225 process_byte_impl( static_cast<unsigned char>((bit_count_low>>16) & 0xFF) );
226 process_byte_impl( static_cast<unsigned char>((bit_count_low>>8 ) & 0xFF) );
227 process_byte_impl( static_cast<unsigned char>((bit_count_low) & 0xFF) );
228
229 // get final digest
230 digest[0] = h_[0];
231 digest[1] = h_[1];
232 digest[2] = h_[2];
233 digest[3] = h_[3];
234 digest[4] = h_[4];
235 }
236
237 }}} // namespace boost::uuids::detail
238
239 #endif