gloox
1.0
|
00001 /* 00002 Copyright (c) 2006-2009 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 "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 }