stdex
Additional custom or not Standard C++ covered algorithms
Loading...
Searching...
No Matches
hash.hpp
1/*
2 SPDX-License-Identifier: MIT
3 Copyright © 2016-2024 Amebis
4*/
5
6#pragma once
7
8#include "compat.hpp"
9#include "math.h"
10#include "stream.hpp"
11#include <stdint.h>
12
13#if defined(__GNUC__)
14#pragma GCC diagnostic push
15#pragma GCC diagnostic ignored "-Wunknown-pragmas"
16#endif
17
18namespace stdex
19{
20#pragma warning(push)
21#pragma warning(disable: 26495)
22
26 template<class T>
28 {
29 public:
33 virtual void clear() = 0;
34
41 virtual void hash(_In_reads_bytes_opt_(length) const void* data, _In_ size_t length) = 0;
42
46 virtual void finalize() = 0;
47
51 static size_t size() { return sizeof(T); }
52
56 const T& data() { return m_value; };
57
61 operator const T&() const { return m_value; };
62
63 protected:
64 T m_value;
65 };
66
70 template<class T>
71 class block_hash : public basic_hash<T>
72 {
73 public:
74 virtual void clear()
75 {
76 m_counter[0] = m_counter[1] = 0;
77 }
78
79 virtual void hash(_In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
80 {
81 _Assume_(data || !length);
82
83 // Compute number of bytes mod 64.
84 size_t j = static_cast<size_t>((m_counter[0] >> 3) & 63);
85
86 // Update number of m_counter[1].
87 if ((m_counter[0] += (static_cast<uint32_t>(length) << 3)) < (static_cast<uint32_t>(length) << 3))
88 m_counter[1]++;
89 m_counter[1] += static_cast<uint32_t>(length) >> 29;
90
91 // Transform as many times as possible.
92 size_t i, remainder = 64 - j;
93 if (length >= remainder) {
94 _Assume_(j < 64 && j + remainder <= 64);
95 _Assume_(remainder <= length);
96 memcpy(m_queue + j, data, remainder);
97 hash_block();
98 for (i = remainder; i + 64 <= length; i += 64) {
99#pragma warning(push)
100#pragma warning(disable: 6385)
101 memcpy(m_queue, reinterpret_cast<const uint8_t*>(data) + i, 64);
102#pragma warning(pop)
103 hash_block();
104 }
105
106 j = 0;
107 }
108 else
109 i = 0;
110
111 // Buffer remaining input.
112 _Assume_(j < 64 && j + length - i <= 64);
113 _Assume_(i <= length);
114 memcpy(m_queue + j, reinterpret_cast<const uint8_t*>(data) + i, length - i);
115 }
116
117 protected:
118 virtual void hash_block() = 0;
119
120 protected:
121 uint32_t m_counter[2];
122 union {
123 uint8_t m_queue[64];
124 uint32_t m_temp[16];
125 };
126 };
127
128#pragma warning(pop)
129
133 template<class T>
135 {
136 public:
137 stream_hasher(_Inout_ basic_hash<T>& hash, _Inout_ stdex::stream::basic& source) :
139 m_hash(hash)
140 {}
141
142 virtual _Success_(return != 0 || length == 0) size_t read(
143 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
144 {
145 size_t num_read = stdex::stream::converter::read(data, length);
146 m_hash.hash(data, num_read);
147 return num_read;
148 }
149
150 virtual _Success_(return != 0) size_t write(
151 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
152 {
153 size_t num_written = stdex::stream::converter::write(data, length);
154 m_hash.hash(data, num_written);
155 return num_written;
156 }
157
158 protected:
159 basic_hash<T>& m_hash;
160 };
161
165 using crc32_t = uint32_t;
166
170 class crc32_hash : public basic_hash<crc32_t>
171 {
172 public:
173 crc32_hash(crc32_t crc = 0)
174 {
175 m_value = ~crc;
176 }
177
178 virtual void clear()
179 {
180 m_value = 0xffffffff;
181 }
182
183 virtual void hash(_In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
184 {
185 static const uint32_t crc32_table[256] = {
186 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
187 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
188 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
189 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
190 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
191 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
192 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
193 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
194 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
195 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
196 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
197 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
198 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
199 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
200 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
201 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
202 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
203 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
204 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
205 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
206 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
207 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
208 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
209 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
210 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
211 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
212 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
213 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
214 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
215 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
216 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
217 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
218 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
219 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
220 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
221 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
222 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
223 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
224 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
225 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
226 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
227 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
228 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
229 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
230 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
231 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
232 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
233 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
234 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
235 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
236 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
237 0x2d02ef8d
238 };
239
240 _Assume_(data || !length);
241 for (size_t i = 0; i < length; i++)
242 m_value = crc32_table[(m_value ^ reinterpret_cast<const uint8_t*>(data)[i]) & 0xff] ^ (m_value >> 8);
243 }
244
245 virtual void finalize()
246 {
247 m_value = ~m_value;
248 }
249 };
250
254 union md2_t
255 {
256 uint8_t data8[16];
257 uint32_t data32[4];
258
259 bool operator !=(_In_ const stdex::md2_t& other) const
260 {
261 return
262 (data32[0] ^ other.data32[0]) |
263 (data32[1] ^ other.data32[1]) |
264 (data32[2] ^ other.data32[2]) |
265 (data32[3] ^ other.data32[3]);
266 }
267
268 bool operator ==(_In_ const stdex::md2_t& other) const
269 {
270 return !operator !=(other);
271 }
272
273 friend inline stdex::stream::basic& operator >>(_Inout_ stdex::stream::basic& stream, _Out_ stdex::md2_t& data)
274 {
275 if (!stream.ok()) _Unlikely_{
276 memset(&data, 0, sizeof(data));
277 return stream;
278 }
279 stream.read_array(&data, sizeof(data), 1);
280 return stream;
281 }
282
283 friend inline stdex::stream::basic& operator <<(_Inout_ stdex::stream::basic& stream, _In_ const stdex::md2_t& data)
284 {
285 if (!stream.ok()) _Unlikely_ return stream;
286 stream.write_array(&data, sizeof(data), 1);
287 return stream;
288 }
289 };
290
294 using md5_t = md2_t;
295
299 class md5_hash : public block_hash<md5_t>
300 {
301 public:
302 md5_hash()
303 {
304 clear();
305 }
306
307 virtual void clear()
308 {
310 m_state[0] = 0x67452301;
311 m_state[1] = 0xefcdab89;
312 m_state[2] = 0x98badcfe;
313 m_state[3] = 0x10325476;
314 }
315
316 virtual void finalize()
317 {
318 static const uint8_t md5_padding[64] = {
319 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
320 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
321 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
322 };
323
324 // Save number of final.
325 uint8_t final[8];
326 memcpy(final, m_counter, sizeof(m_counter));
327
328 // Pad out to 56 mod 64.
329 size_t index = (m_counter[0] >> 3) & 0x3f;
330 size_t remainder = index < 56 ? 56 - index : 120 - index;
331 hash(md5_padding, remainder);
332
333 // Append length (before padding).
334 hash(final, 8);
335
336 // Store m_state in m_value.
337 memcpy(&m_value, m_state, sizeof(md5_t));
338 }
339
340 protected:
341 virtual void hash_block()
342 {
343 constexpr int S11 = 7;
344 constexpr int S12 = 12;
345 constexpr int S13 = 17;
346 constexpr int S14 = 22;
347 constexpr int S21 = 5;
348 constexpr int S22 = 9;
349 constexpr int S23 = 14;
350 constexpr int S24 = 20;
351 constexpr int S31 = 4;
352 constexpr int S32 = 11;
353 constexpr int S33 = 16;
354 constexpr int S34 = 23;
355 constexpr int S41 = 6;
356 constexpr int S42 = 10;
357 constexpr int S43 = 15;
358 constexpr int S44 = 21;
359
360 // Copy m_state[] to working vars.
361 uint32_t a = m_state[0], b = m_state[1], c = m_state[2], d = m_state[3];
362
363 // MD5 rounds
364 #define MD5_R1(a, b, c, d, i, s, ac) { (a) += (((b) & (c)) | ((~b) & (d))) + m_temp[(i)] + static_cast<uint32_t>(ac); (a) = rol((a), (s)); (a) += (b); }
365 #define MD5_R2(a, b, c, d, i, s, ac) { (a) += (((b) & (d)) | ((c) & (~d))) + m_temp[(i)] + static_cast<uint32_t>(ac); (a) = rol((a), (s)); (a) += (b); }
366 #define MD5_R3(a, b, c, d, i, s, ac) { (a) += ((b) ^ (c) ^ (d)) + m_temp[(i)] + static_cast<uint32_t>(ac); (a) = rol((a), (s)); (a) += (b); }
367 #define MD5_R4(a, b, c, d, i, s, ac) { (a) += ((c) ^ ((b) | (~d))) + m_temp[(i)] + static_cast<uint32_t>(ac); (a) = rol((a), (s)); (a) += (b); }
368
369 // 4 rounds of 16 operations each. Loop unrolled.
370 MD5_R1(a, b, c, d, 0, S11, 0xd76aa478);
371 MD5_R1(d, a, b, c, 1, S12, 0xe8c7b756);
372 MD5_R1(c, d, a, b, 2, S13, 0x242070db);
373 MD5_R1(b, c, d, a, 3, S14, 0xc1bdceee);
374 MD5_R1(a, b, c, d, 4, S11, 0xf57c0faf);
375 MD5_R1(d, a, b, c, 5, S12, 0x4787c62a);
376 MD5_R1(c, d, a, b, 6, S13, 0xa8304613);
377 MD5_R1(b, c, d, a, 7, S14, 0xfd469501);
378 MD5_R1(a, b, c, d, 8, S11, 0x698098d8);
379 MD5_R1(d, a, b, c, 9, S12, 0x8b44f7af);
380 MD5_R1(c, d, a, b, 10, S13, 0xffff5bb1);
381 MD5_R1(b, c, d, a, 11, S14, 0x895cd7be);
382 MD5_R1(a, b, c, d, 12, S11, 0x6b901122);
383 MD5_R1(d, a, b, c, 13, S12, 0xfd987193);
384 MD5_R1(c, d, a, b, 14, S13, 0xa679438e);
385 MD5_R1(b, c, d, a, 15, S14, 0x49b40821);
386 MD5_R2(a, b, c, d, 1, S21, 0xf61e2562);
387 MD5_R2(d, a, b, c, 6, S22, 0xc040b340);
388 MD5_R2(c, d, a, b, 11, S23, 0x265e5a51);
389 MD5_R2(b, c, d, a, 0, S24, 0xe9b6c7aa);
390 MD5_R2(a, b, c, d, 5, S21, 0xd62f105d);
391 MD5_R2(d, a, b, c, 10, S22, 0x2441453);
392 MD5_R2(c, d, a, b, 15, S23, 0xd8a1e681);
393 MD5_R2(b, c, d, a, 4, S24, 0xe7d3fbc8);
394 MD5_R2(a, b, c, d, 9, S21, 0x21e1cde6);
395 MD5_R2(d, a, b, c, 14, S22, 0xc33707d6);
396 MD5_R2(c, d, a, b, 3, S23, 0xf4d50d87);
397 MD5_R2(b, c, d, a, 8, S24, 0x455a14ed);
398 MD5_R2(a, b, c, d, 13, S21, 0xa9e3e905);
399 MD5_R2(d, a, b, c, 2, S22, 0xfcefa3f8);
400 MD5_R2(c, d, a, b, 7, S23, 0x676f02d9);
401 MD5_R2(b, c, d, a, 12, S24, 0x8d2a4c8a);
402 MD5_R3(a, b, c, d, 5, S31, 0xfffa3942);
403 MD5_R3(d, a, b, c, 8, S32, 0x8771f681);
404 MD5_R3(c, d, a, b, 11, S33, 0x6d9d6122);
405 MD5_R3(b, c, d, a, 14, S34, 0xfde5380c);
406 MD5_R3(a, b, c, d, 1, S31, 0xa4beea44);
407 MD5_R3(d, a, b, c, 4, S32, 0x4bdecfa9);
408 MD5_R3(c, d, a, b, 7, S33, 0xf6bb4b60);
409 MD5_R3(b, c, d, a, 10, S34, 0xbebfbc70);
410 MD5_R3(a, b, c, d, 13, S31, 0x289b7ec6);
411 MD5_R3(d, a, b, c, 0, S32, 0xeaa127fa);
412 MD5_R3(c, d, a, b, 3, S33, 0xd4ef3085);
413 MD5_R3(b, c, d, a, 6, S34, 0x4881d05);
414 MD5_R3(a, b, c, d, 9, S31, 0xd9d4d039);
415 MD5_R3(d, a, b, c, 12, S32, 0xe6db99e5);
416 MD5_R3(c, d, a, b, 15, S33, 0x1fa27cf8);
417 MD5_R3(b, c, d, a, 2, S34, 0xc4ac5665);
418 MD5_R4(a, b, c, d, 0, S41, 0xf4292244);
419 MD5_R4(d, a, b, c, 7, S42, 0x432aff97);
420 MD5_R4(c, d, a, b, 14, S43, 0xab9423a7);
421 MD5_R4(b, c, d, a, 5, S44, 0xfc93a039);
422 MD5_R4(a, b, c, d, 12, S41, 0x655b59c3);
423 MD5_R4(d, a, b, c, 3, S42, 0x8f0ccc92);
424 MD5_R4(c, d, a, b, 10, S43, 0xffeff47d);
425 MD5_R4(b, c, d, a, 1, S44, 0x85845dd1);
426 MD5_R4(a, b, c, d, 8, S41, 0x6fa87e4f);
427 MD5_R4(d, a, b, c, 15, S42, 0xfe2ce6e0);
428 MD5_R4(c, d, a, b, 6, S43, 0xa3014314);
429 MD5_R4(b, c, d, a, 13, S44, 0x4e0811a1);
430 MD5_R4(a, b, c, d, 4, S41, 0xf7537e82);
431 MD5_R4(d, a, b, c, 11, S42, 0xbd3af235);
432 MD5_R4(c, d, a, b, 2, S43, 0x2ad7d2bb);
433 MD5_R4(b, c, d, a, 9, S44, 0xeb86d391);
434
435 #undef MD5_R1
436 #undef MD5_R2
437 #undef MD5_R3
438 #undef MD5_R4
439
440 // Add the working vars back into internal state.
441 m_state[0] += a;
442 m_state[1] += b;
443 m_state[2] += c;
444 m_state[3] += d;
445 }
446
447 protected:
448 uint32_t m_state[4];
449 };
450
454 union sha_t
455 {
456 uint8_t data8[20];
457 uint32_t data32[5];
458
459 bool operator !=(_In_ const stdex::sha_t& other) const
460 {
461 return
462 (data32[0] ^ other.data32[0]) |
463 (data32[1] ^ other.data32[1]) |
464 (data32[2] ^ other.data32[2]) |
465 (data32[3] ^ other.data32[3]) |
466 (data32[4] ^ other.data32[4]);
467 }
468
469 bool operator ==(_In_ const stdex::sha_t& other) const
470 {
471 return !operator !=(other);
472 }
473
474 friend inline stdex::stream::basic& operator >>(_Inout_ stdex::stream::basic& stream, _Out_ stdex::sha_t& data)
475 {
476 if (!stream.ok()) _Unlikely_{
477 memset(&data, 0, sizeof(data));
478 return stream;
479 }
480 stream.read_array(&data, sizeof(data), 1);
481 return stream;
482 }
483
484 friend inline stdex::stream::basic& operator <<(_Inout_ stdex::stream::basic& stream, _In_ const stdex::sha_t data)
485 {
486 if (!stream.ok()) _Unlikely_ return stream;
487 stream.write_array(&data, sizeof(data), 1);
488 return stream;
489 }
490 };
491
495 using sha1_t = sha_t;
496
500 class sha1_hash : public block_hash<sha1_t>
501 {
502 public:
503 sha1_hash()
504 {
505 clear();
506 }
507
508 virtual void clear()
509 {
511
512 // SHA1 initialization constants
513 m_state[0] = 0x67452301;
514 m_state[1] = 0xEFCDAB89;
515 m_state[2] = 0x98BADCFE;
516 m_state[3] = 0x10325476;
517 m_state[4] = 0xC3D2E1F0;
518 }
519
520 virtual void finalize()
521 {
522 // Save number of final.
523 uint8_t final[8];
524 for (size_t i = 0; i < 8; i++)
525 final[i] = static_cast<uint8_t>((m_counter[((i >= 4) ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); // Endian independent
526
527 hash("\200", 1);
528 while ((m_counter[0] & 504) != 448)
529 hash("\0", 1);
530 hash(final, 8); // Cause a SHA1Transform()
531
532 // Store m_state in m_value.
533 for (size_t i = 0; i < 20; i++)
534 m_value.data8[i] = static_cast<uint8_t>((m_state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
535 }
536
537 protected:
538 virtual void hash_block()
539 {
540 // Copy m_state[] to working vars.
541 uint32_t a = m_state[0], b = m_state[1], c = m_state[2], d = m_state[3], e = m_state[4];
542
543#if BYTE_ORDER == BIG_ENDIAN
544 #define SHA1BLK0(i) (m_temp[i])
545#else
546 #define SHA1BLK0(i) (m_temp[i] = (rol(m_temp[i],24) & 0xFF00FF00) | (rol(m_temp[i],8) & 0x00FF00FF))
547#endif
548 #define SHA1BLK(i) (m_temp[i&15] = rol(m_temp[(i+13)&15] ^ m_temp[(i+8)&15] ^ m_temp[(i+2)&15] ^ m_temp[i&15],1))
549
550 // SHA1 rounds
551 #define SHA1_R0(v, w, x, y, z, i) { (z) += (((w)&((x)^(y)))^(y))+SHA1BLK0((i))+0x5A827999+rol((v),5); (w)=rol((w),30); }
552 #define SHA1_R1(v, w, x, y, z, i) { (z) += (((w)&((x)^(y)))^(y))+SHA1BLK((i))+0x5A827999+rol((v),5); (w)=rol((w),30); }
553 #define SHA1_R2(v, w, x, y, z, i) { (z) += ((w)^(x)^(y))+SHA1BLK((i))+0x6ED9EBA1+rol((v),5); (w)=rol((w),30); }
554 #define SHA1_R3(v, w, x, y, z, i) { (z) += ((((w)|(x))&(y))|((w)&(x)))+SHA1BLK((i))+0x8F1BBCDC+rol((v),5); (w)=rol((w),30); }
555 #define SHA1_R4(v, w, x, y, z, i) { (z) += ((w)^(x)^(y))+SHA1BLK((i))+0xCA62C1D6+rol((v),5); (w)=rol((w),30); }
556
557 // 5 rounds of 16 operations each. Loop unrolled.
558 SHA1_R0(a, b, c, d, e, 0); SHA1_R0(e, a, b, c, d, 1); SHA1_R0(d, e, a, b, c, 2); SHA1_R0(c, d, e, a, b, 3);
559 SHA1_R0(b, c, d, e, a, 4); SHA1_R0(a, b, c, d, e, 5); SHA1_R0(e, a, b, c, d, 6); SHA1_R0(d, e, a, b, c, 7);
560 SHA1_R0(c, d, e, a, b, 8); SHA1_R0(b, c, d, e, a, 9); SHA1_R0(a, b, c, d, e, 10); SHA1_R0(e, a, b, c, d, 11);
561 SHA1_R0(d, e, a, b, c, 12); SHA1_R0(c, d, e, a, b, 13); SHA1_R0(b, c, d, e, a, 14); SHA1_R0(a, b, c, d, e, 15);
562 SHA1_R1(e, a, b, c, d, 16); SHA1_R1(d, e, a, b, c, 17); SHA1_R1(c, d, e, a, b, 18); SHA1_R1(b, c, d, e, a, 19);
563 SHA1_R2(a, b, c, d, e, 20); SHA1_R2(e, a, b, c, d, 21); SHA1_R2(d, e, a, b, c, 22); SHA1_R2(c, d, e, a, b, 23);
564 SHA1_R2(b, c, d, e, a, 24); SHA1_R2(a, b, c, d, e, 25); SHA1_R2(e, a, b, c, d, 26); SHA1_R2(d, e, a, b, c, 27);
565 SHA1_R2(c, d, e, a, b, 28); SHA1_R2(b, c, d, e, a, 29); SHA1_R2(a, b, c, d, e, 30); SHA1_R2(e, a, b, c, d, 31);
566 SHA1_R2(d, e, a, b, c, 32); SHA1_R2(c, d, e, a, b, 33); SHA1_R2(b, c, d, e, a, 34); SHA1_R2(a, b, c, d, e, 35);
567 SHA1_R2(e, a, b, c, d, 36); SHA1_R2(d, e, a, b, c, 37); SHA1_R2(c, d, e, a, b, 38); SHA1_R2(b, c, d, e, a, 39);
568 SHA1_R3(a, b, c, d, e, 40); SHA1_R3(e, a, b, c, d, 41); SHA1_R3(d, e, a, b, c, 42); SHA1_R3(c, d, e, a, b, 43);
569 SHA1_R3(b, c, d, e, a, 44); SHA1_R3(a, b, c, d, e, 45); SHA1_R3(e, a, b, c, d, 46); SHA1_R3(d, e, a, b, c, 47);
570 SHA1_R3(c, d, e, a, b, 48); SHA1_R3(b, c, d, e, a, 49); SHA1_R3(a, b, c, d, e, 50); SHA1_R3(e, a, b, c, d, 51);
571 SHA1_R3(d, e, a, b, c, 52); SHA1_R3(c, d, e, a, b, 53); SHA1_R3(b, c, d, e, a, 54); SHA1_R3(a, b, c, d, e, 55);
572 SHA1_R3(e, a, b, c, d, 56); SHA1_R3(d, e, a, b, c, 57); SHA1_R3(c, d, e, a, b, 58); SHA1_R3(b, c, d, e, a, 59);
573 SHA1_R4(a, b, c, d, e, 60); SHA1_R4(e, a, b, c, d, 61); SHA1_R4(d, e, a, b, c, 62); SHA1_R4(c, d, e, a, b, 63);
574 SHA1_R4(b, c, d, e, a, 64); SHA1_R4(a, b, c, d, e, 65); SHA1_R4(e, a, b, c, d, 66); SHA1_R4(d, e, a, b, c, 67);
575 SHA1_R4(c, d, e, a, b, 68); SHA1_R4(b, c, d, e, a, 69); SHA1_R4(a, b, c, d, e, 70); SHA1_R4(e, a, b, c, d, 71);
576 SHA1_R4(d, e, a, b, c, 72); SHA1_R4(c, d, e, a, b, 73); SHA1_R4(b, c, d, e, a, 74); SHA1_R4(a, b, c, d, e, 75);
577 SHA1_R4(e, a, b, c, d, 76); SHA1_R4(d, e, a, b, c, 77); SHA1_R4(c, d, e, a, b, 78); SHA1_R4(b, c, d, e, a, 79);
578
579 // Add the working vars back into m_state.
580 m_state[0] += a;
581 m_state[1] += b;
582 m_state[2] += c;
583 m_state[3] += d;
584 m_state[4] += e;
585
586 #undef SHA1_R0
587 #undef SHA1_R1
588 #undef SHA1_R2
589 #undef SHA1_R3
590 #undef SHA1_R4
591 #undef SHA1BLK0
592 #undef SHA1BLK0
593 #undef SHA1BLK
594 }
595
596 protected:
597 uint32_t m_state[5];
598 };
599
604 {
605 uint8_t data8[32];
606 uint32_t data32[8];
607
608 bool operator !=(_In_ const stdex::sha256_t& other) const
609 {
610 return
611 (data32[0] ^ other.data32[0]) |
612 (data32[1] ^ other.data32[1]) |
613 (data32[2] ^ other.data32[2]) |
614 (data32[3] ^ other.data32[3]) |
615 (data32[4] ^ other.data32[4]) |
616 (data32[5] ^ other.data32[5]) |
617 (data32[6] ^ other.data32[6]) |
618 (data32[7] ^ other.data32[7]);
619 }
620
621 bool operator ==(_In_ const stdex::sha256_t& other) const
622 {
623 return !operator !=(other);
624 }
625
626 friend inline stdex::stream::basic& operator >>(_Inout_ stdex::stream::basic& stream, _Out_ stdex::sha256_t& data)
627 {
628 if (!stream.ok()) _Unlikely_{
629 memset(&data, 0, sizeof(data));
630 return stream;
631 }
632 stream.read_array(&data, sizeof(data), 1);
633 return stream;
634 }
635
636 friend inline stdex::stream::basic& operator <<(_Inout_ stdex::stream::basic& stream, _In_ const stdex::sha256_t& data)
637 {
638 if (!stream.ok()) _Unlikely_ return stream;
639 stream.write_array(&data, sizeof(data), 1);
640 return stream;
641 }
642 };
643}
644
645#if defined(__GNUC__)
646#pragma GCC diagnostic pop
647#endif
Basic hashing operations.
Definition hash.hpp:28
const T & data()
Returns hash value.
Definition hash.hpp:56
virtual void hash(_In_reads_bytes_opt_(length) const void *data, size_t length)=0
Hashes block of data.
static size_t size()
Returns size of the hash value in bytes.
Definition hash.hpp:51
virtual void finalize()=0
Finalizes hash value.
virtual void clear()=0
Initializes hash value and internal state.
Hashing in blocks.
Definition hash.hpp:72
virtual void hash(_In_reads_bytes_opt_(length) const void *data, size_t length)
Hashes block of data.
Definition hash.hpp:79
virtual void clear()
Initializes hash value and internal state.
Definition hash.hpp:74
Hashes as CRC32.
Definition hash.hpp:171
virtual void finalize()
Finalizes hash value.
Definition hash.hpp:245
virtual void hash(_In_reads_bytes_opt_(length) const void *data, size_t length)
Hashes block of data.
Definition hash.hpp:183
virtual void clear()
Initializes hash value and internal state.
Definition hash.hpp:178
Hashes as MD5.
Definition hash.hpp:300
virtual void clear()
Initializes hash value and internal state.
Definition hash.hpp:307
virtual void finalize()
Finalizes hash value.
Definition hash.hpp:316
Hashes as SHA1.
Definition hash.hpp:501
virtual void clear()
Initializes hash value and internal state.
Definition hash.hpp:508
virtual void finalize()
Finalizes hash value.
Definition hash.hpp:520
‍UTF-8 byte-order-mark
Definition stream.hpp:84
Modifies data on the fly when reading from/writing to a source stream. Could also be used to modify r...
Definition stream.hpp:1022
virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
Reads block of data from the stream.
Definition stream.hpp:1051
virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
Writes block of data to the stream.
Definition stream.hpp:1059
Hashes read to or write from data of the stream.
Definition hash.hpp:135
virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
Reads block of data from the stream.
Definition hash.hpp:142
virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
Writes block of data to the stream.
Definition hash.hpp:150
MD2 hash value.
Definition hash.hpp:255
SHA256 hash value.
Definition hash.hpp:604
SHA hash value.
Definition hash.hpp:455