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