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