obsolete/jabber_s/sha.c

00001 /*
00002  * $Id$
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  * 
00018  *  Gabber
00019  *  Copyright (C) 1999-2000 Dave Smith & Julian Missig
00020  *
00021  */
00022 
00023 
00024 
00025 /* 
00026    Implements the Secure Hash Algorithm (SHA1)
00027 
00028    Copyright (C) 1999 Scott G. Miller
00029 
00030    Released under the terms of the GNU General Public License v2
00031    see file COPYING for details
00032 
00033    Credits: 
00034       Robert Klep <robert@ilse.nl>  -- Expansion function fix 
00035           Thomas "temas" Muldowney <temas@box5.net>:
00036                         -- shahash() for string fun
00037                         -- Will add the int32 stuff in a few
00038                         
00039    ---
00040    FIXME: This source takes int to be a 32 bit integer.  This
00041    may vary from system to system.  I'd use autoconf if I was familiar
00042    with it.  Anyone want to help me out?
00043 */
00044 
00045 //#include <config.h>
00046 
00047 #include <stdio.h>
00048 #include <stdlib.h>
00049 #include <fcntl.h>
00050 #include <string.h>
00051 
00052 #ifndef MACOS
00053 #  include <sys/stat.h>
00054 #  include <sys/types.h>
00055 #endif
00056 #ifndef WIN32
00057 #  include <unistd.h>
00058 #  define INT64 long long
00059 #else
00060 #  define snprintf _snprintf
00061 #  define INT64 __int64
00062 #endif
00063 
00064 #define switch_endianness(x) (x<<24 & 0xff000000) | \
00065                              (x<<8  & 0x00ff0000) | \
00066                              (x>>8  & 0x0000ff00) | \
00067                              (x>>24 & 0x000000ff)
00068 
00069 /* Initial hash values */
00070 #define Ai 0x67452301 
00071 #define Bi 0xefcdab89
00072 #define Ci 0x98badcfe
00073 #define Di 0x10325476
00074 #define Ei 0xc3d2e1f0
00075 
00076 /* SHA1 round constants */
00077 #define K1 0x5a827999
00078 #define K2 0x6ed9eba1
00079 #define K3 0x8f1bbcdc 
00080 #define K4 0xca62c1d6
00081 
00082 /* Round functions.  Note that f2() is used in both rounds 2 and 4 */
00083 #define f1(B,C,D) ((B & C) | ((~B) & D))
00084 #define f2(B,C,D) (B ^ C ^ D)
00085 #define f3(B,C,D) ((B & C) | (B & D) | (C & D))
00086 
00087 /* left circular shift functions (rotate left) */
00088 #define rol1(x) ((x<<1) | ((x>>31) & 1))
00089 #define rol5(A) ((A<<5) | ((A>>27) & 0x1f))
00090 #define rol30(B) ((B<<30) | ((B>>2) & 0x3fffffff))
00091 
00092 /*
00093   Hashes 'data', which should be a pointer to 512 bits of data (sixteen
00094   32 bit ints), into the ongoing 160 bit hash value (five 32 bit ints)
00095   'hash'
00096 */
00097 int 
00098 sha_hash(int *data, int *hash)  
00099 {
00100   int W[80];
00101   unsigned int A=hash[0], B=hash[1], C=hash[2], D=hash[3], E=hash[4];
00102   unsigned int t, x, TEMP;
00103 
00104   for (t=0; t<16; t++) 
00105     {
00106 #ifndef WORDS_BIGENDIAN
00107       W[t]=switch_endianness(data[t]);
00108 #else 
00109       W[t]=data[t];
00110 #endif
00111     }
00112 
00113 
00114   /* SHA1 Data expansion */
00115   for (t=16; t<80; t++) 
00116     {
00117       x=W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
00118       W[t]=rol1(x);
00119     }
00120 
00121   /* SHA1 main loop (t=0 to 79) 
00122    This is broken down into four subloops in order to use
00123    the correct round function and constant */
00124   for (t=0; t<20; t++) 
00125     {
00126       TEMP=rol5(A) + f1(B,C,D) + E + W[t] + K1;
00127       E=D;
00128       D=C;
00129       C=rol30(B);
00130       B=A;
00131       A=TEMP;
00132     }
00133   for (; t<40; t++) 
00134     {
00135       TEMP=rol5(A) + f2(B,C,D) + E + W[t] + K2;
00136       E=D;
00137       D=C;
00138       C=rol30(B);
00139       B=A;
00140       A=TEMP;
00141     }
00142   for (; t<60; t++) 
00143     {
00144       TEMP=rol5(A) + f3(B,C,D) + E + W[t] + K3;
00145       E=D;
00146       D=C;
00147       C=rol30(B);
00148       B=A;
00149       A=TEMP;
00150     }
00151   for (; t<80; t++) 
00152     {
00153       TEMP=rol5(A) + f2(B,C,D) + E + W[t] + K4;
00154       E=D;
00155       D=C;
00156       C=rol30(B);
00157       B=A;
00158       A=TEMP;
00159     }
00160   hash[0]+=A; 
00161   hash[1]+=B;
00162   hash[2]+=C;
00163   hash[3]+=D;
00164   hash[4]+=E;
00165   return 0;
00166 }
00167 
00168 /*
00169   Takes a pointer to a 160 bit block of data (five 32 bit ints) and
00170   initializes it to the start constants of the SHA1 algorithm.  This
00171   must be called before using hash in the call to sha_hash
00172 */
00173 int 
00174 sha_init(int *hash) 
00175 {
00176   hash[0]=Ai;
00177   hash[1]=Bi;
00178   hash[2]=Ci;
00179   hash[3]=Di;
00180   hash[4]=Ei;
00181   return 0;
00182 }
00183 
00184 int strprintsha(char *dest, int *hashval) 
00185 {
00186         int x;
00187         char *hashstr = dest;
00188         for (x=0; x<5; x++) 
00189         {
00190                 snprintf(hashstr, 9, "%08x", hashval[x]);
00191                 hashstr+=8;
00192         }
00193         /*old way */
00194         //snprintf(hashstr++, 1, "\0");
00195         /*new way - by bogdan*/
00196         *hashstr = 0;
00197 
00198         return 0;
00199 }
00200 
00201 char *shahash(const char *str) 
00202 {
00203         char read_buffer[65];
00204         //int read_buffer[64];
00205         int c=1, i;
00206        
00207         INT64 length=0;
00208 
00209         int strsz;
00210         static char final[40];
00211         int *hashval;
00212 
00213         hashval = (int *)malloc(20);
00214 
00215         sha_init(hashval);
00216 
00217         strsz = strlen(str);
00218 
00219         if(strsz == 0) 
00220         {
00221              memset(read_buffer, 0, 65);
00222              read_buffer[0] = 0x80;
00223              sha_hash((int *)read_buffer, hashval);
00224         }
00225 
00226         while (strsz>0) 
00227         {
00228                 memset(read_buffer, 0, 65);
00229                 strncpy((char*)read_buffer, str, 64);
00230                 c = strlen((char *)read_buffer);
00231                 length+=c;
00232                 strsz-=c;
00233                 if (strsz<=0) 
00234                 {
00235                         length<<=3;     
00236                         read_buffer[c]=(char)0x80;
00237                         for (i=c+1; i<64; i++) 
00238                                 read_buffer[i]=0;
00239                         if (c>55) 
00240                         {
00241                                 /* we need to do an entire new block */
00242                                 sha_hash((int *)read_buffer, hashval);
00243                                 for (i=0; i<14; i++) 
00244                                         ((int*)read_buffer)[i]=0;
00245                         }      
00246 #ifndef WORDS_BIGENDIAN
00247                         for (i=0; i<8; i++) 
00248                         {
00249                                 read_buffer[56+i]=(char)(length>>(56-(i*8))) & 0xff;
00250                         }
00251 #else   
00252                         memcpy(read_buffer+56, &length, 8);
00253 #endif
00254                 }
00255                 
00256                 sha_hash((int *)read_buffer, hashval);
00257                 str+=64;
00258         }
00259 
00260         strprintsha((char *)final, hashval);
00261         free(hashval);
00262         return (char *)final;
00263 }