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