Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

SHA.cpp

Go to the documentation of this file.
00001 /*
00002  ---------------------------------------------------------------------------
00003  Copyright (c) 2002, Dr Brian Gladman <[email protected]>, Worcester, UK.
00004  All rights reserved.
00005 
00006  LICENSE TERMS
00007 
00008  The free distribution and use of this software in both source and binary 
00009  form is allowed (with or without changes) provided that:
00010 
00011    1. distributions of this source code include the above copyright 
00012       notice, this list of conditions and the following disclaimer;
00013 
00014    2. distributions in binary form include the above copyright
00015       notice, this list of conditions and the following disclaimer
00016       in the documentation and/or other associated materials;
00017 
00018    3. the copyright holder's name is not used to endorse products 
00019       built using this software without specific written permission. 
00020 
00021  ALTERNATIVELY, provided that this notice is retained in full, this product
00022  may be distributed under the terms of the GNU General Public License (GPL),
00023  in which case the provisions of the GPL apply INSTEAD OF those given above.
00024  
00025  DISCLAIMER
00026 
00027  This software is provided 'as is' with no explicit or implied warranties
00028  in respect of its properties, including, but not limited to, correctness 
00029  and/or fitness for purpose.
00030  ---------------------------------------------------------------------------
00031  Issue Date: 30/11/2002
00032 
00033  This is a byte oriented version of SHA1 that operates on arrays of bytes
00034  stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor
00035 */
00036 
00037 /* Modified by Camper using extern methods     6.7.2004 */
00038 
00039 #include "StdAfx.h"
00040 #include "SHA.h"
00041 
00042 // This detects ICL and makes necessary changes for proper compilation
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     /* extract the hash value as bytes in case the hash buffer is   */
00078     /* misaligned for 32-bit words                                  */
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         // Save number of bits
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         // Pad out to 56 mod 64.
00106         index = (unsigned int)(m_nCount[0] & 0x3f);
00107         SHA_Add_p5(this, SHA_PADDING, (index < 56) ? (56 - index) : (120 - index) );
00108         // Append length (before padding)
00109         SHA_Add_p5(this, bits, 8 );
00110 }
00111 
00113 // CSHA get hash string (Base64)
00114 
00115 CString CSHA::GetHashString(BOOL bURN)
00116 {
00117         SHA1 pHash;
00118         GetHash( &pHash );
00119         return HashToString( &pHash, bURN );
00120 }
00121 
00123 // CSHA convert hash to string (Base64)
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 // CSHA convert hash to string (hex)
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 // CSHA parse hash from string (Base64)
00191 
00192 BOOL CSHA::HashFromString(LPCTSTR pszHash, SHA1* pHashIn)
00193 {
00194         if ( ! pszHash || _tcslen( pszHash ) < 32 ) return FALSE;  //Invalid hash
00195 
00196         if ( _tcsnicmp(pszHash, _T("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), 32 ) == 0 ) return FALSE; //Bad hash
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 // CSHA parse hash from URN
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                 // 13 + 32 + 1 + 39
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 }

Generated on Thu Dec 15 10:39:48 2005 for Shareaza 2.2.1.0 by  doxygen 1.4.2