Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | Related Pages

sha.cpp

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