sha.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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 }