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>
23 #ifdef BOOST_NO_STDC_NAMESPACE
33 BOOST_STATIC_ASSERT(sizeof(unsigned char)*8 == 8);
34 BOOST_STATIC_ASSERT(sizeof(unsigned int)*8 == 32);
36 inline unsigned int left_rotate(unsigned int x, std::size_t n)
38 return (x<<n) ^ (x>> (32-n));
44 typedef unsigned int(&digest_type)[5];
50 void process_byte(unsigned char byte);
51 void process_block(void const* bytes_begin, void const* bytes_end);
52 void process_bytes(void const* buffer, std::size_t byte_count);
54 void get_digest(digest_type digest);
58 void process_byte_impl(unsigned char byte);
63 unsigned char block_[64];
65 std::size_t block_byte_index_;
66 std::size_t bit_count_low;
67 std::size_t bit_count_high;
75 inline void sha1::reset()
83 block_byte_index_ = 0;
88 inline void sha1::process_byte(unsigned char byte)
90 process_byte_impl(byte);
93 if (bit_count_low == 0) {
95 if (bit_count_high == 0) {
96 BOOST_THROW_EXCEPTION(std::runtime_error("sha1 too many bytes"));
101 inline void sha1::process_byte_impl(unsigned char byte)
103 block_[block_byte_index_++] = byte;
105 if (block_byte_index_ == 64) {
106 block_byte_index_ = 0;
111 inline void sha1::process_block(void const* bytes_begin, void const* bytes_end)
113 unsigned char const* begin = static_cast<unsigned char const*>(bytes_begin);
114 unsigned char const* end = static_cast<unsigned char const*>(bytes_end);
115 for(; begin != end; ++begin) {
116 process_byte(*begin);
120 inline void sha1::process_bytes(void const* buffer, std::size_t byte_count)
122 unsigned char const* b = static_cast<unsigned char const*>(buffer);
123 process_block(b, b+byte_count);
126 inline void sha1::process_block()
129 for (std::size_t i=0; i<16; ++i) {
130 w[i] = (block_[i*4 + 0] << 24);
131 w[i] |= (block_[i*4 + 1] << 16);
132 w[i] |= (block_[i*4 + 2] << 8);
133 w[i] |= (block_[i*4 + 3]);
135 for (std::size_t i=16; i<80; ++i) {
136 w[i] = left_rotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1);
139 unsigned int a = h_[0];
140 unsigned int b = h_[1];
141 unsigned int c = h_[2];
142 unsigned int d = h_[3];
143 unsigned int e = h_[4];
145 for (std::size_t i=0; i<80; ++i) {
150 f = (b & c) | (~b & d);
156 f = (b & c) | (b & d) | (c & d);
163 unsigned temp = left_rotate(a, 5) + f + e + k + w[i];
166 c = left_rotate(b, 30);
178 inline void sha1::get_digest(digest_type digest)
180 // append the bit '1' to the message
181 process_byte_impl(0x80);
183 // append k bits '0', where k is the minimum number >= 0
184 // such that the resulting message length is congruent to 56 (mod 64)
185 // check if there is enough space for padding and bit_count
186 if (block_byte_index_ > 56) {
188 while (block_byte_index_ != 0) {
189 process_byte_impl(0);
193 while (block_byte_index_ < 56) {
194 process_byte_impl(0);
197 while (block_byte_index_ < 56) {
198 process_byte_impl(0);
202 // append length of message (before pre-processing)
203 // as a 64-bit big-endian integer
204 process_byte_impl( static_cast<unsigned char>((bit_count_high>>24) & 0xFF) );
205 process_byte_impl( static_cast<unsigned char>((bit_count_high>>16) & 0xFF) );
206 process_byte_impl( static_cast<unsigned char>((bit_count_high>>8 ) & 0xFF) );
207 process_byte_impl( static_cast<unsigned char>((bit_count_high) & 0xFF) );
208 process_byte_impl( static_cast<unsigned char>((bit_count_low>>24) & 0xFF) );
209 process_byte_impl( static_cast<unsigned char>((bit_count_low>>16) & 0xFF) );
210 process_byte_impl( static_cast<unsigned char>((bit_count_low>>8 ) & 0xFF) );
211 process_byte_impl( static_cast<unsigned char>((bit_count_low) & 0xFF) );
221 }}} // namespace boost::uuids::detail