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