SNode.C
Loading...
Searching...
No Matches
sha1.cpp
Go to the documentation of this file.
1/*
2 sha1.cpp - source code of
3
4 ============
5 SHA-1 in C++
6 ============
7
8 100% Public Domain.
9
10 Original C Code
11 -- Steve Reid <steve@edmweb.com>
12 Small changes to fit into bglibs
13 -- Bruce Guenter <bruce@untroubled.org>
14 Translation to simpler C++ Code
15 -- Volker Grabsch <vog@notjusthosting.com>
16 Transform (transform_to_binary) digest to binary
17 -- Volker Christian <me@vchrist.at>
18*/
19
20#ifndef DOXYGEN_SHOULD_SKIP_THIS
21
22#include "utils/sha1.h"
23
24#include <cstdlib>
25#include <iomanip>
26#include <sstream>
27
28#endif /* DOXYGEN_SHOULD_SKIP_THIS */
29
30namespace utils {
31
32/* Help macros */
33#define SHA1_ROL(value, bits) (((value) << (bits)) | (((value) & 0xffffffff) >> (32 - (bits))))
34#define SHA1_BLK(i) (block[i & 15] = SHA1_ROL(block[(i + 13) & 15] ^ block[(i + 8) & 15] ^ block[(i + 2) & 15] ^ block[i & 15], 1))
35
36/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
37#define SHA1_R0(v, w, x, y, z, i)
38 z += ((w & (x ^ y)) ^ y) + block[i] + 0x5a827999 + SHA1_ROL(v, 5);
39 w = SHA1_ROL(w, 30);
40#define SHA1_R1(v, w, x, y, z, i)
41 z += ((w & (x ^ y)) ^ y) + SHA1_BLK(i) + 0x5a827999 + SHA1_ROL(v, 5);
42 w = SHA1_ROL(w, 30);
43#define SHA1_R2(v, w, x, y, z, i)
44 z += (w ^ x ^ y) + SHA1_BLK(i) + 0x6ed9eba1 + SHA1_ROL(v, 5);
45 w = SHA1_ROL(w, 30);
46#define SHA1_R3(v, w, x, y, z, i)
47 z += (((w | x) & y) | (w & x)) + SHA1_BLK(i) + 0x8f1bbcdc + SHA1_ROL(v, 5);
48 w = SHA1_ROL(w, 30);
49#define SHA1_R4(v, w, x, y, z, i)
50 z += (w ^ x ^ y) + SHA1_BLK(i) + 0xca62c1d6 + SHA1_ROL(v, 5);
51 w = SHA1_ROL(w, 30);
52
53 SHA1::SHA1() {
54 reset();
55 }
56
57 void SHA1::update(const std::string& s) {
58 std::istringstream is(s);
59 update(is);
60 }
61
62 void SHA1::update(std::istream& is) {
63 std::string rest_of_buffer;
64 read(is, rest_of_buffer, static_cast<std::size_t>(static_cast<int>(BLOCK_BYTES) - static_cast<int>(buffer.size())));
65 buffer += rest_of_buffer;
66
67 while (is) {
68 uint32_t block[BLOCK_INTS];
69 buffer_to_block(buffer, block);
70 transform(block);
71 read(is, buffer, BLOCK_BYTES);
72 }
73 }
74
75 /*
76 * Add padding and return the message digest.
77 */
78
79 std::string SHA1::final() {
80 /* Total number of hashed bits */
81 const uint64_t total_bits = (transforms * BLOCK_BYTES + buffer.size()) * 8;
82
83 /* Padding */
84 buffer += static_cast<std::string::value_type>(0x80);
85 const std::size_t orig_size = buffer.size();
86 while (buffer.size() < BLOCK_BYTES) {
87 buffer += static_cast<char>(0x00);
88 }
89
90 uint32_t block[BLOCK_INTS];
91 buffer_to_block(buffer, block);
92
93 if (orig_size > BLOCK_BYTES - 8) {
94 transform(block);
95 for (unsigned int i = 0; i < BLOCK_INTS - 2; i++) {
96 block[i] = 0;
97 }
98 }
99
100 /* Append total_bits, split this uint64 into two uint32 */
101 block[BLOCK_INTS - 1] = static_cast<uint32_t>(total_bits & 0x00000000FFFFFFFF);
102 block[BLOCK_INTS - 2] = static_cast<uint32_t>((total_bits >> 32) & 0x00000000FFFFFFFF);
103 transform(block);
104
105 /* Hex std::string */
106 std::ostringstream result;
107 for (unsigned int i = 0; i < DIGEST_INTS; i++) {
108 result << std::hex << std::setfill('0') << std::setw(8);
109 result << (digest[i] & 0xffffffff);
110 }
111
112 /* Reset for next run */
113 reset();
114
115 return result.str();
116 }
117
118 void SHA1::reset() {
119 /* SHA1 initialization constants */
120 digest[0] = 0x67452301;
121 digest[1] = 0xefcdab89;
122 digest[2] = 0x98badcfe;
123 digest[3] = 0x10325476;
124 digest[4] = 0xc3d2e1f0;
125
126 /* Reset counters */
127 transforms = 0;
128 buffer = "";
129 }
130
131 /*
132 * Hash a single 512-bit block. This is the core of the algorithm.
133 */
134
135 void SHA1::transform(uint32_t block[BLOCK_BYTES]) {
136 /* Copy digest[] to working vars */
137 uint32_t a = digest[0];
138 uint32_t b = digest[1];
139 uint32_t c = digest[2];
140 uint32_t d = digest[3];
141 uint32_t e = digest[4];
142
143 /* 4 rounds of 20 operations each. Loop unrolled. */
144 SHA1_R0(a, b, c, d, e, 0)
145 SHA1_R0(e, a, b, c, d, 1)
146 SHA1_R0(d, e, a, b, c, 2)
147 SHA1_R0(c, d, e, a, b, 3)
148 SHA1_R0(b, c, d, e, a, 4)
149 SHA1_R0(a, b, c, d, e, 5)
150 SHA1_R0(e, a, b, c, d, 6)
151 SHA1_R0(d, e, a, b, c, 7)
152 SHA1_R0(c, d, e, a, b, 8)
153 SHA1_R0(b, c, d, e, a, 9)
154 SHA1_R0(a, b, c, d, e, 10)
155 SHA1_R0(e, a, b, c, d, 11)
156 SHA1_R0(d, e, a, b, c, 12)
157 SHA1_R0(c, d, e, a, b, 13)
158 SHA1_R0(b, c, d, e, a, 14)
159 SHA1_R0(a, b, c, d, e, 15)
160 SHA1_R1(e, a, b, c, d, 16)
161 SHA1_R1(d, e, a, b, c, 17)
162 SHA1_R1(c, d, e, a, b, 18)
163 SHA1_R1(b, c, d, e, a, 19)
164 SHA1_R2(a, b, c, d, e, 20)
165 SHA1_R2(e, a, b, c, d, 21)
166 SHA1_R2(d, e, a, b, c, 22)
167 SHA1_R2(c, d, e, a, b, 23)
168 SHA1_R2(b, c, d, e, a, 24)
169 SHA1_R2(a, b, c, d, e, 25)
170 SHA1_R2(e, a, b, c, d, 26)
171 SHA1_R2(d, e, a, b, c, 27)
172 SHA1_R2(c, d, e, a, b, 28)
173 SHA1_R2(b, c, d, e, a, 29)
174 SHA1_R2(a, b, c, d, e, 30)
175 SHA1_R2(e, a, b, c, d, 31)
176 SHA1_R2(d, e, a, b, c, 32)
177 SHA1_R2(c, d, e, a, b, 33)
178 SHA1_R2(b, c, d, e, a, 34)
179 SHA1_R2(a, b, c, d, e, 35)
180 SHA1_R2(e, a, b, c, d, 36)
181 SHA1_R2(d, e, a, b, c, 37)
182 SHA1_R2(c, d, e, a, b, 38)
183 SHA1_R2(b, c, d, e, a, 39)
184 SHA1_R3(a, b, c, d, e, 40)
185 SHA1_R3(e, a, b, c, d, 41)
186 SHA1_R3(d, e, a, b, c, 42)
187 SHA1_R3(c, d, e, a, b, 43)
188 SHA1_R3(b, c, d, e, a, 44)
189 SHA1_R3(a, b, c, d, e, 45)
190 SHA1_R3(e, a, b, c, d, 46)
191 SHA1_R3(d, e, a, b, c, 47)
192 SHA1_R3(c, d, e, a, b, 48)
193 SHA1_R3(b, c, d, e, a, 49)
194 SHA1_R3(a, b, c, d, e, 50)
195 SHA1_R3(e, a, b, c, d, 51)
196 SHA1_R3(d, e, a, b, c, 52)
197 SHA1_R3(c, d, e, a, b, 53)
198 SHA1_R3(b, c, d, e, a, 54)
199 SHA1_R3(a, b, c, d, e, 55)
200 SHA1_R3(e, a, b, c, d, 56)
201 SHA1_R3(d, e, a, b, c, 57)
202 SHA1_R3(c, d, e, a, b, 58)
203 SHA1_R3(b, c, d, e, a, 59)
204 SHA1_R4(a, b, c, d, e, 60)
205 SHA1_R4(e, a, b, c, d, 61)
206 SHA1_R4(d, e, a, b, c, 62)
207 SHA1_R4(c, d, e, a, b, 63)
208 SHA1_R4(b, c, d, e, a, 64)
209 SHA1_R4(a, b, c, d, e, 65)
210 SHA1_R4(e, a, b, c, d, 66)
211 SHA1_R4(d, e, a, b, c, 67)
212 SHA1_R4(c, d, e, a, b, 68)
213 SHA1_R4(b, c, d, e, a, 69)
214 SHA1_R4(a, b, c, d, e, 70)
215 SHA1_R4(e, a, b, c, d, 71)
216 SHA1_R4(d, e, a, b, c, 72)
217 SHA1_R4(c, d, e, a, b, 73)
218 SHA1_R4(b, c, d, e, a, 74)
219 SHA1_R4(a, b, c, d, e, 75)
220 SHA1_R4(e, a, b, c, d, 76)
221 SHA1_R4(d, e, a, b, c, 77)
222 SHA1_R4(c, d, e, a, b, 78)
223 SHA1_R4(b, c, d, e, a, 79)
224
225 /* Add the working vars back into digest[] */
226 digest[0] += a;
227 digest[1] += b;
228 digest[2] += c;
229 digest[3] += d;
230 digest[4] += e;
231
232 /* Count the number of transformations */
233 transforms++;
234 }
235
236 void SHA1::buffer_to_block(const std::string& buffer, uint32_t block[BLOCK_BYTES]) {
237 /* Convert the std::string (byte buffer) to a uint32 array (MSB) */
238 for (unsigned int i = 0; i < BLOCK_INTS; i++) {
239 block[i] = static_cast<uint32_t>((buffer[4 * i + 3] & 0xff) | (buffer[4 * i + 2] & 0xff) << 8 |
240 (buffer[4 * i + 1] & 0xff) << 16 | (buffer[4 * i + 0] & 0xff) << 24);
241 }
242 }
243
244 void SHA1::read(std::istream& is, std::string& s, std::size_t max) {
245 char* sbuf = new char[max];
246 is.read(sbuf, static_cast<std::streamsize>(max));
247 s.assign(sbuf, static_cast<unsigned long>(is.gcount()));
248 delete[] sbuf;
249 }
250
251 static std::vector<unsigned char> transform_to_binary(const std::string& string) {
252 std::vector<unsigned char> buf;
253
254 char hex_byte[3];
255 hex_byte[2] = 0;
256
257 for (std::size_t i = 0, j = 0; i < string.size(); i += 2, j += 1) {
258 hex_byte[0] = string.at(i);
259 hex_byte[1] = string.at(i + 1);
260 char* end_ptr = nullptr;
261 buf.push_back(static_cast<unsigned char>(strtoul(hex_byte, &end_ptr, 16)));
262 }
263
264 return buf;
265 }
266
267 std::vector<unsigned char> sha1(const std::string& string) {
268 SHA1 checksum;
269 checksum.update(string);
270 return transform_to_binary(checksum.final());
271 }
272
273} // namespace utils
static std::vector< unsigned char > transform_to_binary(const std::string &string)
Definition sha1.cpp:251
#define SHA1_ROL(value, bits)
Definition sha1.cpp:33
#define SHA1_R2(v, w, x, y, z, i)
Definition sha1.cpp:43
#define SHA1_R3(v, w, x, y, z, i)
Definition sha1.cpp:46
#define SHA1_BLK(i)
Definition sha1.cpp:34
#define SHA1_R4(v, w, x, y, z, i)
Definition sha1.cpp:49
#define SHA1_R1(v, w, x, y, z, i)
Definition sha1.cpp:40
#define SHA1_R0(v, w, x, y, z, i)
Definition sha1.cpp:37