1/**
2 * Copyright (c) 2006-2023 LOVE Development Team
3 *
4 * This software is provided 'as-is', without any express or implied
5 * warranty. In no event will the authors be held liable for any damages
6 * arising from the use of this software.
7 *
8 * Permission is granted to anyone to use this software for any purpose,
9 * including commercial applications, and to alter it and redistribute it
10 * freely, subject to the following restrictions:
11 *
12 * 1. The origin of this software must not be misrepresented; you must not
13 * claim that you wrote the original software. If you use this software
14 * in a product, an acknowledgment in the product documentation would be
15 * appreciated but is not required.
16 * 2. Altered source versions must be plainly marked as such, and must not be
17 * misrepresented as being the original software.
18 * 3. This notice may not be removed or altered from any source distribution.
19 **/
20
21#include "HashFunction.h"
22
23// FIXME: Probably trivial by having tole and tobe functions, which can be ifdeffed to being identity functions
24#ifdef LOVE_BIG_ENDIAN
25# error Hashing not yet implemented for big endian
26#endif
27
28namespace love
29{
30namespace data
31{
32
33namespace
34{
35namespace impl
36{
37
38inline uint32 leftrot(uint32 x, uint8 amount)
39{
40 return (x << amount) | (x >> (32 - amount));
41}
42
43inline uint32 rightrot(uint32 x, uint8 amount)
44{
45 return (x >> amount) | (x << (32 - amount));
46}
47
48inline uint64 rightrot(uint64 x, uint8 amount)
49{
50 return (x >> amount) | (x << (64 - amount));
51}
52
53// Extend the value of `a` to make it a multiple of `n`.
54inline uint64 extend_multiple(uint64 a, uint64 n)
55{
56 uint64 r = a % n;
57 return r == 0 ? a : a + (n-r);
58}
59
60/**
61 * The following implementation is based on the pseudocode provided by multiple
62 * authors on wikipedia: https://en.wikipedia.org/wiki/MD5
63 * The pseudocode is licensed under the CC-BY-SA license, but no authorship
64 * information is present. I believe this note, and the zlib license of this
65 * project satisfy the conditions of the license.
66 **/
67class MD5 : public HashFunction
68{
69private:
70 static const uint8 shifts[64];
71 static const uint32 constants[64];
72
73public:
74 bool isSupported(Function function) const override
75 {
76 return function == FUNCTION_MD5;
77 }
78
79 void hash(Function function, const char *input, uint64 length, Value &output) const override
80 {
81 if (function != FUNCTION_MD5)
82 throw love::Exception("Hash function not supported by MD5 implementation");
83
84 uint32 a0 = 0x67452301;
85 uint32 b0 = 0xefcdab89;
86 uint32 c0 = 0x98badcfe;
87 uint32 d0 = 0x10325476;
88
89 // Compute final padded length, accounting for the appended bit (byte) and size
90 uint64 paddedLength = extend_multiple(length + 1 + 8, 64);
91
92 uint32 *padded = new uint32[paddedLength / 4];
93 memcpy(padded, input, length);
94 memset(((uint8*)padded) + length, 0, paddedLength - length);
95 *(((uint8*)padded) + length) = 0x80; // append bit
96
97 // Append length in bits
98 uint64 bit_length = length * 8;
99 memcpy(((uint8*)padded) + paddedLength - 8, &bit_length, 8);
100
101 // Process chunks
102 for (uint64 i = 0; i < paddedLength/4; i += 16)
103 {
104 uint32 *chunk = &padded[i];
105
106 uint32 A = a0;
107 uint32 B = b0;
108 uint32 C = c0;
109 uint32 D = d0;
110 uint32 F;
111 uint32 g;
112
113 for (int j = 0; j < 64; j++)
114 {
115 if (j < 16)
116 {
117 F = (B & C) | (~B & D);
118 g = j;
119 }
120 else if (j < 32)
121 {
122 F = (D & B) | (~D & C);
123 g = (5*j + 1) % 16;
124 }
125 else if (j < 48)
126 {
127 F = B ^ C ^ D;
128 g = (3*j + 5) % 16;
129 }
130 else
131 {
132 F = C ^ (B | ~D);
133 g = (7*j) % 16;
134 }
135
136 uint32 temp = D;
137 D = C;
138 C = B;
139 B += leftrot(A + F + constants[j] + chunk[g], shifts[j]);
140 A = temp;
141 }
142
143 a0 += A;
144 b0 += B;
145 c0 += C;
146 d0 += D;
147 }
148
149 delete[] padded;
150
151 memcpy(&output.data[ 0], &a0, 4);
152 memcpy(&output.data[ 4], &b0, 4);
153 memcpy(&output.data[ 8], &c0, 4);
154 memcpy(&output.data[12], &d0, 4);
155 output.size = 16;
156 }
157} md5;
158
159const uint8 MD5::shifts[64] = {
160 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
161 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
162 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
163 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21,
164};
165
166const uint32 MD5::constants[64] = {
167 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
168 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
169 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
170 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
171 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
172 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
173 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
174 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
175 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
176 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
177 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
178 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
179 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
180 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
181 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
182 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
183};
184
185/**
186 * The following implementation was based on the text, not the code listings,
187 * in RFC3174. I believe this means no copyright other than that of the L�VE
188 * Development Team applies.
189 **/
190class SHA1 : public HashFunction
191{
192public:
193 bool isSupported(Function function) const override
194 {
195 return function == FUNCTION_SHA1;
196 }
197
198 void hash(Function function, const char *input, uint64 length, Value &output) const override
199 {
200 if (function != FUNCTION_SHA1)
201 throw love::Exception("Hash function not supported by SHA1 implementation");
202
203 uint32 intermediate[5] = {
204 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0
205 };
206
207 // Compute final padded length, accounting for the appended bit (byte) and size
208 uint64 paddedLength = extend_multiple(length + 1 + 8, 64);
209
210 uint32 *padded = new uint32[paddedLength / 4];
211 memcpy(padded, input, length);
212 memset(((uint8*)padded) + length, 0, paddedLength - length);
213 *(((uint8*)padded) + length) = 0x80; // append bit
214
215 // Append length in bits (big endian)
216 uint64 bit_length = length * 8;
217 for (int i = 0; i < 8; ++i)
218 *(((uint8*)padded) + (paddedLength - 8 + i)) = (bit_length >> (56 - i * 8)) & 0xFF;
219
220 // Allocate our extended words
221 uint32 words[80];
222
223 for (uint64 i = 0; i < paddedLength/4; i += 16)
224 {
225 uint32 *chunk = &padded[i];
226 for (int j = 0; j < 16; j++)
227 {
228 char *c = (char*) &words[j];
229 c[0] = (chunk[j] >> 24) & 0xFF;
230 c[1] = (chunk[j] >> 16) & 0xFF;
231 c[2] = (chunk[j] >> 8) & 0xFF;
232 c[3] = (chunk[j] >> 0) & 0xFF;
233 }
234 for (int j = 16; j < 80; j++)
235 words[j] = leftrot(words[j-3] ^ words[j-8] ^ words[j-14] ^ words[j-16], 1);
236
237 uint32 A = intermediate[0];
238 uint32 B = intermediate[1];
239 uint32 C = intermediate[2];
240 uint32 D = intermediate[3];
241 uint32 E = intermediate[4];
242
243 for (int j = 0; j < 80; j++)
244 {
245 uint32 temp = leftrot(A, 5) + E + words[j];
246
247 if (j < 20)
248 temp += 0x5A827999 + ((B & C) | (~B & D));
249 else if (j < 40)
250 temp += 0x6ED9EBA1 + (B ^ C ^ D);
251 else if (j < 60)
252 temp += 0x8F1BBCDC + ((B & C) | (B & D) | (C & D));
253 else
254 temp += 0xCA62C1D6 + (B ^ C ^ D);
255
256 E = D;
257 D = C;
258 C = leftrot(B, 30);
259 B = A;
260 A = temp;
261 }
262
263 intermediate[0] += A;
264 intermediate[1] += B;
265 intermediate[2] += C;
266 intermediate[3] += D;
267 intermediate[4] += E;
268 }
269
270 delete[] padded;
271
272 for (int i = 0; i < 20; i += 4)
273 {
274 output.data[i+0] = (intermediate[i/4] >> 24) & 0xFF;
275 output.data[i+1] = (intermediate[i/4] >> 16) & 0xFF;
276 output.data[i+2] = (intermediate[i/4] >> 8) & 0xFF;
277 output.data[i+3] = (intermediate[i/4] >> 0) & 0xFF;
278 }
279
280 output.size = 20;
281 }
282} sha1;
283
284/**
285 * This implementation was based on the description in RFC-6234.
286 **/
287// SHA-2: SHA-224 and SHA-256
288class SHA256 : public HashFunction
289{
290private:
291 static const uint32 initial224[8];
292 static const uint32 initial256[8];
293 static const uint32 constants[64];
294
295public:
296 bool isSupported(Function function) const override
297 {
298 return function == FUNCTION_SHA224 || function == FUNCTION_SHA256;
299 }
300
301 void hash(Function function, const char *input, uint64 length, Value &output) const override
302 {
303 if (!isSupported(function))
304 throw love::Exception("Hash function not supported by SHA-224/SHA-256 implementation");
305
306 // Compute final padded length, accounting for the appended bit (byte) and size
307 uint64 paddedLength = extend_multiple(length + 1 + 8, 64);
308
309 uint32 *padded = new uint32[paddedLength / 4];
310 memcpy(padded, input, length);
311 memset(((uint8*)padded) + length, 0, paddedLength - length);
312 *(((uint8*)padded) + length) = 0x80; // append bit
313
314 // Append length in bits (big endian)
315 uint64 bit_length = length * 8;
316 for (int i = 0; i < 8; ++i)
317 *(((uint8*)padded) + (paddedLength - 8 + i)) = (bit_length >> (56 - i * 8)) & 0xFF;
318
319 uint32 intermediate[8];
320 if (function == FUNCTION_SHA224)
321 memcpy(intermediate, initial224, sizeof(intermediate));
322 else
323 memcpy(intermediate, initial256, sizeof(intermediate));
324
325 // Allocate our extended words
326 uint32 words[64];
327
328 for (uint64 i = 0; i < paddedLength/4; i += 16)
329 {
330 uint32 *chunk = &padded[i];
331 for (int j = 0; j < 16; j++)
332 {
333 char *c = (char*) &words[j];
334 c[0] = (chunk[j] >> 24) & 0xFF;
335 c[1] = (chunk[j] >> 16) & 0xFF;
336 c[2] = (chunk[j] >> 8) & 0xFF;
337 c[3] = (chunk[j] >> 0) & 0xFF;
338 }
339 for (int j = 16; j < 64; j++)
340 {
341 words[j] = rightrot(words[j-2], 17) ^ rightrot(words[j-2], 19) ^ (words[j-2] >> 10);
342 words[j] += rightrot(words[j-15], 7) ^ rightrot(words[j-15], 18) ^ (words[j-15] >> 3);
343 words[j] += words[j-7] + words[j-16];
344 }
345
346 uint32 A = intermediate[0];
347 uint32 B = intermediate[1];
348 uint32 C = intermediate[2];
349 uint32 D = intermediate[3];
350 uint32 E = intermediate[4];
351 uint32 F = intermediate[5];
352 uint32 G = intermediate[6];
353 uint32 H = intermediate[7];
354
355 for (int j = 0; j < 64; j++)
356 {
357 uint32 temp1 = H + constants[j] + words[j];
358 temp1 += rightrot(E, 6) ^ rightrot(E, 11) ^ rightrot(E, 25);
359 temp1 += (E & F) ^ (~E & G);
360 uint32 temp2 = rightrot(A, 2) ^ rightrot(A, 13) ^ rightrot(A, 22);
361 temp2 += (A & B) ^ (A & C) ^ (B & C);
362
363 H = G;
364 G = F;
365 F = E;
366 E = D + temp1;
367 D = C;
368 C = B;
369 B = A;
370 A = temp1 + temp2;
371 }
372
373 intermediate[0] += A;
374 intermediate[1] += B;
375 intermediate[2] += C;
376 intermediate[3] += D;
377 intermediate[4] += E;
378 intermediate[5] += F;
379 intermediate[6] += G;
380 intermediate[7] += H;
381 }
382
383 delete[] padded;
384
385 int hashlength = 32;
386 if (function == FUNCTION_SHA224)
387 hashlength = 28;
388
389 for (int i = 0; i < hashlength; i += 4)
390 {
391 output.data[i+0] = (intermediate[i/4] >> 24) & 0xFF;
392 output.data[i+1] = (intermediate[i/4] >> 16) & 0xFF;
393 output.data[i+2] = (intermediate[i/4] >> 8) & 0xFF;
394 output.data[i+3] = (intermediate[i/4] >> 0) & 0xFF;
395 }
396
397 output.size = hashlength;
398 }
399} sha256;
400
401const uint32 SHA256::initial224[8] = {
402 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
403 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4,
404};
405
406const uint32 SHA256::initial256[8] = {
407 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
408 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
409};
410
411const uint32 SHA256::constants[64] = {
412 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
413 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
414 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
415 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
416 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
417 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
418 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
419 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
420 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
421 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
422 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
423 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
424 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
425 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
426 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
427 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
428};
429
430/**
431 * This implementation was based on the description in RFC-6234.
432 **/
433// SHA-2: SHA-384 and SHA-512
434class SHA512 : public HashFunction
435{
436private:
437 static const uint64 initial384[8];
438 static const uint64 initial512[8];
439 static const uint64 constants[80];
440
441public:
442 bool isSupported(Function function) const override
443 {
444 return function == FUNCTION_SHA384 || function == FUNCTION_SHA512;
445 }
446
447 void hash(Function function, const char *input, uint64 length, Value &output) const override
448 {
449 if (!isSupported(function))
450 throw love::Exception("Hash function not supported by SHA-384/SHA-512 implementation");
451
452 uint64 intermediates[8];
453 if (function == FUNCTION_SHA384)
454 memcpy(intermediates, initial384, sizeof(intermediates));
455 else
456 memcpy(intermediates, initial512, sizeof(intermediates));
457
458 // Compute final padded length, accounting for the appended bit (byte) and size
459 uint64 paddedLength = extend_multiple(length + 1 + 16, 128);
460
461 uint64 *padded = new uint64[paddedLength / 8];
462 memcpy(padded, input, length);
463 memset(((uint8*)padded) + length, 0, paddedLength - length);
464 *(((uint8*)padded) + length) = 0x80; // append bit
465
466 // Append length in bits (big endian), note we only write a 64-bit int, so
467 // we have filled the first 8 bytes with zeroes
468 uint64 bit_length = length * 8;
469 for (int i = 0; i < 8; ++i)
470 *(((uint8*)padded) + (paddedLength - 8 + i)) = (bit_length >> (56 - i * 8)) & 0xFF;
471
472 // Allocate our extended words
473 uint64 words[80];
474
475 for (uint64 i = 0; i < paddedLength/8; i += 16)
476 {
477 uint64 *chunk = &padded[i];
478 for (int j = 0; j < 16; ++j)
479 {
480 char *c = (char*) &words[j];
481 c[0] = (chunk[j] >> 56) & 0xFF;
482 c[1] = (chunk[j] >> 48) & 0xFF;
483 c[2] = (chunk[j] >> 40) & 0xFF;
484 c[3] = (chunk[j] >> 32) & 0xFF;
485 c[4] = (chunk[j] >> 24) & 0xFF;
486 c[5] = (chunk[j] >> 16) & 0xFF;
487 c[6] = (chunk[j] >> 8) & 0xFF;
488 c[7] = (chunk[j] >> 0) & 0xFF;
489 }
490 for (int j = 16; j < 80; ++j)
491 {
492 words[j] = words[j-7] + words[j-16];
493 words[j] += rightrot(words[j-2], 19) ^ rightrot(words[j-2], 61) ^ (words[j-2] >> 6);
494 words[j] += rightrot(words[j-15], 1) ^ rightrot(words[j-15], 8) ^ (words[j-15] >> 7);
495 }
496
497 uint64 A = intermediates[0];
498 uint64 B = intermediates[1];
499 uint64 C = intermediates[2];
500 uint64 D = intermediates[3];
501 uint64 E = intermediates[4];
502 uint64 F = intermediates[5];
503 uint64 G = intermediates[6];
504 uint64 H = intermediates[7];
505
506 for (int j = 0; j < 80; ++j)
507 {
508 uint64 temp1 = H + constants[j] + words[j];
509 temp1 += rightrot(E, 14) ^ rightrot(E, 18) ^ rightrot(E, 41);
510 temp1 += (E & F) ^ (~E & G);
511 uint64 temp2 = rightrot(A, 28) ^ rightrot(A, 34) ^ rightrot(A, 39);
512 temp2 += (A & B) ^ (A & C) ^ (B & C);
513 H = G;
514 G = F;
515 F = E;
516 E = D + temp1;
517 D = C;
518 C = B;
519 B = A;
520 A = temp1 + temp2;
521 }
522
523 intermediates[0] += A;
524 intermediates[1] += B;
525 intermediates[2] += C;
526 intermediates[3] += D;
527 intermediates[4] += E;
528 intermediates[5] += F;
529 intermediates[6] += G;
530 intermediates[7] += H;
531 }
532
533 delete[] padded;
534
535 int hashlength = 64;
536 if (function == FUNCTION_SHA384)
537 hashlength = 48;
538
539 for (int i = 0; i < hashlength; i += 8)
540 {
541 output.data[i+0] = (intermediates[i/8] >> 56) & 0xFF;
542 output.data[i+1] = (intermediates[i/8] >> 48) & 0xFF;
543 output.data[i+2] = (intermediates[i/8] >> 40) & 0xFF;
544 output.data[i+3] = (intermediates[i/8] >> 32) & 0xFF;
545 output.data[i+4] = (intermediates[i/8] >> 24) & 0xFF;
546 output.data[i+5] = (intermediates[i/8] >> 16) & 0xFF;
547 output.data[i+6] = (intermediates[i/8] >> 8) & 0xFF;
548 output.data[i+7] = (intermediates[i/8] >> 0) & 0xFF;
549 }
550
551 output.size = hashlength;
552 }
553} sha512;
554
555const uint64 SHA512::initial384[8] = {
556 0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939,
557 0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4,
558};
559
560const uint64 SHA512::initial512[8] = {
561 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
562 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
563};
564
565const uint64 SHA512::constants[80] = {
566 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
567 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
568 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
569 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
570 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
571 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
572 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
573 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
574 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
575 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
576 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
577 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
578 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
579 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
580 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
581 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
582 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
583 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
584 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
585 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
586};
587
588} // impl
589}
590
591HashFunction *HashFunction::getHashFunction(Function function)
592{
593 switch(function)
594 {
595 case FUNCTION_MD5:
596 return &impl::md5;
597 case FUNCTION_SHA1:
598 return &impl::sha1;
599 case FUNCTION_SHA224:
600 case FUNCTION_SHA256:
601 return &impl::sha256;
602 case FUNCTION_SHA384:
603 case FUNCTION_SHA512:
604 return &impl::sha512;
605 case FUNCTION_MAX_ENUM:
606 return nullptr;
607 // No default for compiler warnings
608 }
609 return nullptr;
610}
611
612bool HashFunction::getConstant(const char *in, Function &out)
613{
614 return functionNames.find(in, out);
615}
616
617bool HashFunction::getConstant(const Function &in, const char *&out)
618{
619 return functionNames.find(in, out);
620}
621std::vector<std::string> HashFunction::getConstants(Function)
622{
623 return functionNames.getNames();
624}
625
626StringMap<HashFunction::Function, HashFunction::FUNCTION_MAX_ENUM>::Entry HashFunction::functionEntries[] =
627{
628 {"md5", FUNCTION_MD5},
629 {"sha1", FUNCTION_SHA1},
630 {"sha224", FUNCTION_SHA224},
631 {"sha256", FUNCTION_SHA256},
632 {"sha384", FUNCTION_SHA384},
633 {"sha512", FUNCTION_SHA512},
634};
635
636StringMap<HashFunction::Function, HashFunction::FUNCTION_MAX_ENUM> HashFunction::functionNames(HashFunction::functionEntries, sizeof(HashFunction::functionEntries));
637
638} // data
639} // love
640