/****************************************************************************** * SHA1 ******************************************************************************/ /* SHA-1 hashing routines. * see RFC3174 for the SHA-1 algorithm. * * Jon Mayo - PUBLIC DOMAIN - June 24, 2010 * */ #include #include #include /** * size of a SHA-1 digest in bytes. SHA-1 is 160-bit. */ #define SHA1_DIGEST_LENGTH 20 unsigned char *sha1(const void *data, size_t len, unsigned char md[SHA1_DIGEST_LENGTH]); /* rotate v left by b bits, truncate to 32-bits. */ #define ROL32(v, b) ((((v)<<(b))|((v)>>(32-(b))))&0xfffffffful) /** * quick calculation of SHA1 on buffer data. * data - pointer. * len - length of data. * md - cannot be NULL. * return md. */ unsigned char *sha1(const void *data, size_t len, unsigned char md[SHA1_DIGEST_LENGTH]) { uint_least32_t h[5] = { 0x67452301lu, 0xefcdab89lu, 0x98badcfelu, 0x10325476lu, 0xc3d2e1f0lu }; uint_least32_t v[5]; /* called a, b, c, d, e in documentation. */ uint_least64_t cnt=0; /* total so far in bits. */ uint_least32_t chunk[80]; /* 0..15 is 512-bit of data. 16..79 is copies. */ unsigned i, tail_fl=0, length_fl=0; while(tail_fl || len) { /* fill in chunk[0..15] using data[+0..+63] */ for(i=0;i<512/8;i++) { uint_least32_t n=chunk[i/4], d=0; if(len>i) { d=*(uint8_t*)data; data=(uint8_t*)data+1; cnt+=8; } else if(!tail_fl && i==len) { d=0x80; tail_fl=1; /* tail_fl is used when end of data is reached. */ } else if(tail_fl && i>=448/8) { if(i==448/8) length_fl=1; /* length_fl is set when filling in length data. */ if(length_fl) { d=(cnt>>(64-(i-448/8+1)*8))&255; if(i==512/8-1) tail_fl=0; /* finished with length. */ } } // printf("i=%-2d d=%02x len=%d\n", i, d, len); switch(i%4) { case 0: n=(n&0xffffff)|(d<<24); break; case 1: n=(n&0xff00ffff)|(d<<16); break; case 2: n=(n&0xffff00ff)|(d<<8); break; case 3: n=(n&0xffffff00)|d; break; } chunk[i/4]=n; } if(len>512/8) { len-=512/8; } else { len=0; } /* transform chunk */ for(i=16;i<80;i++) { chunk[i]=chunk[i-3]^chunk[i-8]^chunk[i-14]^chunk[i-16]; chunk[i]=ROL32(chunk[i], 1); /* rotate left 1 */ } for(i=0;i<5;i++) v[i]=h[i]; /* set a-e to h0..4 */ for(i=0;i<80;i++) { uint_least32_t f, k, tmp; if(i<20) { f=(v[1]&v[2])|(~v[1]&v[3]); /* f=v[3]^(v[1]&(v[2]^v[3])); */ k=0x5a827999; } else if(i<40) { f=v[1]^v[2]^v[3]; /* f=(v[1]&v[2])^((~v[1])&v[3]) */ k=0x6ed9eba1; } else if(i<60) { f=(v[1]&v[2])|(v[1]&v[3])|(v[2]&v[3]); /* f=(v[1]&v[2])+((~v[1])&v[3]); */ k=0x8f1bbcdc; } else { f=v[1]^v[2]^v[3]; k=0xca62c1d6; } tmp=ROL32(v[0], 5)+f+v[4]+k+chunk[i]; /* (a ROL 5) + f + e + k + w[i] */ v[4]=v[3]; /* e = d */ v[3]=v[2]; /* d = c */ v[2]=ROL32(v[1], 30); /* c = b ROL 30 */ v[1]=v[0]; /* b = a */ v[0]=tmp; /* a = tmp */ } for(i=0;i<5;i++) h[i]+=v[i]; /* add a-e to h0..4 */ } /* produce final hash */ for(i=0;i<5;i++) { *md++=h[i]>>24; *md++=h[i]>>16; *md++=h[i]>>8; *md++=h[i]; } return md; } /******************************************************************************/ #ifndef NTEST static const char test0[]="The quick brown fox jumps over the lazy dog"; static const unsigned char test0_digest[SHA1_DIGEST_LENGTH] = { 0x2f, 0xd4, 0xe1, 0xc6, 0x7a, 0x2d, 0x28, 0xfc, 0xed, 0x84, 0x9e, 0xe1, 0xbb, 0x76, 0xe7, 0x39, 0x1b, 0x93, 0xeb, 0x12, }; static unsigned char test1[] = { 0x83, 0xb8, 0x08, 0xe5, 0xcd, 0x85, 0xbf, 0xe1, 0x5c, 0x27, 0x7c, 0x6a, 0x98, 0x79, 0xa0, 0x22, 0xf5, 0xaf, 0xab, 0xff, 0x86, 0x05, 0xf4, 0x8e, 0xc0, 0x32, 0x80, 0x37, 0xb2, 0xd6, 0xe9, 0x11, 0xb8, 0x68, 0xd0, 0x7d, 0xe6, 0x50, 0x28, 0x0b, 0xcb, 0x1e, 0x69, 0x53, 0xe9, 0x10, 0x83, 0xdf, 0x59, 0x54, 0xda, 0x73, 0x22, 0xa6, 0xd0, 0x82, 0x38, 0x80, 0x02, 0xb4, 0x27, 0x63, 0xd2, 0xf6, 0x01 }; static const size_t test1_len = 65; static const unsigned char test1_digest[] = { 0x68, 0xb2, 0x1d, 0x8f, 0x56, 0x1a, 0xd0, 0x8e, 0x68, 0x3e, 0x61, 0x95, 0x4c, 0x66, 0xac, 0x53, 0xf1, 0x24, 0x56, 0xa7 }; static unsigned char test2[] = { 0x54, 0x91, 0x06, 0x9b, 0x24, 0x00, 0x8b, 0xfd, 0x9e, 0x4a, 0x52, 0xb5 }; static const size_t test2_len = 12; static const unsigned char test2_digest[] = { 0xc8, 0xd9, 0x2c, 0xb3, 0x81, 0x97, 0x1d, 0xc8, 0xe7, 0xa4, 0x1a, 0xfd, 0xb7, 0x9e, 0x0f, 0x4f, 0x86, 0x76, 0xa0, 0xef }; static unsigned char test3[] = { 0xc2, 0xba, 0xb3, 0x02, 0xfb, 0x08, 0x58, 0x87, 0xad, 0x23, 0xc7, 0x4a, 0xca, 0x45, 0x40, 0xc2, 0xa4, 0x64, 0x96, 0xae, 0x40, 0x41, 0x16, 0x0e, 0x49, 0xd7, 0xdc, 0x53, 0x7e, 0xc6, 0x5e, 0xa2, 0x1a, 0x67, 0x35, 0x0a, 0x4d, 0x4a, 0xdc, 0x9a, 0x78, 0xf4, 0xd6, 0x69, 0xb6, 0x4e, 0xb1, 0x31, 0x92, 0x8b, 0xbe, 0xcd, 0x0b, 0x4f, 0x83, 0x0f, 0xe1, 0x2e, 0x0e, 0x8c, 0xf7, 0x9e, 0xf1 }; static const size_t test3_len = 63; static const unsigned char test3_digest[] = { 0xe6, 0x11, 0x4e, 0xea, 0x22, 0x13, 0x57, 0xe3, 0x48, 0x42, 0x7f, 0x5e, 0x5d, 0x6e, 0xc3, 0x59, 0x4f, 0x3d, 0x50, 0x7b }; static unsigned char test4[] = { 0x99, 0xd3, 0xf5, 0x77, 0x0f, 0x22, 0xc3, 0x34, 0x46, 0xb1, 0x4c, 0x69, 0x08, 0x9b, 0x22, 0x5b, 0x88, 0xbf, 0x10, 0x9a, 0xe4, 0x86, 0x8c, 0xa4, 0xb3, 0x5e, 0xa7, 0x1a, 0x36, 0xc8, 0x92, 0xd5, 0x06, 0x62, 0xd1, 0x65, 0x22, 0xa9, 0x33, 0xe1, 0x5a, 0x29 }; static const size_t test4_len = 42; static const unsigned char test4_digest[] = { 0x0b, 0x0f, 0x2b, 0xce, 0xf8, 0x44, 0x8f, 0xfe, 0x53, 0xd2, 0x25, 0x40, 0x0d, 0xa5, 0x07, 0x17, 0x84, 0x3a, 0xab, 0x33 }; static void sha1_print_digest(const unsigned char *md) { unsigned i; for(i=0;i