2 * Tweaked in various ways for Google/Android:
3 * - Changed from .cpp to .c.
4 * - Made argument to SHA1Update a const pointer, and enabled
5 * SHA1HANDSOFF. This incurs a speed penalty but prevents us from
7 * - Include <endian.h> to get endian info.
8 * - Split a small piece into a header file.
12 sha1sum: inspired by md5sum.
15 By Steve Reid <steve@edmweb.com>
20 By James H. Brown <jbrown@burgoyne.com>
21 Still 100% Public Domain
24 Routine SHA1Update changed from
25 void SHA1Update(SHA1_CTX* context, unsigned char* data,
28 void SHA1Update(SHA1_CTX* context, unsigned char* data,
31 The 'len' parameter was declared an int which works fine on 32
32 bit machines. However, on 16 bit machines an int is too small
33 for the shifts being done against it. This caused the hash
34 function to generate incorrect values if len was greater than
35 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
37 Since the file IO in main() reads 16K at a time, any file 8K or
38 larger would be guaranteed to generate the wrong hash (e.g.
39 Test Vector #3, a million "a"s).
41 I also changed the declaration of variables i & j in SHA1Update
42 to unsigned long from unsigned int for the same reason.
44 These changes should make no difference to any 32 bit
45 implementations since an int and a long are the same size in
49 I also corrected a few compiler warnings generated by Borland
51 1. Added #include <process.h> for exit() prototype
52 2. Removed unused variable 'j' in SHA1Final
53 3. Changed exit(0) to return(0) at end of main.
55 ALL changes I made can be located by searching for comments
59 Modified 13 August 2000
60 By Michael Paul Johnson <mpj@cryptography.org>
61 Still 100% Public Domain
63 Changed command line syntax, added feature to automatically
64 check files against their previous SHA-1 check values, kind of
65 like md5sum does. Added functions hexval, verifyfile,
66 and sha1file. Rewrote main().
69 Test Vectors (from FIPS PUB 180-1)
71 A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
72 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
73 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
74 A million repetitions of "a"
75 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
78 #define SHA1HANDSOFF /*Copies data before messing with it.*/
80 /*#define CMDLINE * include main() and file processing */
89 #include <process.h> /* prototype for exit() - JHB
90 needed for Win32, but chokes Linux - MPJ */
91 #define X_LITTLE_ENDIAN /* This should be #define'd if true.*/
95 //# include <endian.h>
97 #include "DexFile.h" // want common byte ordering def
99 # if __BYTE_ORDER == __LITTLE_ENDIAN
100 # define X_LITTLE_ENDIAN
105 #define LINESIZE 2048
107 static void SHA1Transform(unsigned long state[5],
108 const unsigned char buffer[64]);
110 #define rol(value,bits) \
111 (((value)<<(bits))|((value)>>(32-(bits))))
113 /* blk0() and blk() perform the initial expand. */
114 /* I got the idea of expanding during the round function from
116 #ifdef X_LITTLE_ENDIAN
117 #define blk0(i) (block->l[i]=(rol(block->l[i],24)&0xFF00FF00) \
118 |(rol(block->l[i],8)&0x00FF00FF))
120 #define blk0(i) block->l[i]
122 #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
123 ^block->l[(i+2)&15]^block->l[i&15],1))
125 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
126 #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
127 #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
128 #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
129 #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
130 #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
133 /* Hash a single 512-bit block. This is the core of the algorithm. */
135 static void SHA1Transform(unsigned long state[5],
136 const unsigned char buffer[64])
138 unsigned long a, b, c, d, e;
145 static unsigned char workspace[64];
146 block = (CHAR64LONG16*)workspace;
147 memcpy(block, buffer, 64);
149 block = (CHAR64LONG16*)buffer;
151 /* Copy context->state[] to working vars */
157 /* 4 rounds of 20 operations each. Loop unrolled. */
158 R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2);
159 R0(c,d,e,a,b, 3); R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5);
160 R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); R0(c,d,e,a,b, 8);
161 R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
162 R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14);
163 R0(a,b,c,d,e,15); R1(e,a,b,c,d,16); R1(d,e,a,b,c,17);
164 R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); R2(a,b,c,d,e,20);
165 R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
166 R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26);
167 R2(d,e,a,b,c,27); R2(c,d,e,a,b,28); R2(b,c,d,e,a,29);
168 R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); R2(d,e,a,b,c,32);
169 R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
170 R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38);
171 R2(b,c,d,e,a,39); R3(a,b,c,d,e,40); R3(e,a,b,c,d,41);
172 R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); R3(b,c,d,e,a,44);
173 R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
174 R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50);
175 R3(e,a,b,c,d,51); R3(d,e,a,b,c,52); R3(c,d,e,a,b,53);
176 R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); R3(e,a,b,c,d,56);
177 R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
178 R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62);
179 R4(c,d,e,a,b,63); R4(b,c,d,e,a,64); R4(a,b,c,d,e,65);
180 R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); R4(c,d,e,a,b,68);
181 R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
182 R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74);
183 R4(a,b,c,d,e,75); R4(e,a,b,c,d,76); R4(d,e,a,b,c,77);
184 R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
186 /* Add the working vars back into context.state[] */
193 /* a = b = c = d = e = 0; Nice try, but the compiler
194 optimizes this out, anyway, and it produces an annoying
199 /* SHA1Init - Initialize new context */
201 void SHA1Init(SHA1_CTX* context)
203 /* SHA1 initialization constants */
204 context->state[0] = 0x67452301;
205 context->state[1] = 0xEFCDAB89;
206 context->state[2] = 0x98BADCFE;
207 context->state[3] = 0x10325476;
208 context->state[4] = 0xC3D2E1F0;
209 context->count[0] = context->count[1] = 0;
213 /* Run your data through this. */
215 void SHA1Update(SHA1_CTX* context, const unsigned char* data,
216 unsigned long len) /* JHB */
218 unsigned long i, j; /* JHB */
220 j = (context->count[0] >> 3) & 63;
221 if ((context->count[0] += len << 3) < (len << 3))
223 context->count[1] += (len >> 29);
226 memcpy(&context->buffer[j], data, (i = 64-j));
227 SHA1Transform(context->state, context->buffer);
228 for ( ; i + 63 < len; i += 64) {
229 SHA1Transform(context->state, &data[i]);
235 memcpy(&context->buffer[j], &data[i], len - i);
239 /* Add padding and return the message digest. */
241 void SHA1Final(unsigned char digest[HASHSIZE], SHA1_CTX*
244 unsigned long i; /* JHB */
245 unsigned char finalcount[8];
247 for (i = 0; i < 8; i++)
249 finalcount[i] = (unsigned char)((context->count[(i>=4?
250 0:1)]>>((3-(i&3))*8))&255);
251 /* Endian independent */
253 SHA1Update(context, (unsigned char *)"\200", 1);
254 while ((context->count[0] & 504) != 448) {
255 SHA1Update(context, (unsigned char *)"\0", 1);
257 SHA1Update(context, finalcount, 8);
258 /* Should cause a SHA1Transform() */
259 for (i = 0; i < HASHSIZE; i++) {
260 digest[i] = (unsigned char)
261 ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
264 memset(context->buffer, 0, 64);
265 memset(context->state, 0, HASHSIZE);
266 memset(context->count, 0, 8);
267 memset(&finalcount, 0, 8);
269 /* make SHA1Transform overwrite it's own static vars */
270 SHA1Transform(context->state, context->buffer);
278 /* sha1file computes the SHA-1 hash of the named file and puts
279 it in the 20-byte array digest. If fname is NULL, stdin is
282 void sha1file(char *fname, unsigned char* digest)
286 unsigned char buffer[16384];
291 f = fopen(fname, "rb");
294 fprintf(stderr, "Can't open %s\n", fname);
295 memset(digest, 0, HASHSIZE);
306 bytesread = fread(buffer, 1, 16384, f);
307 SHA1Update(&context, buffer, bytesread);
309 SHA1Final(digest, &context);
314 /* Convert ASCII hexidecimal digit to 4-bit value. */
315 unsigned char hexval(char c)
327 /* Verify a file created with sha1sum by redirecting output
329 int verifyfile(char *fname)
333 unsigned char digest[HASHSIZE];
334 unsigned char expected_digest[HASHSIZE];
336 char checkline[LINESIZE];
340 checkfile = fopen(fname, "rt");
343 fprintf(stderr, "Can't open %s\n", fname);
348 s = fgets(checkline, LINESIZE, checkfile);
351 if ((strlen(checkline)>26)&&
352 1 /*(!strncmp(checkline,"SHA1=", 5))*/)
354 /* Overwrite newline. */
355 checkline[strlen(checkline)-1]=0;
358 /* Read expected check value. */
359 for (k=0, j=5; k < HASHSIZE; k++)
361 expected_digest[k]=hexval(checkline[j++]);
362 expected_digest[k]=(expected_digest[k]<<4)
363 +hexval(checkline[j++]);
366 /* Compute fingerprints */
370 /* Compare fingerprints */
372 for (k=0; k<HASHSIZE; k++)
377 fprintf(stderr, "FAILED: %s\n"
379 for (k=0; k<HASHSIZE; k++)
380 fprintf(stderr, "%02X",
382 fprintf(stderr,"\n FOUND: ");
383 for (k=0; k<HASHSIZE; k++)
384 fprintf(stderr, "%02X", digest[k]);
385 fprintf(stderr, "\n");
389 printf("OK: %s\n", s);
399 void syntax(char *progname)
402 "%s [-c|-h][-q] file name[s]\n"
403 " -c = check files against previous check values\n"
404 " -g = generate SHA-1 check values (default action)\n"
405 " -h = display this help\n"
407 "sha1sum test.txt > check.txt\n"
408 "generates check value for test.txt in check.txt, and\n"
409 "sha1sum -c check.txt\n"
410 "checks test.txt against the check value in check.txt\n",
416 /**********************************************************/
418 int main(int argc, char** argv)
423 unsigned char digest[HASHSIZE];
424 unsigned char expected_digest[HASHSIZE];
426 char checkline[LINESIZE];
432 char drive[MAXDRIVE];
439 for (i = 1; i < argc; i++)
441 if (argv[i][0] == '-')
459 for (i=1; i<argc; i++)
461 if (argv[i][0] != '-')
464 fnsplit(argv[i], drive, dir, name, ext);
465 done = findfirst(argv[i], &f, FA_RDONLY |
466 FA_HIDDEN|FA_SYSTEM|FA_ARCH);
469 sprintf(path, "%s%s%s", drive, dir, f.ff_name);
476 { /* Check fingerprint file. */
477 found |= verifyfile(s);
480 { /* Generate fingerprints & write to
484 for (j=0; j<HASHSIZE; j++)
485 printf("%02x", digest[j]);
502 "No SHA1 lines found in %s\n",
507 fprintf(stderr, "No files checked.\n");