00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "StdAfx.h"
00040 #include "SHA.h"
00041
00042
00043 #if __INTEL_COMPILER > 0
00044 #define asm_m_nCount CSHA.m_nCount
00045 #else
00046 #define asm_m_nCount m_nCount
00047 #endif
00048
00049 extern "C" void SHA_Add_p5(CSHA *, LPCVOID pData, DWORD nLength);
00050 static unsigned char SHA_PADDING[64] = {
00051 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00052 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00053 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00054 };
00055
00056 CSHA::CSHA()
00057 {
00058 Reset();
00059 }
00060
00061 CSHA::~CSHA()
00062 {
00063 }
00064
00065 void CSHA::Reset()
00066 {
00067 m_nCount[0] = m_nCount[1] = 0;
00068 m_nHash[0] = 0x67452301;
00069 m_nHash[1] = 0xefcdab89;
00070 m_nHash[2] = 0x98badcfe;
00071 m_nHash[3] = 0x10325476;
00072 m_nHash[4] = 0xc3d2e1f0;
00073 }
00074
00075 void CSHA::GetHash(SHA1* pHash)
00076 {
00077
00078
00079 for(int i = 0; i < SHA1_DIGEST_SIZE; ++i)
00080 pHash->b[i] = (unsigned char)(m_nHash[i >> 2] >> 8 * (~i & 3));
00081 }
00082
00083 void CSHA::Add(LPCVOID pData, DWORD nLength)
00084 {
00085 SHA_Add_p5(this, pData, nLength);
00086 }
00087
00088
00089 void CSHA::Finish()
00090 {
00091 unsigned int bits[2], index = 0;
00092
00093 _asm
00094 {
00095 mov ecx, this
00096 mov eax, [ecx+asm_m_nCount]
00097 mov edx, [ecx+asm_m_nCount+4]
00098 shld edx, eax, 3
00099 shl eax, 3
00100 bswap edx
00101 bswap eax
00102 mov bits, edx
00103 mov bits+4, eax
00104 }
00105
00106 index = (unsigned int)(m_nCount[0] & 0x3f);
00107 SHA_Add_p5(this, SHA_PADDING, (index < 56) ? (56 - index) : (120 - index) );
00108
00109 SHA_Add_p5(this, bits, 8 );
00110 }
00111
00113
00114
00115 CString CSHA::GetHashString(BOOL bURN)
00116 {
00117 SHA1 pHash;
00118 GetHash( &pHash );
00119 return HashToString( &pHash, bURN );
00120 }
00121
00123
00124
00125 CString CSHA::HashToString(const SHA1* pHashIn, BOOL bURN)
00126 {
00127 static LPCTSTR pszBase64 = _T("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567");
00128
00129 CString strHash;
00130 LPTSTR pszHash = strHash.GetBuffer( bURN ? 9 + 32 : 32 );
00131
00132 if ( bURN )
00133 {
00134 *pszHash++ = 'u'; *pszHash++ = 'r'; *pszHash++ = 'n'; *pszHash++ = ':';
00135 *pszHash++ = 's'; *pszHash++ = 'h'; *pszHash++ = 'a'; *pszHash++ = '1'; *pszHash++ = ':';
00136 }
00137
00138 LPBYTE pHash = (LPBYTE)pHashIn;
00139 int nShift = 7;
00140
00141 for ( int nChar = 32 ; nChar ; nChar-- )
00142 {
00143 BYTE nBits = 0;
00144
00145 for ( int nBit = 0 ; nBit < 5 ; nBit++ )
00146 {
00147 if ( nBit ) nBits <<= 1;
00148 nBits |= ( *pHash >> nShift ) & 1;
00149
00150 if ( ! nShift-- )
00151 {
00152 nShift = 7;
00153 pHash++;
00154 }
00155 }
00156
00157 *pszHash++ = pszBase64[ nBits ];
00158 }
00159
00160 strHash.ReleaseBuffer( bURN ? 9 + 32 : 32 );
00161
00162 return strHash;
00163 }
00164
00166
00167
00168 CString CSHA::HashToHexString(const SHA1* pHashIn, BOOL bURN)
00169 {
00170 static LPCTSTR pszHex = _T("0123456789ABCDEF");
00171
00172 LPBYTE pHash = (LPBYTE)pHashIn;
00173 CString strHash;
00174 LPTSTR pszHash = strHash.GetBuffer( 40 );
00175
00176 for ( int nByte = 0 ; nByte < 20 ; nByte++, pHash++ )
00177 {
00178 *pszHash++ = pszHex[ *pHash >> 4 ];
00179 *pszHash++ = pszHex[ *pHash & 15 ];
00180 }
00181
00182 strHash.ReleaseBuffer( 40 );
00183
00184 if ( bURN ) strHash = _T("urn:sha1:") + strHash;
00185
00186 return strHash;
00187 }
00188
00190
00191
00192 BOOL CSHA::HashFromString(LPCTSTR pszHash, SHA1* pHashIn)
00193 {
00194 if ( ! pszHash || _tcslen( pszHash ) < 32 ) return FALSE;
00195
00196 if ( _tcsnicmp(pszHash, _T("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), 32 ) == 0 ) return FALSE;
00197
00198 SHA1 Hash;
00199 LPBYTE pHash = (LPBYTE)&Hash;
00200 DWORD nBits = 0;
00201 int nCount = 0;
00202
00203 for ( int nChars = 32 ; nChars-- ; pszHash++ )
00204 {
00205 if ( *pszHash >= 'A' && *pszHash <= 'Z' )
00206 nBits |= ( *pszHash - 'A' );
00207 else if ( *pszHash >= 'a' && *pszHash <= 'z' )
00208 nBits |= ( *pszHash - 'a' );
00209 else if ( *pszHash >= '2' && *pszHash <= '7' )
00210 nBits |= ( *pszHash - '2' + 26 );
00211 else
00212 return FALSE;
00213
00214 nCount += 5;
00215
00216 if ( nCount >= 8 )
00217 {
00218 *pHash++ = (BYTE)( nBits >> ( nCount - 8 ) );
00219 nCount -= 8;
00220 }
00221
00222 nBits <<= 5;
00223 }
00224
00225 *pHashIn = Hash;
00226
00227 return TRUE;
00228 }
00229
00231
00232
00233 BOOL CSHA::HashFromURN(LPCTSTR pszHash, SHA1* pHashIn)
00234 {
00235 if ( pszHash == NULL ) return FALSE;
00236 int nLen = _tcslen( pszHash );
00237
00238 if ( nLen >= 41 && _tcsnicmp( pszHash, _T("urn:sha1:"), 9 ) == 0 )
00239 {
00240 return HashFromString( pszHash + 9, pHashIn );
00241 }
00242 else if ( nLen >= 37 && _tcsnicmp( pszHash, _T("sha1:"), 5 ) == 0 )
00243 {
00244 return HashFromString( pszHash + 5, pHashIn );
00245 }
00246 else if ( nLen >= 85 && _tcsnicmp( pszHash, _T("urn:bitprint:"), 13 ) == 0 )
00247 {
00248
00249 return HashFromString( pszHash + 13, pHashIn );
00250 }
00251 else if ( nLen >= 81 && _tcsnicmp( pszHash, _T("bitprint:"), 9 ) == 0 )
00252 {
00253 return HashFromString( pszHash + 9, pHashIn );
00254 }
00255
00256 return FALSE;
00257 }
00258
00259
00260 BOOL CSHA::IsNull(SHA1* pHash)
00261 {
00262 SHA1 Blank;
00263
00264 ZeroMemory( &Blank, sizeof(SHA1) );
00265
00266 if ( *pHash == Blank ) return TRUE;
00267
00268 return FALSE;
00269 }