├── .gitignore
├── README.md
├── sha1.c
├── sha1.h
└── tests
├── sha1_test.c
└── sha1_test.cpp
/.gitignore:
--------------------------------------------------------------------------------
1 | /tests/build
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
SHA-1 Hashing
2 |
3 |
4 |
5 |
6 |
7 |
8 | A simple SHA-1 hashing implementation. Usage:
9 |
10 | unsigned char digest[SHA1_SIZE];
11 | sha1_context ctx;
12 | sha1_init(&ctx);
13 | {
14 | sha1_update(&ctx, src, sz);
15 | }
16 | sha1_finalize(&ctx, digest);
17 |
18 | The above code is the literal implementation of `sha1()` which is a high level helper for hashing
19 | data of a known size:
20 |
21 | unsigned char hash[SHA1_SIZE];
22 | sha1(hash, data, dataSize);
23 |
24 | Use `sha1_format()` to format the digest as a hex string. The capacity of the output buffer needs to
25 | be at least `SHA1_SIZE_FORMATTED` bytes.
26 |
27 | This library does not perform any memory allocations and does not use anything from the standard
28 | library except for `size_t` and `NULL`, both of which are drawn in from stddef.h. No other standard
29 | headers are included.
30 |
31 | There is no need to link to anything with this library. You can use SHA1_IMPLEMENTATION to define
32 | the implementation section, or you can use sha1.c if you prefer a traditional header/source pair.
33 |
34 | This implements both methods defined in RFC 3174. Method 1 will be used by default. If you want to
35 | use Method 2, define `SHA1_USE_RFC_METHOD_2` at compile time.
36 |
37 | #define SHA1_USE_RFC_METHOD_2
38 | #define SHA1_IMPLEMENTATION
39 | #include "sha1.h"
40 |
41 | No effort has been made to optimize this beyond the algorithms described in RGC 3174. If you're
42 | looking for the fastest SHA-1 implementation you'll need to look elsewhere. An optimized
43 | implementation may come later.
--------------------------------------------------------------------------------
/sha1.c:
--------------------------------------------------------------------------------
1 | #define SHA1_IMPLEMENTATION
2 | #include "sha1.h"
3 |
--------------------------------------------------------------------------------
/sha1.h:
--------------------------------------------------------------------------------
1 | /*
2 | SHA-1 hashing. Choice of public domain or MIT-0. See license statements at the end of this file.
3 |
4 | David Reid - mackron@gmail.com
5 | */
6 |
7 | /*
8 | A simple SHA-1 hashing implementation. Usage:
9 |
10 | unsigned char digest[SHA1_SIZE];
11 | sha1_context ctx;
12 | sha1_init(&ctx);
13 | {
14 | sha1_update(&ctx, src, sz);
15 | }
16 | sha1_finalize(&ctx, digest);
17 |
18 | The above code is the literal implementation of `sha1()` which is a high level helper for hashing
19 | data of a known size:
20 |
21 | unsigned char hash[SHA1_SIZE];
22 | sha1(hash, data, dataSize);
23 |
24 | Use `sha1_format()` to format the digest as a hex string. The capacity of the output buffer needs to
25 | be at least `SHA1_SIZE_FORMATTED` bytes.
26 |
27 | This library does not perform any memory allocations and does not use anything from the standard
28 | library except for `size_t` and `NULL`, both of which are drawn in from stddef.h. No other standard
29 | headers are included.
30 |
31 | There is no need to link to anything with this library. You can use SHA1_IMPLEMENTATION to define
32 | the implementation section, or you can use sha1.c if you prefer a traditional header/source pair.
33 |
34 | This implements both methods defined in RFC 3174. Method 1 will be used by default. If you want to
35 | use Method 2, define `SHA1_USE_RFC_METHOD_2` at compile time.
36 |
37 | #define SHA1_USE_RFC_METHOD_2
38 | #define SHA1_IMPLEMENTATION
39 | #include "sha1.h"
40 |
41 | No effort has been made to optimize this beyond the algorithms described in RGC 3174. If you're
42 | looking for the fastest SHA-1 implementation you'll need to look elsewhere. An optimized
43 | implementation may come later.
44 | */
45 | #ifndef sha1_h
46 | #define sha1_h
47 |
48 | #ifdef __cplusplus
49 | extern "C" {
50 | #endif
51 |
52 | #include /* For size_t and NULL. */
53 |
54 | #if defined(_MSC_VER)
55 | typedef unsigned __int64 sha1_uint64;
56 | #else
57 | typedef unsigned long long sha1_uint64;
58 | #endif
59 |
60 | #if !defined(SHA1_API)
61 | #define SHA1_API
62 | #endif
63 |
64 | #define SHA1_SIZE 20
65 | #define SHA1_SIZE_FORMATTED 41
66 |
67 | typedef struct
68 | {
69 | unsigned int h[5];
70 | sha1_uint64 sz;
71 | unsigned char cache[64];
72 | unsigned int cacheLen;
73 | } sha1_context;
74 |
75 | SHA1_API void sha1_init(sha1_context* ctx);
76 | SHA1_API void sha1_update(sha1_context* ctx, const void* src, size_t sz);
77 | SHA1_API void sha1_finalize(sha1_context* ctx, unsigned char* digest);
78 | SHA1_API void sha1(unsigned char* digest, const void* src, size_t sz);
79 | SHA1_API void sha1_format(char* dst, size_t dstCap, const unsigned char* hash);
80 |
81 | #ifdef __cplusplus
82 | }
83 | #endif
84 | #endif /* sha1_h */
85 |
86 | #if defined(SHA1_IMPLEMENTATION)
87 | #ifndef sha1_c
88 | #define sha1_c
89 |
90 | #define SHA1_ALGORITHM_RFC_METHOD_1 1
91 | #define SHA1_ALGORITHM_RFC_METHOD_2 2
92 | #define SHA1_ALGORITHM_DEFAULT SHA1_ALGORITHM_RFC_METHOD_1
93 |
94 | # if defined(SHA1_USE_RFC_METHOD_1)
95 | #define SHA1_ALGORITHM SHA1_ALGORITHM_RFC_METHOD_1
96 | #elif defined(SHA1_USE_RFC_METHOD_2)
97 | #define SHA1_ALGORITHM SHA1_ALGORITHM_RFC_METHOD_2
98 | #else
99 | #define SHA1_ALGORITHM SHA1_ALGORITHM_DEFAULT
100 | #endif
101 |
102 |
103 | static void sha1_zero_memory(void* p, size_t sz)
104 | {
105 | size_t i;
106 | for (i = 0; i < sz; i += 1) {
107 | ((unsigned char*)p)[i] = 0;
108 | }
109 | }
110 |
111 | static void sha1_copy_memory(void* dst, const void* src, size_t sz)
112 | {
113 | size_t i;
114 | for (i = 0; i < sz; i += 1) {
115 | ((unsigned char*)dst)[i] = ((unsigned char*)src)[i];
116 | }
117 | }
118 |
119 |
120 | #define SHA1_ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
121 |
122 | #define SHA1_F00(b, c, d) (((b) & (c)) | ((~(b)) & (d))) /* (B AND C) OR ((NOT B) AND D) */
123 | #define SHA1_F20(b, c, d) ((b) ^ (c) ^ (d)) /* B XOR C XOR D */
124 | #define SHA1_F40(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d))) /* (B AND C) OR (B AND D) OR (C AND D) */
125 | #define SHA1_F60(b, c, d) ((b) ^ (c) ^ (d)) /* B XOR C XOR D */
126 |
127 | /*
128 | This is the main SHA-1 function. Everything is processed in blocks of 64 bytes.
129 | */
130 | static void sha1_update_block(sha1_context* ctx, const unsigned char* src)
131 | {
132 | size_t i;
133 | unsigned int w[80];
134 | unsigned int a, b, c, d, e;
135 | unsigned int temp;
136 |
137 | /* assert(ctx != NULL); */
138 | /* assert(src != NULL); */
139 |
140 | for (i = 0; i < 16; i += 1) {
141 | w[i] = (src[i*4 + 0] << 24);
142 | w[i] |= (src[i*4 + 1] << 16);
143 | w[i] |= (src[i*4 + 2] << 8);
144 | w[i] |= (src[i*4 + 3] << 0);
145 | }
146 |
147 | a = ctx->h[0];
148 | b = ctx->h[1];
149 | c = ctx->h[2];
150 | d = ctx->h[3];
151 | e = ctx->h[4];
152 |
153 | #if SHA1_ALGORITHM == SHA1_ALGORITHM_RFC_METHOD_1
154 | {
155 | for (i = 16; i < 80; i += 1) {
156 | w[i] = SHA1_ROTATE_LEFT((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1);
157 | }
158 |
159 | for (i = 0; i < 20; i += 1) {
160 | temp = SHA1_ROTATE_LEFT(a, 5) + SHA1_F00(b, c, d) + e + w[i] + 0x5A827999;
161 | e = d;
162 | d = c;
163 | c = SHA1_ROTATE_LEFT(b, 30);
164 | b = a;
165 | a = temp;
166 | }
167 |
168 | for (i = 20; i < 40; i += 1) {
169 | temp = SHA1_ROTATE_LEFT(a, 5) + SHA1_F20(b, c, d) + e + w[i] + 0x6ED9EBA1;
170 | e = d;
171 | d = c;
172 | c = SHA1_ROTATE_LEFT(b, 30);
173 | b = a;
174 | a = temp;
175 | }
176 |
177 | for (i = 40; i < 60; i += 1) {
178 | temp = SHA1_ROTATE_LEFT(a, 5) + SHA1_F40(b, c, d) + e + w[i] + 0x8F1BBCDC;
179 | e = d;
180 | d = c;
181 | c = SHA1_ROTATE_LEFT(b, 30);
182 | b = a;
183 | a = temp;
184 | }
185 |
186 | for (i = 60; i < 80; i += 1) {
187 | temp = SHA1_ROTATE_LEFT(a, 5) + SHA1_F60(b, c, d) + e + w[i] + 0xCA62C1D6;
188 | e = d;
189 | d = c;
190 | c = SHA1_ROTATE_LEFT(b, 30);
191 | b = a;
192 | a = temp;
193 | }
194 | }
195 | #endif
196 |
197 | #if SHA1_ALGORITHM == SHA1_ALGORITHM_RFC_METHOD_2
198 | {
199 | unsigned int mask = 0x0000000F;
200 | unsigned int s;
201 |
202 | for (i = 0; i < 16; i += 1) {
203 | s = i & mask;
204 | temp = SHA1_ROTATE_LEFT(a, 5) + SHA1_F00(b, c, d) + e + w[s] + 0x5A827999;
205 | e = d;
206 | d = c;
207 | c = SHA1_ROTATE_LEFT(b, 30);
208 | b = a;
209 | a = temp;
210 | }
211 |
212 | for (i = 16; i < 20; i += 1) {
213 | s = i & mask;
214 | w[s] = SHA1_ROTATE_LEFT(w[(s + 13) & mask] ^ w[(s + 8) & mask] ^ w[(s + 2) & mask] ^ w[s], 1);
215 | temp = SHA1_ROTATE_LEFT(a, 5) + SHA1_F00(b, c, d) + e + w[s] + 0x5A827999;
216 | e = d;
217 | d = c;
218 | c = SHA1_ROTATE_LEFT(b, 30);
219 | b = a;
220 | a = temp;
221 | }
222 |
223 | for (i = 20; i < 40; i += 1) {
224 | s = i & mask;
225 | w[s] = SHA1_ROTATE_LEFT(w[(s + 13) & mask] ^ w[(s + 8) & mask] ^ w[(s + 2) & mask] ^ w[s], 1);
226 | temp = SHA1_ROTATE_LEFT(a, 5) + SHA1_F20(b, c, d) + e + w[s] + 0x6ED9EBA1;
227 | e = d;
228 | d = c;
229 | c = SHA1_ROTATE_LEFT(b, 30);
230 | b = a;
231 | a = temp;
232 | }
233 |
234 | for (i = 40; i < 60; i += 1) {
235 | s = i & mask;
236 | w[s] = SHA1_ROTATE_LEFT(w[(s + 13) & mask] ^ w[(s + 8) & mask] ^ w[(s + 2) & mask] ^ w[s], 1);
237 | temp = SHA1_ROTATE_LEFT(a, 5) + SHA1_F40(b, c, d) + e + w[s] + 0x8F1BBCDC;
238 | e = d;
239 | d = c;
240 | c = SHA1_ROTATE_LEFT(b, 30);
241 | b = a;
242 | a = temp;
243 | }
244 |
245 | for (i = 60; i < 80; i += 1) {
246 | s = i & mask;
247 | w[s] = SHA1_ROTATE_LEFT(w[(s + 13) & mask] ^ w[(s + 8) & mask] ^ w[(s + 2) & mask] ^ w[s], 1);
248 | temp = SHA1_ROTATE_LEFT(a, 5) + SHA1_F60(b, c, d) + e + w[s] + 0xCA62C1D6;
249 | e = d;
250 | d = c;
251 | c = SHA1_ROTATE_LEFT(b, 30);
252 | b = a;
253 | a = temp;
254 | }
255 | }
256 | #endif
257 |
258 | ctx->h[0] += a;
259 | ctx->h[1] += b;
260 | ctx->h[2] += c;
261 | ctx->h[3] += d;
262 | ctx->h[4] += e;
263 |
264 | /* We'll only ever be calling this if the context's cache is full. At this point the cache will also be empty. */
265 | ctx->cacheLen = 0;
266 | }
267 |
268 | SHA1_API void sha1_init(sha1_context* ctx)
269 | {
270 | if (ctx == NULL) {
271 | return;
272 | }
273 |
274 | sha1_zero_memory(ctx, sizeof(*ctx));
275 |
276 | ctx->h[0] = 0x67452301;
277 | ctx->h[1] = 0xEFCDAB89;
278 | ctx->h[2] = 0x98BADCFE;
279 | ctx->h[3] = 0x10325476;
280 | ctx->h[4] = 0xC3D2E1F0;
281 | }
282 |
283 | SHA1_API void sha1_update(sha1_context* ctx, const void* src, size_t sz)
284 | {
285 | const unsigned char* bytes = (const unsigned char*)src;
286 | size_t totalBytesProcessed = 0;
287 |
288 | if (ctx == NULL || (src == NULL && sz > 0)) {
289 | return;
290 | }
291 |
292 | /* Keep processing until all data has been exhausted. */
293 | while (totalBytesProcessed < sz) {
294 | /* Optimization. Bypass the cache if there's nothing in it and the number of bytes remaining to process is larger than 64. */
295 | size_t bytesRemainingToProcess = sz - totalBytesProcessed;
296 | if (ctx->cacheLen == 0 && bytesRemainingToProcess > sizeof(ctx->cache)) {
297 | /* Fast path. Bypass the cache and just process directly. */
298 | sha1_update_block(ctx, bytes + totalBytesProcessed);
299 | totalBytesProcessed += sizeof(ctx->cache);
300 | } else {
301 | /* Slow path. Need to store in the cache. */
302 | size_t cacheRemaining = sizeof(ctx->cache) - ctx->cacheLen;
303 | if (cacheRemaining > 0) {
304 | /* There's still some room left in the cache. Write as much data to it as we can. */
305 | size_t bytesToProcess = bytesRemainingToProcess;
306 | if (bytesToProcess > cacheRemaining) {
307 | bytesToProcess = cacheRemaining;
308 | }
309 |
310 | sha1_copy_memory(ctx->cache + ctx->cacheLen, bytes + totalBytesProcessed, bytesToProcess);
311 | ctx->cacheLen += (unsigned int)bytesToProcess; /* Safe cast. bytesToProcess will always be <= sizeof(ctx->cache) which is 64. */
312 | totalBytesProcessed += bytesToProcess;
313 |
314 | /* Update the number of bytes remaining in the cache so we can use it later. */
315 | cacheRemaining = sizeof(ctx->cache) - ctx->cacheLen;
316 | }
317 |
318 | /* If the cache is full, get it processed. */
319 | if (cacheRemaining == 0) {
320 | sha1_update_block(ctx, ctx->cache);
321 | }
322 | }
323 | }
324 |
325 | ctx->sz += sz;
326 | }
327 |
328 | SHA1_API void sha1_finalize(sha1_context* ctx, unsigned char* digest)
329 | {
330 | size_t cacheRemaining;
331 | unsigned int szLo;
332 | unsigned int szHi;
333 |
334 | if (digest == NULL) {
335 | return;
336 | }
337 |
338 | if (ctx == NULL) {
339 | sha1_zero_memory(digest, SHA1_SIZE);
340 | return;
341 | }
342 |
343 | /*
344 | Padding must be applied. First thing to do is clear the cache if there's no room for at least
345 | one byte. This should never happen, but leaving this logic here for safety.
346 | */
347 | cacheRemaining = sizeof(ctx->cache) - ctx->cacheLen;
348 | if (cacheRemaining == 0) {
349 | sha1_update_block(ctx, ctx->cache);
350 | }
351 |
352 | /* Now we need to write a byte with the most significant bit set (0x80). */
353 | ctx->cache[ctx->cacheLen] = 0x80;
354 | ctx->cacheLen += 1;
355 |
356 | /* If there isn't enough room for 8 bytes we need to padd with zeroes and get the block processed. */
357 | cacheRemaining = sizeof(ctx->cache) - ctx->cacheLen;
358 | if (cacheRemaining < 8) {
359 | sha1_zero_memory(ctx->cache + ctx->cacheLen, cacheRemaining);
360 | sha1_update_block(ctx, ctx->cache);
361 | cacheRemaining = sizeof(ctx->cache);
362 | }
363 |
364 | /* Now we need to fill the buffer with zeros until we've filled 56 bytes (8 bytes left over for the length). */
365 | sha1_zero_memory(ctx->cache + ctx->cacheLen, cacheRemaining - 8);
366 |
367 | szLo = (unsigned int)(((ctx->sz >> 0) & 0xFFFFFFFF) << 3);
368 | szHi = (unsigned int)(((ctx->sz >> 32) & 0xFFFFFFFF) << 3);
369 | ctx->cache[56] = (unsigned char)((szHi >> 24) & 0xFF);
370 | ctx->cache[57] = (unsigned char)((szHi >> 16) & 0xFF);
371 | ctx->cache[58] = (unsigned char)((szHi >> 8) & 0xFF);
372 | ctx->cache[59] = (unsigned char)((szHi >> 0) & 0xFF);
373 | ctx->cache[60] = (unsigned char)((szLo >> 24) & 0xFF);
374 | ctx->cache[61] = (unsigned char)((szLo >> 16) & 0xFF);
375 | ctx->cache[62] = (unsigned char)((szLo >> 8) & 0xFF);
376 | ctx->cache[63] = (unsigned char)((szLo >> 0) & 0xFF);
377 | sha1_update_block(ctx, ctx->cache);
378 |
379 | /* Now write out the digest. */
380 | digest[ 0] = (unsigned char)(ctx->h[0] >> 24); digest[ 1] = (unsigned char)(ctx->h[0] >> 16); digest[ 2] = (unsigned char)(ctx->h[0] >> 8); digest[ 3] = (unsigned char)(ctx->h[0] >> 0);
381 | digest[ 4] = (unsigned char)(ctx->h[1] >> 24); digest[ 5] = (unsigned char)(ctx->h[1] >> 16); digest[ 6] = (unsigned char)(ctx->h[1] >> 8); digest[ 7] = (unsigned char)(ctx->h[1] >> 0);
382 | digest[ 8] = (unsigned char)(ctx->h[2] >> 24); digest[ 9] = (unsigned char)(ctx->h[2] >> 16); digest[10] = (unsigned char)(ctx->h[2] >> 8); digest[11] = (unsigned char)(ctx->h[2] >> 0);
383 | digest[12] = (unsigned char)(ctx->h[3] >> 24); digest[13] = (unsigned char)(ctx->h[3] >> 16); digest[14] = (unsigned char)(ctx->h[3] >> 8); digest[15] = (unsigned char)(ctx->h[3] >> 0);
384 | digest[16] = (unsigned char)(ctx->h[4] >> 24); digest[17] = (unsigned char)(ctx->h[4] >> 16); digest[18] = (unsigned char)(ctx->h[4] >> 8); digest[19] = (unsigned char)(ctx->h[4] >> 0);
385 | }
386 |
387 | SHA1_API void sha1(unsigned char* digest, const void* src, size_t sz)
388 | {
389 | sha1_context ctx;
390 | sha1_init(&ctx);
391 | {
392 | sha1_update(&ctx, src, sz);
393 | }
394 | sha1_finalize(&ctx, digest);
395 | }
396 |
397 |
398 | static void sha1_format_byte(char* dst, unsigned char byte)
399 | {
400 | const char* hex = "0123456789abcdef";
401 | dst[0] = hex[(byte & 0xF0) >> 4];
402 | dst[1] = hex[(byte & 0x0F) ];
403 | }
404 |
405 | SHA1_API void sha1_format(char* dst, size_t dstCap, const unsigned char* hash)
406 | {
407 | size_t i;
408 |
409 | if (dst == NULL) {
410 | return;
411 | }
412 |
413 | if (dstCap < SHA1_SIZE_FORMATTED) {
414 | if (dstCap > 0) {
415 | dst[0] = '\0';
416 | }
417 |
418 | return;
419 | }
420 |
421 | for (i = 0; i < SHA1_SIZE; i += 1) {
422 | sha1_format_byte(dst + (i*2), hash[i]);
423 | }
424 |
425 | /* Always null terminate. */
426 | dst[SHA1_SIZE_FORMATTED-1] = '\0';
427 | }
428 | #endif /* sha1_c */
429 | #endif /* SHA1_IMPLEMENTATION */
430 |
431 | /*
432 | This software is available as a choice of the following licenses. Choose
433 | whichever you prefer.
434 |
435 | ===============================================================================
436 | ALTERNATIVE 1 - Public Domain (www.unlicense.org)
437 | ===============================================================================
438 | This is free and unencumbered software released into the public domain.
439 |
440 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
441 | software, either in source code form or as a compiled binary, for any purpose,
442 | commercial or non-commercial, and by any means.
443 |
444 | In jurisdictions that recognize copyright laws, the author or authors of this
445 | software dedicate any and all copyright interest in the software to the public
446 | domain. We make this dedication for the benefit of the public at large and to
447 | the detriment of our heirs and successors. We intend this dedication to be an
448 | overt act of relinquishment in perpetuity of all present and future rights to
449 | this software under copyright law.
450 |
451 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
452 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
453 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
454 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
455 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
456 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
457 |
458 | For more information, please refer to
459 |
460 | ===============================================================================
461 | ALTERNATIVE 2 - MIT No Attribution
462 | ===============================================================================
463 | Copyright 2022 David Reid
464 |
465 | Permission is hereby granted, free of charge, to any person obtaining a copy of
466 | this software and associated documentation files (the "Software"), to deal in
467 | the Software without restriction, including without limitation the rights to
468 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
469 | of the Software, and to permit persons to whom the Software is furnished to do
470 | so.
471 |
472 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
473 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
474 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
475 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
476 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
477 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
478 | SOFTWARE.
479 | */
480 |
--------------------------------------------------------------------------------
/tests/sha1_test.c:
--------------------------------------------------------------------------------
1 | #define SHA1_IMPLEMENTATION
2 | #include "../sha1.h"
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | int do_test(size_t iterationCount, const char* input, const char* expected)
9 | {
10 | unsigned char hash[SHA1_SIZE];
11 | char hashStr[SHA1_SIZE_FORMATTED];
12 | sha1_context ctx;
13 |
14 | sha1_init(&ctx);
15 | {
16 | size_t i;
17 | size_t inputSize = strlen(input);
18 | for (i = 0; i < iterationCount; i += 1) {
19 | sha1_update(&ctx, input, inputSize);
20 | }
21 | }
22 | sha1_finalize(&ctx, hash);
23 |
24 | /* Check and compare results. */
25 | sha1_format(hashStr, sizeof(hashStr), hash);
26 |
27 | printf("%s = %s : ", input, hashStr);
28 | if (strcmp(hashStr, expected) == 0) {
29 | printf("success\n");
30 | return 0;
31 | } else {
32 | printf("failed\n");
33 | return -1;
34 | }
35 | }
36 |
37 | int main(int argc, char** argv)
38 | {
39 | (void)argc;
40 | (void)argv;
41 |
42 | do_test(1, "", "da39a3ee5e6b4b0d3255bfef95601890afd80709");
43 | do_test(1, "a", "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8");
44 | do_test(1, "abc", "a9993e364706816aba3e25717850c26c9cd0d89d");
45 | do_test(1, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "84983e441c3bd26ebaae4aa1f95129e5e54670f1");
46 | do_test(1000000, "a", "34aa973cd4c4daa4f61eeb2bdbad27316534016f");
47 | do_test(1, "0123456701234567012345670123456701234567012345670123456701234567", "e0c094e867ef46c350ef54a7f59dd60bed92ae83");
48 |
49 | return 0;
50 | }
51 |
--------------------------------------------------------------------------------
/tests/sha1_test.cpp:
--------------------------------------------------------------------------------
1 | #include "sha1_test.c"
2 |
--------------------------------------------------------------------------------