blob: 03894d6edb07a7c88ba6a7dc1f7a82c7d4b5b515 [file] [log] [blame]
tanjent@gmail.comad4b3632010-11-05 01:20:58 +00001/*
2SHA-1 in C
3By Steve Reid <sreid@sea-to-sky.net>
4100% Public Domain
5
6-----------------
7Modified 7/98
8By James H. Brown <jbrown@burgoyne.com>
9Still 100% Public Domain
10
11Corrected a problem which generated improper hash values on 16 bit machines
12Routine SHA1Update changed from
13 void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
14len)
15to
16 void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
17long len)
18
19The 'len' parameter was declared an int which works fine on 32 bit machines.
20However, on 16 bit machines an int is too small for the shifts being done
21against
22it. This caused the hash function to generate incorrect values if len was
23greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
24
25Since the file IO in main() reads 16K at a time, any file 8K or larger would
26be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
27"a"s).
28
29I also changed the declaration of variables i & j in SHA1Update to
30unsigned long from unsigned int for the same reason.
31
32These changes should make no difference to any 32 bit implementations since
33an
34int and a long are the same size in those environments.
35
36--
37I also corrected a few compiler warnings generated by Borland C.
381. Added #include <process.h> for exit() prototype
392. Removed unused variable 'j' in SHA1Final
403. Changed exit(0) to return(0) at end of main.
41
42ALL changes I made can be located by searching for comments containing 'JHB'
43-----------------
44Modified 8/98
45By Steve Reid <sreid@sea-to-sky.net>
46Still 100% public domain
47
481- Removed #include <process.h> and used return() instead of exit()
492- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
503- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
51
52-----------------
53Modified 4/01
54By Saul Kravitz <Saul.Kravitz@celera.com>
55Still 100% PD
56Modified to run on Compaq Alpha hardware.
57
58-----------------
59Modified 07/2002
60By Ralph Giles <giles@ghostscript.com>
61Still 100% public domain
62modified for use with stdint types, autoconf
63code cleanup, removed attribution comments
64switched SHA1Final() argument order for consistency
65use SHA1_ prefix for public api
66move public api to sha1.h
67*/
68
69/*
70Test Vectors (from FIPS PUB 180-1)
71"abc"
72 A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
73"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
74 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
75A million repetitions of "a"
76 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
77*/
78
79#include <stdio.h>
80#include <string.h>
81#include <stdlib.h>
82
83#include "sha1.h"
84
85#pragma warning(disable : 4267)
86#pragma warning(disable : 4996)
87#pragma warning(disable : 4100)
88
89void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]);
90
91#define rol _rotl
92
93/* blk0() and blk() perform the initial expand. */
94/* I got the idea of expanding during the round function from SSLeay */
95/* FIXME: can we do this in an endian-proof way? */
96
97#ifdef WORDS_BIGENDIAN
98#define blk0(i) block->l[i]
99#else
100#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) | (rol(block->l[i],8)&0x00FF00FF))
101#endif
102#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] ^ block->l[(i+2)&15]^block->l[i&15],1))
103
104/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
105#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
106#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
107#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
108#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
109#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
110
111
112/* Hash a single 512-bit block. This is the core of the algorithm. */
113void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
114{
115 uint32_t a, b, c, d, e;
116 typedef union {
117 uint8_t c[64];
118 uint32_t l[16];
119 } CHAR64LONG16;
120 CHAR64LONG16* block;
121
122 block = (CHAR64LONG16*)buffer;
123
124 /* Copy context->state[] to working vars */
125 a = state[0];
126 b = state[1];
127 c = state[2];
128 d = state[3];
129 e = state[4];
130
131 /* 4 rounds of 20 operations each. Loop unrolled. */
132 R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
133 R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
134 R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
135 R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
136 R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
137 R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
138 R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
139 R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
140 R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
141 R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
142 R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
143 R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
144 R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
145 R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
146 R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
147 R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
148 R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
149 R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
150 R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
151 R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
152
153 /* Add the working vars back into context.state[] */
154 state[0] += a;
155 state[1] += b;
156 state[2] += c;
157 state[3] += d;
158 state[4] += e;
159
160 /* Wipe variables */
161 a = b = c = d = e = 0;
162}
163
164
165/* SHA1Init - Initialize new context */
166void SHA1_Init(SHA1_CTX* context)
167{
168 /* SHA1 initialization constants */
169 context->state[0] = 0x67452301;
170 context->state[1] = 0xEFCDAB89;
171 context->state[2] = 0x98BADCFE;
172 context->state[3] = 0x10325476;
173 context->state[4] = 0xC3D2E1F0;
174 context->count[0] = 0;
175 context->count[1] = 0;
176}
177
178
179/* Run your data through this. */
180void SHA1_Update(SHA1_CTX* context, const uint8_t* data, const size_t len)
181{
182 size_t i, j;
183
184 j = (context->count[0] >> 3) & 63;
185 if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
186
187 context->count[1] += (len >> 29);
188
189 if ((j + len) > 63)
190 {
191 memcpy(&context->buffer[j], data, (i = 64-j));
192 SHA1_Transform(context->state, context->buffer);
193
194 for ( ; i + 63 < len; i += 64)
195 {
196 SHA1_Transform(context->state, data + i);
197 }
198
199 j = 0;
200 }
201 else i = 0;
202 memcpy(&context->buffer[j], &data[i], len - i);
203}
204
205
206/* Add padding and return the message digest. */
207void SHA1_Final(SHA1_CTX* context, uint8_t digest[SHA1_DIGEST_SIZE])
208{
209 uint32_t i;
210 uint8_t finalcount[8];
211
212 for (i = 0; i < 8; i++) {
213 finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
214 >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
215 }
216 SHA1_Update(context, (uint8_t *)"\200", 1);
217 while ((context->count[0] & 504) != 448) {
218 SHA1_Update(context, (uint8_t *)"\0", 1);
219 }
220 SHA1_Update(context, finalcount, 8); /* Should cause a SHA1_Transform() */
221 for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
222 digest[i] = (uint8_t)
223 ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
224 }
225
226 /* Wipe variables */
227 i = 0;
228 memset(context->buffer, 0, 64);
229 memset(context->state, 0, 20);
230 memset(context->count, 0, 8);
231 memset(finalcount, 0, 8); /* SWR */
232}
233
234//-----------------------------------------------------------------------------
235
236void sha1_32a ( const void * key, int len, uint32_t seed, void * out )
237{
238 SHA1_CTX context;
239
240 uint8_t digest[20];
241
242 SHA1_Init(&context);
243 SHA1_Update(&context, (uint8_t*)key, len);
244 SHA1_Final(&context, digest);
245
246 memcpy(out,&digest[0],4);
247}
248
249//-----------------------------------------------------------------------------
250// self test
251
252//#define TEST
253
254#ifdef TEST
255
256static char *test_data[] = {
257 "abc",
258 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
259 "A million repetitions of 'a'"};
260static char *test_results[] = {
261 "A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D",
262 "84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1",
263 "34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F"};
264
265
266void digest_to_hex(const uint8_t digest[SHA1_DIGEST_SIZE], char *output)
267{
268 int i,j;
269 char *c = output;
270
271 for (i = 0; i < SHA1_DIGEST_SIZE/4; i++) {
272 for (j = 0; j < 4; j++) {
273 sprintf(c,"%02X", digest[i*4+j]);
274 c += 2;
275 }
276 sprintf(c, " ");
277 c += 1;
278 }
279 *(c - 1) = '\0';
280}
281
282int main(int argc, char** argv)
283{
284 int k;
285 SHA1_CTX context;
286 uint8_t digest[20];
287 char output[80];
288
289 fprintf(stdout, "verifying SHA-1 implementation... ");
290
291 for (k = 0; k < 2; k++){
292 SHA1_Init(&context);
293 SHA1_Update(&context, (uint8_t*)test_data[k], strlen(test_data[k]));
294 SHA1_Final(&context, digest);
295 digest_to_hex(digest, output);
296
297 if (strcmp(output, test_results[k])) {
298 fprintf(stdout, "FAIL\n");
299 fprintf(stderr,"* hash of \"%s\" incorrect:\n", test_data[k]);
300 fprintf(stderr,"\t%s returned\n", output);
301 fprintf(stderr,"\t%s is correct\n", test_results[k]);
302 return (1);
303 }
304 }
305 /* million 'a' vector we feed separately */
306 SHA1_Init(&context);
307 for (k = 0; k < 1000000; k++)
308 SHA1_Update(&context, (uint8_t*)"a", 1);
309 SHA1_Final(&context, digest);
310 digest_to_hex(digest, output);
311 if (strcmp(output, test_results[2])) {
312 fprintf(stdout, "FAIL\n");
313 fprintf(stderr,"* hash of \"%s\" incorrect:\n", test_data[2]);
314 fprintf(stderr,"\t%s returned\n", output);
315 fprintf(stderr,"\t%s is correct\n", test_results[2]);
316 return (1);
317 }
318
319 /* success */
320 fprintf(stdout, "ok\n");
321 return(0);
322}
323#endif /* TEST */