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)
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>
20 #include <boost/throw_exception.hpp>
24 #ifdef BOOST_NO_STDC_NAMESPACE
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
));
45 typedef unsigned int(&digest_type
)[5];
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
);
59 void process_byte_impl(unsigned char byte
);
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
;
76 inline void sha1::reset()
84 block_byte_index_
= 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) {
101 if (bit_count_high
<= 0xFFFFFFFE) {
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;
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()
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
) {
158 f
= (b
& c
) | (~b
& d
);
164 f
= (b
& c
) | (b
& d
) | (c
& d
);
171 unsigned temp
= left_rotate(a
, 5) + f
+ e
+ k
+ w
[i
];
174 c
= left_rotate(b
, 30);
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) {
196 while (block_byte_index_
!= 0) {
197 process_byte_impl(0);
201 while (block_byte_index_
< 56) {
202 process_byte_impl(0);
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) );
229 }}} // namespace boost::uuids::detail