enc_sha1.c

Go to the documentation of this file.
00001 /*
00002 SHA-1 in C
00003 By Steve Reid <steve@edmweb.com>
00004 100% Public Domain
00005 
00006 Test Vectors (from FIPS PUB 180-1)
00007 "abc"
00008   A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
00009 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
00010   84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
00011 A million repetitions of "a"
00012   34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
00013 */
00014 
00015 /* #define LITTLE_ENDIAN * This should be #define'd if true. */
00016 /* #define SHA1HANDSOFF * Copies data before messing with it. */
00017 
00018 #include "module.h"
00019 #include <stdio.h>
00020 #include <string.h>
00021 
00022 typedef struct {
00023     unsigned long state[5];
00024     unsigned long count[2];
00025     unsigned char buffer[64];
00026 } SHA1_CTX;
00027 
00028 void SHA1Transform(unsigned long state[5], const unsigned char buffer[64]);
00029 void SHA1Init(SHA1_CTX* context);
00030 void SHA1Update(SHA1_CTX* context, const unsigned char* data, unsigned int len);
00031 void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
00032 
00033 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
00034 
00035 /* blk0() and blk() perform the initial expand. */
00036 /* I got the idea of expanding during the round function from SSLeay */
00037 #ifdef LITTLE_ENDIAN
00038 #define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
00039     |(rol(block->l[i],8)&0x00FF00FF))
00040 #else
00041 #define blk0(i) block->l[i]
00042 #endif
00043 #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
00044     ^block->l[(i+2)&15]^block->l[i&15],1))
00045 
00046 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
00047 #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
00048 #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
00049 #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
00050 #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
00051 #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
00052 
00053 
00054 /* Hash a single 512-bit block. This is the core of the algorithm. */
00055 
00056 void SHA1Transform(unsigned long state[5], const unsigned char buffer[64])
00057 {
00058 unsigned long a, b, c, d, e;
00059 typedef union {
00060     unsigned char c[64];
00061     unsigned long l[16];
00062 } CHAR64LONG16;
00063 CHAR64LONG16* block;
00064 #ifdef SHA1HANDSOFF
00065 static unsigned char workspace[64];
00066     block = (CHAR64LONG16*)workspace;
00067     memcpy(block, buffer, 64);
00068 #else
00069     block = (CHAR64LONG16*)buffer;
00070 #endif
00071     /* Copy context->state[] to working vars */
00072     a = state[0];
00073     b = state[1];
00074     c = state[2];
00075     d = state[3];
00076     e = state[4];
00077     /* 4 rounds of 20 operations each. Loop unrolled. */
00078     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);
00079     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);
00080     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);
00081     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);
00082     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);
00083     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);
00084     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);
00085     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);
00086     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);
00087     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);
00088     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);
00089     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);
00090     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);
00091     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);
00092     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);
00093     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);
00094     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);
00095     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);
00096     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);
00097     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);
00098     /* Add the working vars back into context.state[] */
00099     state[0] += a;
00100     state[1] += b;
00101     state[2] += c;
00102     state[3] += d;
00103     state[4] += e;
00104     /* Wipe variables */
00105     a = b = c = d = e = 0;
00106 }
00107 
00108 
00109 /* SHA1Init - Initialize new context */
00110 
00111 void SHA1Init(SHA1_CTX* context)
00112 {
00113     /* SHA1 initialization constants */
00114     context->state[0] = 0x67452301;
00115     context->state[1] = 0xEFCDAB89;
00116     context->state[2] = 0x98BADCFE;
00117     context->state[3] = 0x10325476;
00118     context->state[4] = 0xC3D2E1F0;
00119     context->count[0] = context->count[1] = 0;
00120 }
00121 
00122 
00123 /* Run your data through this. */
00124 
00125 void SHA1Update(SHA1_CTX* context, const unsigned char* data, unsigned int len)
00126 {
00127 unsigned int i, j;
00128 
00129     j = (context->count[0] >> 3) & 63;
00130     if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
00131     context->count[1] += (len >> 29);
00132     if ((j + len) > 63) {
00133         memcpy(&context->buffer[j], data, (i = 64-j));
00134         SHA1Transform(context->state, context->buffer);
00135         for ( ; i + 63 < len; i += 64) {
00136             SHA1Transform(context->state, &data[i]);
00137         }
00138         j = 0;
00139     }
00140     else i = 0;
00141     memcpy(&context->buffer[j], &data[i], len - i);
00142 }
00143 
00144 
00145 /* Add padding and return the message digest. */
00146 
00147 void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
00148 {
00149 unsigned long i, j;
00150 unsigned char finalcount[8];
00151 
00152     for (i = 0; i < 8; i++) {
00153         finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
00154          >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
00155     }
00156     SHA1Update(context, (unsigned char *)"\200", 1);
00157     while ((context->count[0] & 504) != 448) {
00158         SHA1Update(context, (unsigned char *)"\0", 1);
00159     }
00160     SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */
00161     for (i = 0; i < 20; i++) {
00162         digest[i] = (unsigned char)
00163          ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
00164     }
00165     /* Wipe variables */
00166     i = j = 0;
00167     memset(context->buffer, 0, 64);
00168     memset(context->state, 0, 20);
00169     memset(context->count, 0, 8);
00170     memset(&finalcount, 0, 8);
00171 #ifdef SHA1HANDSOFF  /* make SHA1Transform overwrite it's own static vars */
00172     SHA1Transform(context->state, context->buffer);
00173 #endif
00174 }
00175 
00176 
00177 /*************************************************************/
00178 
00179 /*
00180 int main(int argc, char** argv)
00181 {
00182     int i, j;
00183     SHA1_CTX context;
00184     unsigned char digest[20], buffer[16384];
00185     FILE* file;
00186 
00187     if (argc > 2) {
00188         puts("Public domain SHA-1 implementation - by Steve Reid <steve@edmweb.com>");
00189         puts("Produces the SHA-1 hash of a file, or stdin if no file is specified.");
00190         exit(0);
00191     }
00192     if (argc < 2) {
00193         file = stdin;
00194     }
00195     else {
00196         if (!(file = fopen(argv[1], "rb"))) {
00197             fputs("Unable to open file.", stderr);
00198             exit(-1);
00199         }
00200     } 
00201     SHA1Init(&context);
00202     while (!feof(file)) { 
00203         i = fread(buffer, 1, 16384, file);
00204         SHA1Update(&context, buffer, i);
00205     }
00206     SHA1Final(digest, &context);
00207     fclose(file);
00208     for (i = 0; i < 5; i++) {
00209         for (j = 0; j < 4; j++) {
00210             printf("%02X", digest[i*4+j]);
00211         }
00212         putchar(' ');
00213     }
00214     putchar('\n');
00215     exit(0);
00216 }
00217     */
00218 
00219 /*****************************************************************************/
00220 
00221 int sha1_encrypt(const char *src, int len, char *dest, int size)
00222 {
00223     SHA1_CTX context;
00224     unsigned char tmp[41];
00225 
00226     if (size < 20)
00227     return -1;
00228 
00229     memset(dest,0,20);
00230 
00231     SHA1Init(&context);
00232     SHA1Update(&context, src, len);
00233     SHA1Final(dest, &context);
00234 
00235     if(debug) {
00236         memset(tmp,0,41);
00237         binary_to_hex(dest,tmp,20);
00238     /* Dont log source if we were encrypting in place :) */
00239         if (memcmp(src, dest, 20) != 0) {
00240             alog("enc_sha1: hashed from [%s] to [%s]",src,tmp); 
00241     } else {
00242             alog("enc_sha1: hashed password to [%s]",tmp); 
00243     }
00244     }
00245     
00246     return 0;
00247 }
00248 
00249 
00250 int sha1_encrypt_in_place(char *buf, int size)
00251 {
00252     char tmp[41];
00253     memset(tmp,0,41);
00254     if(sha1_encrypt(buf, strlen(buf), tmp, size)==0) {
00255         memcpy(buf,tmp,40);
00256     } else {
00257         return -1;
00258     }
00259     return 0;
00260 }
00261 
00262 
00263 int sha1_encrypt_check_len(int passlen, int bufsize)
00264 {
00265     if (bufsize < 20)
00266     fatal("enc_sha1: sha1_check_len(): buffer too small (%d)", bufsize);
00267     return 0;
00268 }
00269 
00270 
00271 int sha1_decrypt(const char *src, char *dest, int size)
00272 {
00273     return 0;
00274 }
00275 
00276 
00277 int sha1_check_password(const char *plaintext, const char *password)
00278 {
00279     char buf[BUFSIZE];
00280 
00281     if (sha1_encrypt(plaintext, strlen(plaintext), buf, sizeof(buf)) < 0)
00282     return -1;
00283     if (memcmp(buf, password, 20) == 0)
00284     return 1;
00285     return 0;
00286 }
00287 
00288 /*************************************************************************/
00289 
00290 /* Module stuff. */
00291 
00292 int AnopeInit(int argc, char **argv) {
00293 
00294     moduleAddAuthor("Anope");
00295     moduleAddVersion("$Id$");
00296     moduleSetType(ENCRYPTION);
00297  
00298     encmodule_encrypt(sha1_encrypt);
00299     encmodule_encrypt_in_place(sha1_encrypt_in_place);
00300     encmodule_encrypt_check_len(sha1_encrypt_check_len);
00301     encmodule_decrypt(sha1_decrypt);
00302     encmodule_check_password(sha1_check_password);
00303 
00304     return MOD_CONT;
00305 }
00306 
00307 void AnopeFini(void) {
00308     encmodule_encrypt(NULL);
00309     encmodule_encrypt_in_place(NULL);
00310     encmodule_encrypt_check_len(NULL);
00311     encmodule_decrypt(NULL);
00312     encmodule_check_password(NULL);
00313 }
00314 

Generated on Sun Dec 30 09:26:47 2007 for Anope by  doxygen 1.5.1-20070107