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