CMSDK 2.0.1
Cross-platform C++ base library and SDK for the Psyclone AIOS platform
Loading...
Searching...
No Matches
sha256.cpp
Go to the documentation of this file.
1
6// //////////////////////////////////////////////////////////
7// sha256.cpp
8// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
9// see http://create.stephan-brumme.com/disclaimer.html
10//
11
12#include "hash/sha256.h"
14
15// big endian architectures need #define __BYTE_ORDER __BIG_ENDIAN
16#ifndef _MSC_VER
17#ifndef __APPLE__
18#include <endian.h>
19#endif
20#endif
21
22// Added namespace to avoid clash with OpenSSL
23namespace hash {
24
27{
28 reset();
29}
30
31
33void SHA256::reset()
34{
35 m_numBytes = 0;
36 m_bufferSize = 0;
37
38 // according to RFC 1321
39 m_hash[0] = 0x6a09e667;
40 m_hash[1] = 0xbb67ae85;
41 m_hash[2] = 0x3c6ef372;
42 m_hash[3] = 0xa54ff53a;
43 m_hash[4] = 0x510e527f;
44 m_hash[5] = 0x9b05688c;
45 m_hash[6] = 0x1f83d9ab;
46 m_hash[7] = 0x5be0cd19;
47}
48
49
50namespace
51{
52 inline uint32_t rotate(uint32_t a, uint32_t c)
53 {
54 return (a >> c) | (a << (32 - c));
55 }
56
57 inline uint32_t swap(uint32_t x)
58 {
59#if defined(__GNUC__) || defined(__clang__)
60 return __builtin_bswap32(x);
61#endif
62#ifdef MSC_VER
63 return _byteswap_ulong(x);
64#endif
65
66 return (x >> 24) |
67 ((x >> 8) & 0x0000FF00) |
68 ((x << 8) & 0x00FF0000) |
69 (x << 24);
70 }
71
72 // mix functions for processBlock()
73 inline uint32_t f1(uint32_t e, uint32_t f, uint32_t g)
74 {
75 uint32_t term1 = rotate(e, 6) ^ rotate(e, 11) ^ rotate(e, 25);
76 uint32_t term2 = (e & f) ^ (~e & g); //(g ^ (e & (f ^ g)))
77 return term1 + term2;
78 }
79
80 inline uint32_t f2(uint32_t a, uint32_t b, uint32_t c)
81 {
82 uint32_t term1 = rotate(a, 2) ^ rotate(a, 13) ^ rotate(a, 22);
83 uint32_t term2 = ((a | b) & c) | (a & b); //(a & (b ^ c)) ^ (b & c);
84 return term1 + term2;
85 }
86}
87
88
90void SHA256::processBlock(const void* data)
91{
92 // get last hash
93 uint32_t a = m_hash[0];
94 uint32_t b = m_hash[1];
95 uint32_t c = m_hash[2];
96 uint32_t d = m_hash[3];
97 uint32_t e = m_hash[4];
98 uint32_t f = m_hash[5];
99 uint32_t g = m_hash[6];
100 uint32_t h = m_hash[7];
101
102 // data represented as 16x 32-bit words
103 const uint32_t* input = (uint32_t*) data;
104 // convert to big endian
105 uint32_t words[64];
106 int i;
107 for (i = 0; i < 16; i++)
108#if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN)
109 words[i] = input[i];
110#else
111 words[i] = swap(input[i]);
112#endif
113
114 uint32_t x,y; // temporaries
115
116 // first round
117 x = h + f1(e,f,g) + 0x428a2f98 + words[ 0]; y = f2(a,b,c); d += x; h = x + y;
118 x = g + f1(d,e,f) + 0x71374491 + words[ 1]; y = f2(h,a,b); c += x; g = x + y;
119 x = f + f1(c,d,e) + 0xb5c0fbcf + words[ 2]; y = f2(g,h,a); b += x; f = x + y;
120 x = e + f1(b,c,d) + 0xe9b5dba5 + words[ 3]; y = f2(f,g,h); a += x; e = x + y;
121 x = d + f1(a,b,c) + 0x3956c25b + words[ 4]; y = f2(e,f,g); h += x; d = x + y;
122 x = c + f1(h,a,b) + 0x59f111f1 + words[ 5]; y = f2(d,e,f); g += x; c = x + y;
123 x = b + f1(g,h,a) + 0x923f82a4 + words[ 6]; y = f2(c,d,e); f += x; b = x + y;
124 x = a + f1(f,g,h) + 0xab1c5ed5 + words[ 7]; y = f2(b,c,d); e += x; a = x + y;
125
126 // secound round
127 x = h + f1(e,f,g) + 0xd807aa98 + words[ 8]; y = f2(a,b,c); d += x; h = x + y;
128 x = g + f1(d,e,f) + 0x12835b01 + words[ 9]; y = f2(h,a,b); c += x; g = x + y;
129 x = f + f1(c,d,e) + 0x243185be + words[10]; y = f2(g,h,a); b += x; f = x + y;
130 x = e + f1(b,c,d) + 0x550c7dc3 + words[11]; y = f2(f,g,h); a += x; e = x + y;
131 x = d + f1(a,b,c) + 0x72be5d74 + words[12]; y = f2(e,f,g); h += x; d = x + y;
132 x = c + f1(h,a,b) + 0x80deb1fe + words[13]; y = f2(d,e,f); g += x; c = x + y;
133 x = b + f1(g,h,a) + 0x9bdc06a7 + words[14]; y = f2(c,d,e); f += x; b = x + y;
134 x = a + f1(f,g,h) + 0xc19bf174 + words[15]; y = f2(b,c,d); e += x; a = x + y;
135
136 // extend to 24 words
137 for (; i < 24; i++)
138 words[i] = words[i-16] +
139 (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
140 words[i-7] +
141 (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
142
143 // third round
144 x = h + f1(e,f,g) + 0xe49b69c1 + words[16]; y = f2(a,b,c); d += x; h = x + y;
145 x = g + f1(d,e,f) + 0xefbe4786 + words[17]; y = f2(h,a,b); c += x; g = x + y;
146 x = f + f1(c,d,e) + 0x0fc19dc6 + words[18]; y = f2(g,h,a); b += x; f = x + y;
147 x = e + f1(b,c,d) + 0x240ca1cc + words[19]; y = f2(f,g,h); a += x; e = x + y;
148 x = d + f1(a,b,c) + 0x2de92c6f + words[20]; y = f2(e,f,g); h += x; d = x + y;
149 x = c + f1(h,a,b) + 0x4a7484aa + words[21]; y = f2(d,e,f); g += x; c = x + y;
150 x = b + f1(g,h,a) + 0x5cb0a9dc + words[22]; y = f2(c,d,e); f += x; b = x + y;
151 x = a + f1(f,g,h) + 0x76f988da + words[23]; y = f2(b,c,d); e += x; a = x + y;
152
153 // extend to 32 words
154 for (; i < 32; i++)
155 words[i] = words[i-16] +
156 (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
157 words[i-7] +
158 (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
159
160 // fourth round
161 x = h + f1(e,f,g) + 0x983e5152 + words[24]; y = f2(a,b,c); d += x; h = x + y;
162 x = g + f1(d,e,f) + 0xa831c66d + words[25]; y = f2(h,a,b); c += x; g = x + y;
163 x = f + f1(c,d,e) + 0xb00327c8 + words[26]; y = f2(g,h,a); b += x; f = x + y;
164 x = e + f1(b,c,d) + 0xbf597fc7 + words[27]; y = f2(f,g,h); a += x; e = x + y;
165 x = d + f1(a,b,c) + 0xc6e00bf3 + words[28]; y = f2(e,f,g); h += x; d = x + y;
166 x = c + f1(h,a,b) + 0xd5a79147 + words[29]; y = f2(d,e,f); g += x; c = x + y;
167 x = b + f1(g,h,a) + 0x06ca6351 + words[30]; y = f2(c,d,e); f += x; b = x + y;
168 x = a + f1(f,g,h) + 0x14292967 + words[31]; y = f2(b,c,d); e += x; a = x + y;
169
170 // extend to 40 words
171 for (; i < 40; i++)
172 words[i] = words[i-16] +
173 (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
174 words[i-7] +
175 (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
176
177 // fifth round
178 x = h + f1(e,f,g) + 0x27b70a85 + words[32]; y = f2(a,b,c); d += x; h = x + y;
179 x = g + f1(d,e,f) + 0x2e1b2138 + words[33]; y = f2(h,a,b); c += x; g = x + y;
180 x = f + f1(c,d,e) + 0x4d2c6dfc + words[34]; y = f2(g,h,a); b += x; f = x + y;
181 x = e + f1(b,c,d) + 0x53380d13 + words[35]; y = f2(f,g,h); a += x; e = x + y;
182 x = d + f1(a,b,c) + 0x650a7354 + words[36]; y = f2(e,f,g); h += x; d = x + y;
183 x = c + f1(h,a,b) + 0x766a0abb + words[37]; y = f2(d,e,f); g += x; c = x + y;
184 x = b + f1(g,h,a) + 0x81c2c92e + words[38]; y = f2(c,d,e); f += x; b = x + y;
185 x = a + f1(f,g,h) + 0x92722c85 + words[39]; y = f2(b,c,d); e += x; a = x + y;
186
187 // extend to 48 words
188 for (; i < 48; i++)
189 words[i] = words[i-16] +
190 (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
191 words[i-7] +
192 (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
193
194 // sixth round
195 x = h + f1(e,f,g) + 0xa2bfe8a1 + words[40]; y = f2(a,b,c); d += x; h = x + y;
196 x = g + f1(d,e,f) + 0xa81a664b + words[41]; y = f2(h,a,b); c += x; g = x + y;
197 x = f + f1(c,d,e) + 0xc24b8b70 + words[42]; y = f2(g,h,a); b += x; f = x + y;
198 x = e + f1(b,c,d) + 0xc76c51a3 + words[43]; y = f2(f,g,h); a += x; e = x + y;
199 x = d + f1(a,b,c) + 0xd192e819 + words[44]; y = f2(e,f,g); h += x; d = x + y;
200 x = c + f1(h,a,b) + 0xd6990624 + words[45]; y = f2(d,e,f); g += x; c = x + y;
201 x = b + f1(g,h,a) + 0xf40e3585 + words[46]; y = f2(c,d,e); f += x; b = x + y;
202 x = a + f1(f,g,h) + 0x106aa070 + words[47]; y = f2(b,c,d); e += x; a = x + y;
203
204 // extend to 56 words
205 for (; i < 56; i++)
206 words[i] = words[i-16] +
207 (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
208 words[i-7] +
209 (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
210
211 // seventh round
212 x = h + f1(e,f,g) + 0x19a4c116 + words[48]; y = f2(a,b,c); d += x; h = x + y;
213 x = g + f1(d,e,f) + 0x1e376c08 + words[49]; y = f2(h,a,b); c += x; g = x + y;
214 x = f + f1(c,d,e) + 0x2748774c + words[50]; y = f2(g,h,a); b += x; f = x + y;
215 x = e + f1(b,c,d) + 0x34b0bcb5 + words[51]; y = f2(f,g,h); a += x; e = x + y;
216 x = d + f1(a,b,c) + 0x391c0cb3 + words[52]; y = f2(e,f,g); h += x; d = x + y;
217 x = c + f1(h,a,b) + 0x4ed8aa4a + words[53]; y = f2(d,e,f); g += x; c = x + y;
218 x = b + f1(g,h,a) + 0x5b9cca4f + words[54]; y = f2(c,d,e); f += x; b = x + y;
219 x = a + f1(f,g,h) + 0x682e6ff3 + words[55]; y = f2(b,c,d); e += x; a = x + y;
220
221 // extend to 64 words
222 for (; i < 64; i++)
223 words[i] = words[i-16] +
224 (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
225 words[i-7] +
226 (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
227
228 // eigth round
229 x = h + f1(e,f,g) + 0x748f82ee + words[56]; y = f2(a,b,c); d += x; h = x + y;
230 x = g + f1(d,e,f) + 0x78a5636f + words[57]; y = f2(h,a,b); c += x; g = x + y;
231 x = f + f1(c,d,e) + 0x84c87814 + words[58]; y = f2(g,h,a); b += x; f = x + y;
232 x = e + f1(b,c,d) + 0x8cc70208 + words[59]; y = f2(f,g,h); a += x; e = x + y;
233 x = d + f1(a,b,c) + 0x90befffa + words[60]; y = f2(e,f,g); h += x; d = x + y;
234 x = c + f1(h,a,b) + 0xa4506ceb + words[61]; y = f2(d,e,f); g += x; c = x + y;
235 x = b + f1(g,h,a) + 0xbef9a3f7 + words[62]; y = f2(c,d,e); f += x; b = x + y;
236 x = a + f1(f,g,h) + 0xc67178f2 + words[63]; y = f2(b,c,d); e += x; a = x + y;
237
238 // update hash
239 m_hash[0] += a;
240 m_hash[1] += b;
241 m_hash[2] += c;
242 m_hash[3] += d;
243 m_hash[4] += e;
244 m_hash[5] += f;
245 m_hash[6] += g;
246 m_hash[7] += h;
247}
248
249
251void SHA256::add(const void* data, size_t numBytes)
252{
253 const uint8_t* current = (const uint8_t*) data;
254
255 if (m_bufferSize > 0)
256 {
257 while (numBytes > 0 && m_bufferSize < BlockSize)
258 {
259 m_buffer[m_bufferSize++] = *current++;
260 numBytes--;
261 }
262 }
263
264 // full buffer
265 if (m_bufferSize == BlockSize)
266 {
267 processBlock(m_buffer);
268 m_numBytes += BlockSize;
269 m_bufferSize = 0;
270 }
271
272 // no more data ?
273 if (numBytes == 0)
274 return;
275
276 // process full blocks
277 while (numBytes >= BlockSize)
278 {
279 processBlock(current);
280 current += BlockSize;
281 m_numBytes += BlockSize;
282 numBytes -= BlockSize;
283 }
284
285 // keep remaining bytes in buffer
286 while (numBytes > 0)
287 {
288 m_buffer[m_bufferSize++] = *current++;
289 numBytes--;
290 }
291}
292
293
295void SHA256::processBuffer()
296{
297 // the input bytes are considered as bits strings, where the first bit is the most significant bit of the byte
298
299 // - append "1" bit to message
300 // - append "0" bits until message length in bit mod 512 is 448
301 // - append length as 64 bit integer
302
303 // number of bits
304 size_t paddedLength = m_bufferSize * 8;
305
306 // plus one bit set to 1 (always appended)
307 paddedLength++;
308
309 // number of bits must be (numBits % 512) = 448
310 size_t lower11Bits = paddedLength & 511;
311 if (lower11Bits <= 448)
312 paddedLength += 448 - lower11Bits;
313 else
314 paddedLength += 512 + 448 - lower11Bits;
315 // convert from bits to bytes
316 paddedLength /= 8;
317
318 // only needed if additional data flows over into a second block
319 unsigned char extra[BlockSize];
320
321 // append a "1" bit, 128 => binary 10000000
322 if (m_bufferSize < BlockSize)
323 m_buffer[m_bufferSize] = 128;
324 else
325 extra[0] = 128;
326
327 size_t i;
328 for (i = m_bufferSize + 1; i < BlockSize; i++)
329 m_buffer[i] = 0;
330 for (; i < paddedLength; i++)
331 extra[i - BlockSize] = 0;
332
333 // add message length in bits as 64 bit number
334 uint64_t msgBits = 8 * (m_numBytes + m_bufferSize);
335 // find right position
336 unsigned char* addLength;
337 if (paddedLength < BlockSize)
338 addLength = m_buffer + paddedLength;
339 else
340 addLength = extra + paddedLength - BlockSize;
341
342 // must be big endian
343 *addLength++ = (unsigned char)((msgBits >> 56) & 0xFF);
344 *addLength++ = (unsigned char)((msgBits >> 48) & 0xFF);
345 *addLength++ = (unsigned char)((msgBits >> 40) & 0xFF);
346 *addLength++ = (unsigned char)((msgBits >> 32) & 0xFF);
347 *addLength++ = (unsigned char)((msgBits >> 24) & 0xFF);
348 *addLength++ = (unsigned char)((msgBits >> 16) & 0xFF);
349 *addLength++ = (unsigned char)((msgBits >> 8) & 0xFF);
350 *addLength = (unsigned char)( msgBits & 0xFF);
351
352 // process blocks
353 processBlock(m_buffer);
354 // flowed over into a second block ?
355 if (paddedLength > BlockSize)
356 processBlock(extra);
357}
358
359
361std::string SHA256::getHash()
362{
363 // compute hash (as raw bytes)
364 unsigned char rawHash[HashBytes];
365 getHash(rawHash);
366
367 // convert to hex string
368 std::string result;
369 result.reserve(2 * HashBytes);
370 for (int i = 0; i < HashBytes; i++)
371 {
372 static const char dec2hex[16+1] = "0123456789abcdef";
373 result += dec2hex[(rawHash[i] >> 4) & 15];
374 result += dec2hex[ rawHash[i] & 15];
375 }
376
377 return result;
378}
379
380
382void SHA256::getHash(unsigned char buffer[SHA256::HashBytes])
383{
384 // save old hash if buffer is partially filled
385 uint32_t oldHash[HashValues];
386 for (int i = 0; i < HashValues; i++)
387 oldHash[i] = m_hash[i];
388
389 // process remaining bytes
390 processBuffer();
391
392 unsigned char* current = buffer;
393 for (int i = 0; i < HashValues; i++)
394 {
395 *current++ = (m_hash[i] >> 24) & 0xFF;
396 *current++ = (m_hash[i] >> 16) & 0xFF;
397 *current++ = (m_hash[i] >> 8) & 0xFF;
398 *current++ = m_hash[i] & 0xFF;
399
400 // restore old hash
401 m_hash[i] = oldHash[i];
402 }
403}
404
405
407std::string SHA256::operator()(const void* data, size_t numBytes)
408{
409 reset();
410 add(data, numBytes);
411 return getHash();
412}
413
414
416std::string SHA256::operator()(const std::string& text)
417{
418 reset();
419 add(text.c_str(), text.size());
420 return getHash();
421}
422
423} // namespace hash
std::string getHash()
return latest hash as 64 hex characters
SHA256()
same as reset()
std::string operator()(const void *data, size_t numBytes)
compute SHA256 of a memory block
void reset()
restart
void add(const void *data, size_t numBytes)
add arbitrary number of bytes
Usage: std::string msg = "The quick brown fox jumps over the lazy dog"; std::string key = "key"; std:...
Definition crc32.h:28
Third-party (vendored): SHA-256 hash from Stephan Brumme's portable hashing library (create....