sha.cpp

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