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

Generated on Mon Dec 7 13:28:19 2009 for gloox by  doxygen 1.6.1