Drizzled Public API Documentation

CSSha1.cc

00001 /* Copyright (C) 2008 PrimeBase Technologies GmbH, Germany
00002  *
00003  * PrimeBase S3Daemon
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
00018  *
00019  *  Modified by Barry Leslie on 10/21/08.
00020  *  I have put a C++ wrapper around the data and functions to create an sha1 class.
00021  *
00022  */
00023 /*
00024   Original Source from: http://www.faqs.org/rfcs/rfc3174.html
00025   and MySQL mysys/sha1.c build 5.1.24.
00026 
00027  DESCRIPTION
00028    This file implements the Secure Hashing Algorithm 1 as
00029    defined in FIPS PUB 180-1 published April 17, 1995.
00030 
00031    The SHA-1, produces a 160-bit message digest for a given data
00032    stream.  It should take about 2**n steps to find a message with the
00033    same digest as a given message and 2**(n/2) to find any two
00034    messages with the same digest, when n is the digest size in bits.
00035    Therefore, this algorithm can serve as a means of providing a
00036    "fingerprint" for a message.
00037 
00038  PORTABILITY ISSUES
00039    SHA-1 is defined in terms of 32-bit "words".  This code uses
00040    <stdint.h> (included via "sha1.h" to define 32 and 8 bit unsigned
00041    integer types.  If your C compiler does not support 32 bit unsigned
00042    integers, this code is not appropriate.
00043 
00044  CAVEATS
00045    SHA-1 is designed to work with messages less than 2^64 bits long.
00046    Although SHA-1 allows a message digest to be generated for messages
00047    of any number of bits less than 2^64, this implementation only
00048    works with messages with a length that is a multiple of the size of
00049    an 8-bit character.
00050 
00051   CHANGES
00052     2002 by Peter Zaitsev to
00053      - fit to new prototypes according to MySQL standard
00054      - Some optimizations
00055      - All checking is now done in debug only mode
00056      - More comments
00057 */
00058 
00059 #include "CSConfig.h"
00060 #include <string.h>
00061 #include <stdint.h>
00062 
00063 #include "CSDefs.h"
00064 #include "CSObject.h"
00065 
00066 #include "CSSha1.h"
00067 
00068 #define SHA1CircularShift(bits,word) (((word) << (bits)) | ((word) >> (32-(bits))))
00069 
00070 void CSSha1::sha1_reset()
00071 {
00072   Length = 0;
00073   Message_Block_Index = 0;
00074 
00075   Intermediate_Hash[0] = 0x67452301;
00076   Intermediate_Hash[1] = 0xEFCDAB89;
00077   Intermediate_Hash[2] = 0x98BADCFE;
00078   Intermediate_Hash[3] = 0x10325476;
00079   Intermediate_Hash[4] = 0xC3D2E1F0;
00080 
00081   Computed = false;
00082 
00083 }
00084 
00085 //------------------------------
00086 void CSSha1::sha1_digest(Sha1Digest *digest)
00087 {
00088   if (!Computed) {
00089     sha1_pad();   
00090     memset(Message_Block, 0, 64);
00091     Length = 0;
00092     Computed = true;
00093   }
00094 
00095   for (int i = 0; i < SHA1_HASH_SIZE; i++)
00096     digest->val[i] = (int8_t)((Intermediate_Hash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) )));
00097 }
00098 
00099 //------------------------------
00100 void CSSha1::sha1_input(const void *data, size_t len)
00101 {
00102   uint8_t *message_array = (u_char *) data;
00103   
00104   if (!len)
00105     return;
00106 
00107   if (Computed)
00108     sha1_reset();
00109 
00110   while (len--) {
00111     Message_Block[Message_Block_Index++]= (*message_array & 0xFF);
00112     Length += 8;  /* Length is in bits */
00113 
00114     if (Message_Block_Index == 64)
00115       sha1_process();
00116 
00117     message_array++;
00118   }
00119 }
00120 
00121 //------------------------------
00122 void CSSha1::sha1_pad()
00123 {
00124   /*
00125   Check to see if the current message block is too small to hold
00126   the initial padding bits and length.  If so, we will pad the
00127   block, process it, and then continue padding into a second
00128   block.
00129   */
00130 
00131   int i = Message_Block_Index;
00132 
00133   if (i > 55) {
00134     Message_Block[i++] = 0x80;
00135     memset(&Message_Block[i], 0, sizeof(Message_Block[0]) * 64-i);
00136     Message_Block_Index=64;
00137 
00138     /* This function sets Message_Block_Index to zero */
00139     sha1_process();
00140 
00141     memset(Message_Block, 0, sizeof(Message_Block[0]) * 56);
00142     Message_Block_Index=56;
00143   } else {
00144     Message_Block[i++] = 0x80;
00145     memset(&Message_Block[i], 0, sizeof(Message_Block[0])*(56-i));
00146     Message_Block_Index=56;
00147   }
00148 
00149   /*
00150   Store the message length as the last 8 octets
00151   */
00152 
00153   Message_Block[56] = (int8_t) (Length >> 56);
00154   Message_Block[57] = (int8_t) (Length >> 48);
00155   Message_Block[58] = (int8_t) (Length >> 40);
00156   Message_Block[59] = (int8_t) (Length >> 32);
00157   Message_Block[60] = (int8_t) (Length >> 24);
00158   Message_Block[61] = (int8_t) (Length >> 16);
00159   Message_Block[62] = (int8_t) (Length >> 8);
00160   Message_Block[63] = (int8_t) (Length);
00161 
00162   sha1_process();
00163 }
00164 
00165 //------------------------------
00166 void CSSha1::sha1_process()
00167 {
00168     const uint32_t K[] = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 };
00169   int   t;       /* Loop counter      */
00170   uint32_t  temp;      /* Temporary word value    */
00171   uint32_t  W[80];       /* Word sequence     */
00172   uint32_t  A, B, C, D, E;     /* Word buffers      */
00173   int idx;
00174 
00175   /*
00176   Initialize the first 16 words in the array W
00177   */
00178 
00179   for (t = 0; t < 16; t++) {
00180     idx=t*4;
00181     W[t] = Message_Block[idx] << 24;
00182     W[t] |= Message_Block[idx + 1] << 16;
00183     W[t] |= Message_Block[idx + 2] << 8;
00184     W[t] |= Message_Block[idx + 3];
00185   }
00186 
00187 
00188   for (t = 16; t < 80; t++) {
00189     W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
00190   }
00191 
00192   A = Intermediate_Hash[0];
00193   B = Intermediate_Hash[1];
00194   C = Intermediate_Hash[2];
00195   D = Intermediate_Hash[3];
00196   E = Intermediate_Hash[4];
00197 
00198   for (t = 0; t < 20; t++) {
00199     temp= SHA1CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
00200     E = D;
00201     D = C;
00202     C = SHA1CircularShift(30,B);
00203     B = A;
00204     A = temp;
00205   }
00206 
00207   for (t = 20; t < 40; t++) {
00208     temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
00209     E = D;
00210     D = C;
00211     C = SHA1CircularShift(30,B);
00212     B = A;
00213     A = temp;
00214   }
00215 
00216   for (t = 40; t < 60; t++) {
00217     temp= (SHA1CircularShift(5,A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]);
00218     E = D;
00219     D = C;
00220     C = SHA1CircularShift(30,B);
00221     B = A;
00222     A = temp;
00223   }
00224 
00225   for (t = 60; t < 80; t++) {
00226     temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
00227     E = D;
00228     D = C;
00229     C = SHA1CircularShift(30,B);
00230     B = A;
00231     A = temp;
00232   }
00233 
00234   Intermediate_Hash[0] += A;
00235   Intermediate_Hash[1] += B;
00236   Intermediate_Hash[2] += C;
00237   Intermediate_Hash[3] += D;
00238   Intermediate_Hash[4] += E;
00239 
00240   Message_Block_Index = 0;
00241 }
00242 
00243