sha.cpp

00001 /*
00002   Copyright (c) 2006-2007 by Jakob Schroeter <js@camaya.net>
00003   This file is part of the gloox library. http://camaya.net/gloox
00004 
00005   This software is distributed under a license. The full license
00006   agreement can be found in the file LICENSE in this distribution.
00007   This software may not be copied, modified, sold or distributed
00008   other than expressed in the named license agreement.
00009 
00010   This software is distributed without any warranty.
00011 */
00012 
00013 #include "sha.h"
00014 
00015 namespace gloox
00016 {
00017 
00018   SHA::SHA()
00019   {
00020     init();
00021   }
00022 
00023   SHA::~SHA()
00024   {
00025   }
00026 
00027   void SHA::init()
00028   {
00029     Length_Low = 0;
00030     Length_High = 0;
00031     Message_Block_Index = 0;
00032 
00033     H[0] = 0x67452301;
00034     H[1] = 0xEFCDAB89;
00035     H[2] = 0x98BADCFE;
00036     H[3] = 0x10325476;
00037     H[4] = 0xC3D2E1F0;
00038 
00039     m_finished = false;
00040     m_corrupted = false;
00041   }
00042 
00043   void SHA::reset()
00044   {
00045     init();
00046   }
00047 
00048   const std::string SHA::hex()
00049   {
00050     if( m_corrupted )
00051       return "";
00052 
00053     if( !m_finished )
00054     {
00055       pad();
00056       m_finished = true;
00057     }
00058 
00059     char buf[41];
00060     for( int i = 0; i < 20; ++i )
00061       sprintf( buf + i * 2, "%02x", (unsigned char)( H[i >> 2] >> ( ( 3 - ( i & 3 ) ) << 3 ) ) );
00062 
00063     return std::string( buf, 40 );
00064   }
00065 
00066   void SHA::finalize()
00067   {
00068     if( !m_finished )
00069     {
00070       pad();
00071       m_finished = true;
00072       return;
00073     }
00074   }
00075 
00076   void SHA::feed( const unsigned char *data, unsigned length )
00077   {
00078     if( !length )
00079       return;
00080 
00081     if( m_finished || m_corrupted )
00082     {
00083       m_corrupted = true;
00084       return;
00085     }
00086 
00087     while( length-- && !m_corrupted )
00088     {
00089       Message_Block[Message_Block_Index++] = ( *data & 0xFF );
00090 
00091       Length_Low += 8;
00092       Length_Low &= 0xFFFFFFFF;
00093       if( Length_Low == 0 )
00094       {
00095         Length_High++;
00096         Length_High &= 0xFFFFFFFF;
00097         if( Length_High == 0 )
00098         {
00099           m_corrupted = true;
00100         }
00101       }
00102 
00103       if( Message_Block_Index == 64 )
00104       {
00105         process();
00106       }
00107 
00108       ++data;
00109     }
00110   }
00111 
00112   void SHA::feed( const std::string& data )
00113   {
00114     feed( (const unsigned char*)data.c_str(), data.length() );
00115   }
00116 
00117   void SHA::process()
00118   {
00119     const unsigned K[] = { 0x5A827999,
00120                            0x6ED9EBA1,
00121                            0x8F1BBCDC,
00122                            0xCA62C1D6
00123                           };
00124     int t;
00125     unsigned temp;
00126     unsigned W[80];
00127     unsigned A, B, C, D, E;
00128 
00129     for( t = 0; t < 16; t++ )
00130     {
00131       W[t] = ((unsigned) Message_Block[t * 4]) << 24;
00132       W[t] |= ((unsigned) Message_Block[t * 4 + 1]) << 16;
00133       W[t] |= ((unsigned) Message_Block[t * 4 + 2]) << 8;
00134       W[t] |= ((unsigned) Message_Block[t * 4 + 3]);
00135     }
00136 
00137     for( t = 16; t < 80; ++t )
00138     {
00139       W[t] = shift( 1, W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16] );
00140     }
00141 
00142     A = H[0];
00143     B = H[1];
00144     C = H[2];
00145     D = H[3];
00146     E = H[4];
00147 
00148     for( t = 0; t < 20; ++t )
00149     {
00150       temp = shift( 5, A ) + ( ( B & C ) | ( ( ~B ) & D ) ) + E + W[t] + K[0];
00151       temp &= 0xFFFFFFFF;
00152       E = D;
00153       D = C;
00154       C = shift( 30, B );
00155       B = A;
00156       A = temp;
00157     }
00158 
00159     for( t = 20; t < 40; ++t )
00160     {
00161       temp = shift( 5, A ) + ( B ^ C ^ D ) + E + W[t] + K[1];
00162       temp &= 0xFFFFFFFF;
00163       E = D;
00164       D = C;
00165       C = shift( 30, B );
00166       B = A;
00167       A = temp;
00168     }
00169 
00170     for( t = 40; t < 60; ++t )
00171     {
00172       temp = shift( 5, A ) + ( ( B & C ) | ( B & D ) | ( C & D ) ) + E + W[t] + K[2];
00173       temp &= 0xFFFFFFFF;
00174       E = D;
00175       D = C;
00176       C = shift( 30, B );
00177       B = A;
00178       A = temp;
00179     }
00180 
00181     for( t = 60; t < 80; ++t )
00182     {
00183       temp = shift( 5, A ) + ( B ^ C ^ D ) + E + W[t] + K[3];
00184       temp &= 0xFFFFFFFF;
00185       E = D;
00186       D = C;
00187       C = shift( 30, B );
00188       B = A;
00189       A = temp;
00190     }
00191 
00192     H[0] = ( H[0] + A ) & 0xFFFFFFFF;
00193     H[1] = ( H[1] + B ) & 0xFFFFFFFF;
00194     H[2] = ( H[2] + C ) & 0xFFFFFFFF;
00195     H[3] = ( H[3] + D ) & 0xFFFFFFFF;
00196     H[4] = ( H[4] + E ) & 0xFFFFFFFF;
00197 
00198     Message_Block_Index = 0;
00199   }
00200 
00201   void SHA::pad()
00202   {
00203     if( Message_Block_Index > 55 )
00204     {
00205       Message_Block[Message_Block_Index++] = 0x80;
00206       while( Message_Block_Index < 64 )
00207       {
00208         Message_Block[Message_Block_Index++] = 0;
00209       }
00210 
00211       process();
00212 
00213       while( Message_Block_Index < 56 )
00214       {
00215         Message_Block[Message_Block_Index++] = 0;
00216       }
00217     }
00218     else
00219     {
00220       Message_Block[Message_Block_Index++] = 0x80;
00221       while( Message_Block_Index < 56 )
00222       {
00223         Message_Block[Message_Block_Index++] = 0;
00224       }
00225 
00226     }
00227 
00228     Message_Block[56] = ( Length_High >> 24 ) & 0xFF;
00229     Message_Block[57] = ( Length_High >> 16 ) & 0xFF;
00230     Message_Block[58] = ( Length_High >> 8 ) & 0xFF;
00231     Message_Block[59] = ( Length_High ) & 0xFF;
00232     Message_Block[60] = ( Length_Low >> 24 ) & 0xFF;
00233     Message_Block[61] = ( Length_Low >> 16 ) & 0xFF;
00234     Message_Block[62] = ( Length_Low >> 8 ) & 0xFF;
00235     Message_Block[63] = ( Length_Low ) & 0xFF;
00236 
00237     process();
00238   }
00239 
00240 
00241   unsigned SHA::shift( int bits, unsigned word )
00242   {
00243     return ( ( word << bits ) & 0xFFFFFFFF) | ( ( word & 0xFFFFFFFF ) >> ( 32-bits ) );
00244   }
00245 
00246 }

Generated on Sat Nov 10 08:50:27 2007 for gloox by  doxygen 1.5.3-20071008