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

TigerTree.cpp

Go to the documentation of this file.
00001 //
00002 // TigerTree.cpp
00003 //
00004 // Copyright (c) Shareaza Development Team, 2002-2005.
00005 // This file is part of SHAREAZA (www.shareaza.com)
00006 //
00007 // Shareaza is free software; you can redistribute it
00008 // and/or modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // Shareaza is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with Shareaza; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //
00021 
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "TigerTree.h"
00025 
00026 #ifdef _DEBUG
00027 #undef THIS_FILE
00028 static char THIS_FILE[]=__FILE__;
00029 #define new DEBUG_NEW
00030 #endif
00031 
00032 #define BLOCK_SIZE              1024
00033 #define STACK_SIZE              64
00034 #define TIGER_SIZE              24
00035 
00036 #define NEW_TIGER_ALG   // New "more secure" padded node combination
00037 
00038 
00040 // CTigerTree construction
00041 extern "C" void TigerTree_Tiger_p5(WORD64* str, WORD64* state);
00042 extern "C" void TigerTree_Tiger_MMX(WORD64* str, WORD64* state);
00043 extern "C" void TigerTree_Tiger_SSE2(WORD64* str, WORD64* state);
00044 void (*pTiger)(WORD64*, WORD64*);
00045 
00046 inline int GetCPUIDFlags()
00047 {
00048         _asm
00049     {
00050                 mov     eax, 1
00051                 cpuid
00052                 mov     eax, edx
00053         }
00054 }
00055 
00056 CTigerTree::CTigerTree()
00057 {
00058         m_nHeight               = 0;
00059         m_pNode                 = NULL;
00060         m_nNodeCount    = 0;
00061 
00062         m_pStackBase    = NULL;
00063         m_pStackTop             = NULL;
00064 
00065         pTiger = &TigerTree_Tiger_p5;
00066 //      if (GetCPUIDFlags() & 0x00800000) pTiger = &TigerTree_Tiger_MMX;
00067         if (GetCPUIDFlags() & 0x04000000) pTiger = &TigerTree_Tiger_SSE2;
00068 }
00069 
00070 CTigerTree::~CTigerTree()
00071 {
00072         Clear();
00073 
00074         if ( m_pStackBase != NULL ) delete [] m_pStackBase;
00075 }
00076 
00078 // CTigerTree setup tree
00079 
00080 void CTigerTree::SetupAndAllocate(DWORD nHeight, QWORD nLength)
00081 {
00082         Clear();
00083 
00084         QWORD nCount = (DWORD)( nLength / BLOCK_SIZE );
00085         if ( nLength % BLOCK_SIZE ) nCount++;
00086 
00087         DWORD nActualHeight = 1;
00088 
00089         for ( DWORD nStep = 1 ; nStep < nCount ; nStep *= 2 ) nActualHeight++;
00090 
00091         m_nHeight = min( nActualHeight, nHeight );
00092 
00093         m_nBlockCount   = 1;
00094         m_nBlockPos             = 0;
00095 
00096         if ( nActualHeight > nHeight )
00097         {
00098                 for ( DWORD nStep = nActualHeight - nHeight ; nStep ; nStep-- ) m_nBlockCount *= 2;
00099         }
00100 
00101         m_nNodeCount = 1;
00102 
00103         for ( DWORD nStep = m_nHeight ; nStep ; nStep-- ) m_nNodeCount *= 2;
00104 
00105         m_nNodeBase     = ( m_nNodeCount / 2 );
00106         m_nBaseUsed     = (DWORD)( nCount / m_nBlockCount );
00107         if ( nCount % m_nBlockCount ) m_nBaseUsed++;
00108 
00109         m_pNode         = new CTigerNode[ --m_nNodeCount ];
00110         m_nNodePos      = 0;
00111 }
00112 
00113 void CTigerTree::SetupParameters(QWORD nLength)
00114 {
00115         QWORD nCount = nLength / BLOCK_SIZE;
00116         if ( nLength % BLOCK_SIZE ) nCount++;
00117 
00118         DWORD nActualHeight = 1;
00119         for ( DWORD nStep = 1 ; nStep < nCount ; nStep *= 2 ) nActualHeight++;
00120 
00121         m_nBlockCount   = 1;
00122         m_nBlockPos             = 0;
00123 
00124         if ( nActualHeight > m_nHeight )
00125         {
00126                 for ( DWORD nStep = nActualHeight - m_nHeight ; nStep ; nStep-- ) m_nBlockCount *= 2;
00127         }
00128 
00129         m_nNodeCount = 1;
00130         for ( DWORD nStep = m_nHeight ; nStep ; nStep-- ) m_nNodeCount *= 2;
00131 
00132         m_nNodeBase = ( m_nNodeCount-- / 2 );
00133 
00134         m_nBaseUsed     = (DWORD)( nCount / m_nBlockCount );
00135         if ( nCount % m_nBlockCount ) m_nBaseUsed++;
00136 }
00137 
00139 // CTigerTree clear
00140 
00141 void CTigerTree::Clear()
00142 {
00143         if ( m_pNode != NULL ) delete [] m_pNode;
00144 
00145         m_nHeight               = 0;
00146         m_pNode                 = NULL;
00147         m_nNodeCount    = 0;
00148 }
00149 
00151 // CTigerTree serialize
00152 
00153 void CTigerTree::Serialize(CArchive& ar)
00154 {
00155         CTigerNode* pNode;
00156         DWORD nStep;
00157 
00158         if ( ar.IsStoring() )
00159         {
00160                 ar << m_nHeight;
00161 
00162                 if ( m_nHeight == 0 ) return;
00163                 ASSERT( m_pNode != NULL );
00164 
00165                 pNode = m_pNode;
00166 
00167                 for ( nStep = m_nNodeCount ; nStep ; nStep--, pNode++ )
00168                 {
00169                         ar.Write( pNode->value, TIGER_SIZE );
00170                         ar << pNode->bValid;
00171                 }
00172         }
00173         else
00174         {
00175                 Clear();
00176 
00177                 ar >> m_nHeight;
00178                 if ( m_nHeight == 0 ) return;
00179 
00180                 m_nNodeCount = 1;
00181                 for ( nStep = m_nHeight ; nStep ; nStep-- ) m_nNodeCount *= 2;
00182                 m_nNodeCount --;
00183 
00184                 m_pNode = pNode = new CTigerNode[ m_nNodeCount ];
00185 
00186                 for ( nStep = m_nNodeCount ; nStep ; nStep--, pNode++ )
00187                 {
00188                         ar.Read( pNode->value, TIGER_SIZE );
00189                         ar >> pNode->bValid;
00190                 }
00191         }
00192 }
00193 
00194 DWORD CTigerTree::GetSerialSize() const
00195 {
00196         return 4 + m_nNodeCount * ( TIGER_SIZE + 1 );
00197 }
00198 
00200 // CTigerTree root output
00201 
00202 BOOL CTigerTree::GetRoot(TIGEROOT* pTiger) const
00203 {
00204         if ( m_pNode == NULL ) return FALSE;
00205         ASSERT( sizeof(TIGEROOT) == TIGER_SIZE );
00206         CopyMemory( pTiger, &m_pNode->value, TIGER_SIZE );
00207         return TRUE;
00208 }
00209 
00211 // CTigerTree string output
00212 
00213 CString CTigerTree::RootToString() const
00214 {
00215         CString str;
00216         if ( m_pNode != NULL ) str = m_pNode->ToString();
00217         return str;
00218 }
00219 
00221 // CTigerTree assume
00222 
00223 void CTigerTree::Assume(CTigerTree* pSource)
00224 {
00225         Clear();
00226         if ( pSource->m_pNode == NULL ) return;
00227 
00228         m_nHeight               = pSource->m_nHeight;
00229         m_nNodeCount    = pSource->m_nNodeCount;
00230         m_pNode                 = pSource->m_pNode;
00231 
00232         pSource->m_nHeight              = 0;
00233         pSource->m_nNodeCount   = 0;
00234         pSource->m_pNode                = NULL;
00235 }
00236 
00238 // CTigerTree create from file
00239 
00240 void CTigerTree::BeginFile(DWORD nHeight, QWORD nLength)
00241 {
00242         ASSERT( ! IsAvailable() );
00243 
00244         SetupAndAllocate( nHeight, nLength );
00245 
00246         if ( m_pStackBase == NULL ) m_pStackBase = new CTigerNode[ STACK_SIZE ];
00247         m_pStackTop     = m_pStackBase;
00248         m_nBlockPos = 0;
00249 }
00250 
00252 // CTigerTree add data to the file
00253 
00254 void CTigerTree::AddToFile(LPCVOID pInput, DWORD nLength)
00255 {
00256         ASSERT( m_pNode != NULL );
00257 
00258         LPBYTE pBlock = (LPBYTE)pInput;
00259 
00260         while ( nLength > 0 )
00261         {
00262                 DWORD nBlock = min( nLength, DWORD(BLOCK_SIZE) );
00263 
00264                 Tiger( pBlock, (WORD64)nBlock, m_pStackTop->value );
00265                 m_pStackTop ++;
00266 
00267                 DWORD nCollapse = ++m_nBlockPos;
00268 
00269                 while ( ! ( nCollapse & 1 ) )
00270                 {
00271                         Collapse();
00272                         nCollapse >>= 1;
00273                 }
00274 
00275                 if ( m_nBlockPos >= m_nBlockCount )
00276                 {
00277                         BlocksToNode();
00278                 }
00279 
00280                 pBlock += nBlock;
00281                 nLength -= nBlock;
00282         }
00283 }
00284 
00286 // CTigerTree finish file
00287 
00288 BOOL CTigerTree::FinishFile()
00289 {
00290         if ( m_pStackTop == NULL ) return FALSE;
00291         if ( m_nBaseUsed == 0 )
00292         {
00293                 Tiger( this, 0, (m_pStackTop++)->value );
00294                 m_nBlockPos++;
00295         }
00296 
00297         BlocksToNode();
00298 
00299         if ( m_nNodePos > m_nNodeBase ) return FALSE;
00300 
00301         if ( m_pStackBase != NULL ) delete [] m_pStackBase;
00302 
00303         m_pStackBase    = NULL;
00304         m_pStackTop             = NULL;
00305 
00306         CTigerNode* pBase = m_pNode + m_nNodeCount - m_nNodeBase;
00307 
00308         for ( DWORD nCombine = m_nNodeBase ; nCombine > 1 ; nCombine /= 2 )
00309         {
00310                 CTigerNode* pIn         = pBase;
00311                 CTigerNode* pOut        = pBase - nCombine / 2;
00312 
00313                 for ( DWORD nIterate = nCombine / 2 ; nIterate ; nIterate--, pIn += 2, pOut++ )
00314                 {
00315                         if ( pIn[0].bValid && pIn[1].bValid )
00316                         {
00317                                 Tiger( NULL, TIGER_SIZE * 2, pOut->value, pIn[0].value, pIn[1].value );
00318                                 pOut->bValid = TRUE;
00319                         }
00320                         else if ( pIn[0].bValid )
00321                         {
00322                                 *pOut = *pIn;
00323                         }
00324                 }
00325 
00326                 pBase -= nCombine / 2;
00327         }
00328 
00329         return TRUE;
00330 }
00331 
00333 // CTigerTree begin a block test
00334 
00335 void CTigerTree::BeginBlockTest()
00336 {
00337         ASSERT( m_pNode != NULL );
00338 
00339         if ( m_pStackBase == NULL ) m_pStackBase = new CTigerNode[ STACK_SIZE ];
00340         m_pStackTop     = m_pStackBase;
00341         m_nBlockPos = 0;
00342 }
00343 
00345 // CTigerTree add data to a block test
00346 
00347 void CTigerTree::AddToTest(LPCVOID pInput, DWORD nLength)
00348 {
00349         ASSERT( m_pNode != NULL );
00350 
00351         LPBYTE pBlock = (LPBYTE)pInput;
00352 
00353         while ( nLength > 0 )
00354         {
00355                 DWORD nBlock = min( nLength, DWORD(BLOCK_SIZE) );
00356 
00357                 Tiger( pBlock, (WORD64)nBlock, m_pStackTop->value );
00358                 m_pStackTop ++;
00359 
00360                 ASSERT( m_nBlockPos < m_nBlockCount );
00361 
00362                 DWORD nCollapse = ++m_nBlockPos;
00363 
00364                 while ( ! ( nCollapse & 1 ) )
00365                 {
00366                         Collapse();
00367                         nCollapse >>= 1;
00368                 }
00369 
00370                 pBlock += nBlock;
00371                 nLength -= nBlock;
00372         }
00373 }
00374 
00376 // CTigerTree block test finish and compare
00377 
00378 BOOL CTigerTree::FinishBlockTest(DWORD nBlock)
00379 {
00380         ASSERT( nBlock < m_nBaseUsed );
00381         if ( nBlock >= m_nBaseUsed ) return FALSE;
00382 
00383         while ( m_pStackTop - 1 > m_pStackBase ) Collapse();
00384 
00385         CTigerNode* pNode = m_pNode + m_nNodeCount - m_nNodeBase + nBlock;
00386 
00387         if ( pNode->v1 != m_pStackBase->v1 ) return FALSE;
00388         if ( pNode->v2 != m_pStackBase->v2 ) return FALSE;
00389         if ( pNode->v3 != m_pStackBase->v3 ) return FALSE;
00390 
00391         return TRUE;
00392 }
00393 
00395 // CTigerTree breadth-first serialize
00396 
00397 BOOL CTigerTree::ToBytes(BYTE** pOutput, DWORD* pnOutput, DWORD nHeight)
00398 {
00399         if ( m_pNode == NULL ) return FALSE;
00400 
00401         if ( nHeight < 1 || nHeight > m_nHeight ) nHeight = m_nHeight;
00402 
00403         DWORD nNodeCount = 1;
00404         while ( nHeight-- ) nNodeCount *= 2;
00405         nNodeCount --;
00406 
00407         nNodeCount      = min( nNodeCount, m_nNodeCount );
00408         *pnOutput       = nNodeCount * TIGER_SIZE;
00409         *pOutput        = new BYTE[ *pnOutput ];
00410 
00411         CTigerNode* pNode = m_pNode;
00412         BYTE* pOut = *pOutput;
00413 
00414         for ( DWORD nNode = 0 ; nNode < nNodeCount ; nNode++, pNode++ )
00415         {
00416                 if ( pNode->bValid )
00417                 {
00418                         CopyMemory( pOut, pNode->value, TIGER_SIZE );
00419                         pOut += TIGER_SIZE;
00420                 }
00421                 else
00422                 {
00423                         *pnOutput -= TIGER_SIZE;
00424                 }
00425         }
00426 
00427         return TRUE;
00428 }
00429 
00431 // CTigerTree breadth-first serialize
00432 
00433 BOOL CTigerTree::FromBytes(BYTE* pInput, DWORD nInput, DWORD nHeight, QWORD nLength)
00434 {
00435         SetupAndAllocate( nHeight, nLength );
00436 
00437         CTigerNode* pBase = m_pNode + m_nNodeCount - m_nNodeBase;
00438 
00439         for ( DWORD nStep = m_nBaseUsed ; nStep ; nStep-- )
00440         {
00441                 pBase[ nStep - 1 ].bValid = TRUE;
00442         }
00443 
00444         for ( DWORD nCombine = m_nNodeBase ; nCombine > 1 ; nCombine /= 2 )
00445         {
00446                 CTigerNode* pIn         = pBase;
00447                 CTigerNode* pOut        = pBase - nCombine / 2;
00448 
00449                 for ( DWORD nIterate = nCombine / 2 ; nIterate ; nIterate--, pIn += 2, pOut++ )
00450                 {
00451                         if ( pIn[0].bValid ) pOut->bValid = TRUE;
00452                 }
00453 
00454                 pBase -= nCombine / 2;
00455         }
00456 
00457         TIGEROOT* pTiger = (TIGEROOT*)pInput;
00458         nInput /= TIGER_SIZE;
00459 
00460         DWORD nRowPos = 0, nRowCount = 1;
00461         m_nHeight = 0;
00462 
00463         for ( DWORD nStep = 0 ; nStep < m_nNodeCount && nInput > 0 ; nStep++ )
00464         {
00465                 if ( m_pNode[ nStep ].bValid )
00466                 {
00467                         CopyMemory( m_pNode[ nStep ].value, pTiger->w, TIGER_SIZE );
00468                         pTiger ++; nInput --;
00469                 }
00470 
00471                 if ( nRowPos == 0 ) m_nHeight ++;
00472 
00473                 if ( ++nRowPos == nRowCount )
00474                 {
00475                         nRowCount *= 2;
00476                         nRowPos = 0;
00477                 }
00478         }
00479 
00480         if ( m_nHeight == 0 || m_nHeight > nHeight )
00481         {
00482                 Clear();
00483                 return FALSE;
00484         }
00485 
00486         SetupParameters( nLength );
00487 
00488         if ( ! CheckIntegrity() )
00489         {
00490                 Clear();
00491                 return FALSE;
00492         }
00493 
00494         return TRUE;
00495 }
00496 
00498 // CTigerTree integrity check
00499 
00500 BOOL CTigerTree::CheckIntegrity()
00501 {
00502         if ( m_pNode == NULL ) return FALSE;
00503 
00504         m_nNodeBase = ( m_nNodeCount + 1 ) / 2;
00505         CTigerNode* pBase = m_pNode + m_nNodeCount - m_nNodeBase;
00506 
00507         for ( DWORD nCombine = m_nNodeBase ; nCombine > 1 ; nCombine /= 2 )
00508         {
00509                 CTigerNode* pIn         = pBase;
00510                 CTigerNode* pOut        = pBase - nCombine / 2;
00511 
00512                 if ( nCombine == 2 && pOut->bValid == FALSE ) return FALSE;
00513 
00514                 for ( DWORD nIterate = nCombine / 2 ; nIterate ; nIterate--, pIn += 2, pOut++ )
00515                 {
00516                         if ( pIn[0].bValid && pIn[1].bValid )
00517                         {
00518                                 TIGEROOT pTemp;
00519                                 Tiger( NULL, TIGER_SIZE * 2, pTemp.w, pIn[0].value, pIn[1].value );
00520                                 if ( memcmp( pTemp.w, pOut->value, TIGER_SIZE ) ) return FALSE;
00521                         }
00522                         else if ( pIn[0].bValid )
00523                         {
00524                                 if ( memcmp( pIn[0].value, pOut->value, TIGER_SIZE ) ) return FALSE;
00525                         }
00526                         else
00527                         {
00528                                 // pOut is bValid=FALSE
00529                         }
00530                 }
00531 
00532                 pBase -= nCombine / 2;
00533         }
00534 
00535         return TRUE;
00536 }
00537 
00539 // CTigerTree dump to file
00540 
00541 void CTigerTree::Dump()
00542 {
00543 #ifdef _DEBUG
00544         CString strOutput, strLine;
00545 
00546         DWORD nRowPos = 0, nRowCount = 1;
00547         m_nHeight = 0;
00548 
00549         for ( DWORD nStep = 0 ; nStep < m_nNodeCount ; nStep++ )
00550         {
00551                 if ( m_pNode[ nStep ].bValid )
00552                         strLine += CTigerNode::HashToString( (TIGEROOT*)m_pNode[ nStep ].value );
00553                 else
00554                         strLine += _T("_______________________________________");
00555                 strLine += ' ';
00556 
00557                 if ( ++nRowPos == nRowCount )
00558                 {
00559                         strOutput += strLine;
00560                         strOutput += _T("\r\n");
00561                         strLine.Empty();
00562 
00563                         m_nHeight ++;
00564                         nRowCount *= 2;
00565                         nRowPos = 0;
00566                 }
00567         }
00568 
00569         theApp.LogMessage( strOutput );
00570 
00571 #endif
00572 }
00573 
00574 
00576 // CTigerNode to string
00577 
00578 CString CTigerNode::ToString()
00579 {
00580         return HashToString( (TIGEROOT*)&value );
00581 }
00582 
00583 CString CTigerNode::HashToString(const TIGEROOT* pInHash, BOOL bURN)
00584 {
00585         static LPCTSTR pszBase64 = _T("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567");
00586 
00587         CString strHash;
00588         LPTSTR pszHash  = strHash.GetBuffer( bURN ? 16 + 39 : 39 );
00589 
00590         if ( bURN )
00591         {
00592                 *pszHash++ = 'u'; *pszHash++ = 'r'; *pszHash++ = 'n'; *pszHash++ = ':';
00593                 *pszHash++ = 't'; *pszHash++ = 'r'; *pszHash++ = 'e'; *pszHash++ = 'e'; *pszHash++ = ':';
00594                 *pszHash++ = 't'; *pszHash++ = 'i'; *pszHash++ = 'g'; *pszHash++ = 'e'; *pszHash++ = 'r'; *pszHash++ = '/'; *pszHash++ = ':';
00595         }
00596 
00597         LPBYTE pHash    = (LPBYTE)pInHash;
00598         BYTE pZero              = 0;
00599         int nShift              = 7;
00600         int nHash               = 0;
00601 
00602         for ( int nChar = 39 ; nChar ; nChar-- )
00603         {
00604                 BYTE nBits = 0;
00605 
00606                 for ( int nBit = 0 ; nBit < 5 ; nBit++ )
00607                 {
00608                         if ( nBit ) nBits <<= 1;
00609                         nBits |= ( *pHash >> nShift ) & 1;
00610 
00611                         if ( ! nShift-- )
00612                         {
00613                                 nShift = 7;
00614                                 if ( ++nHash < TIGER_SIZE )
00615                                         pHash++;
00616                                 else
00617                                         pHash = &pZero;
00618                         }
00619                 }
00620 
00621                 *pszHash++ = pszBase64[ nBits ];
00622         }
00623 
00624         strHash.ReleaseBuffer( bURN ? 16 + 39 : 39 );
00625 
00626         return strHash;
00627 }
00628 
00630 // CTigerNode parse from string
00631 
00632 BOOL CTigerNode::HashFromString(LPCTSTR pszHash, TIGEROOT* pTiger)
00633 {
00634         if ( ! pszHash || _tcslen( pszHash ) < 39 ) return FALSE; //Invalid hash
00635 
00636         if ( _tcsnicmp(pszHash, _T("BVBCHUUIDO4TRQL3C2QL3RIA3KB3TDWJDZ7AHCQ"), 39 ) == 0 ) return FALSE; //Bad hash
00637 
00638         LPBYTE pHash = (LPBYTE)pTiger;
00639         DWORD nBits     = 0;
00640         int nCount      = 0;
00641 
00642         for ( int nChars = 39 ; nChars-- ; pszHash++ )
00643         {
00644                 if ( *pszHash >= 'A' && *pszHash <= 'Z' )
00645                         nBits |= ( *pszHash - 'A' );
00646                 else if ( *pszHash >= 'a' && *pszHash <= 'z' )
00647                         nBits |= ( *pszHash - 'a' );
00648                 else if ( *pszHash >= '2' && *pszHash <= '7' )
00649                         nBits |= ( *pszHash - '2' + 26 );
00650                 else
00651                         return FALSE;
00652 
00653                 nCount += 5;
00654 
00655                 if ( nCount >= 8 )
00656                 {
00657                         *pHash++ = (BYTE)( nBits >> ( nCount - 8 ) );
00658                         nCount -= 8;
00659                 }
00660 
00661                 nBits <<= 5;
00662         }
00663 
00664         return TRUE;
00665 }
00666 
00667 BOOL CTigerNode::HashFromURN(LPCTSTR pszHash, TIGEROOT* pTiger)
00668 {
00669         if ( pszHash == NULL ) return FALSE;
00670 
00671         int nLen = _tcslen( pszHash );
00672 
00673         if ( nLen >= 16+39 && _tcsnicmp( pszHash, _T("urn:tree:tiger/:"), 16 ) == 0 )
00674         {
00675                 return HashFromString( pszHash + 16, pTiger );
00676         }
00677         else if ( nLen >= 12+39 && _tcsnicmp( pszHash, _T("tree:tiger/:"), 12 ) == 0 )
00678         {
00679                 return HashFromString( pszHash + 12, pTiger );
00680         }
00681         else if ( nLen >= 15+39 && _tcsnicmp( pszHash, _T("urn:tree:tiger:"), 15 ) == 0 )
00682         {
00683                 return HashFromString( pszHash + 15, pTiger );
00684         }
00685         else if ( nLen >= 11+39 && _tcsnicmp( pszHash, _T("tree:tiger:"), 11 ) == 0 )
00686         {
00687                 return HashFromString( pszHash + 11, pTiger );
00688         }
00689         else if ( nLen >= 85 && _tcsnicmp( pszHash, _T("urn:bitprint:"), 13 ) == 0 )
00690         {
00691                 return HashFromString( pszHash + 46, pTiger );
00692         }
00693         else if ( nLen >= 81 && _tcsnicmp( pszHash, _T("bitprint:"), 9 ) == 0 )
00694         {
00695                 return HashFromString( pszHash + 42, pTiger );
00696         }
00697 
00698         return FALSE;
00699 }
00700 
00701 BOOL CTigerNode::IsNull(TIGEROOT* pTiger)
00702 {
00703         if ( _tcsnicmp( HashToString(pTiger) , _T("BVBCHUUIDO4TRQL3C2QL3RIA3KB3TDWJDZ7AHCQ"), 39 ) == 0 ) return TRUE; //Bad hash
00704 
00705         return FALSE;
00706 }
00707 
00708 
00710 // CTigerTree tiger hash implementation
00711 //
00712 // Portions created and released into the public domain by Eli Biham
00713 //
00714 
00715 void CTigerTree::Tiger(LPCVOID pInput, WORD64 nInput, WORD64* pOutput, WORD64* pInput1, WORD64* pInput2)
00716 {
00717         register WORD64 i, j;
00718         BYTE pTemp[64];
00719 
00720         pOutput[0] = 0x0123456789ABCDEF;
00721         pOutput[1] = 0xFEDCBA9876543210;
00722         pOutput[2] = 0xF096A5B4C3B2E187;
00723 
00724         if ( pInput != NULL )
00725         {
00726 #ifdef NEW_TIGER_ALG
00727                 if ( nInput < 63 )
00728                 {
00729                         pTemp[0] = 0x00;
00730                         const BYTE* pBytes = (const BYTE*)pInput;
00731                         for ( j = 1 ; j < nInput + 1 ; j++ ) pTemp[j] = *pBytes++;
00732                 }
00733                 else
00734                 {
00735                         pTemp[0] = 0x00;
00736                         CopyMemory( pTemp + 1, pInput, 63 );
00737                         pTiger( (WORD64*)pTemp, pOutput );
00738 
00739                         const WORD64* pWords = (const WORD64*)( (const BYTE*)pInput + 63 );
00740 
00741                         for ( i = nInput - 63 ; i >= 64 ; i -= 64 )
00742                         {
00743                                 pTiger( (WORD64*) pWords, pOutput );
00744                                 pWords += 8;
00745                         }
00746 
00747                         for ( j = 0 ; j < i ; j++ ) pTemp[j] = ((BYTE*)pWords)[j];
00748                 }
00749                 nInput++;
00750 #else
00751                 const WORD64* pWords = (const WORD64*)pInput;
00752 
00753                 for ( i = nInput ; i >= 64 ; i -= 64 )
00754                 {
00755                         pTiger( pWords, pOutput );
00756                         pWords += 8;
00757                 }
00758 
00759                 for ( j = 0 ; j < i ; j++ ) pTemp[j] = ((BYTE*)pWords)[j];
00760 #endif
00761         }
00762         else if ( pInput1 != NULL && pInput2 != NULL )
00763         {
00764 #ifdef NEW_TIGER_ALG
00765                 pTemp[0] = 0x01;
00766                 CopyMemory( pTemp + 1, pInput1, TIGER_SIZE );
00767                 CopyMemory( pTemp + TIGER_SIZE + 1, pInput2, TIGER_SIZE );
00768                 j = TIGER_SIZE * 2 + 1;
00769                 nInput = j;
00770 #else
00771                 CopyMemory( pTemp, pInput1, TIGER_SIZE );
00772                 CopyMemory( pTemp + TIGER_SIZE, pInput2, TIGER_SIZE );
00773                 nInput = j = TIGER_SIZE * 2;
00774 #endif
00775         }
00776         else
00777         {
00778                 ASSERT( FALSE );
00779         }
00780 
00781         pTemp[j++] = 0x01;
00782 
00783         for ( ; j & 7 ; j++ ) pTemp[j] = 0;
00784 
00785         if ( j > 56 )
00786         {
00787                 for ( ; j < 64 ; j++ ) pTemp[j] = 0;
00788                 pTiger( ((WORD64*)pTemp), pOutput );
00789                 j = 0;
00790         }
00791 
00792         for ( ; j < 56 ; j++ ) pTemp[j] = 0;
00793 
00794         ((WORD64*)(&(pTemp[56])))[0] = ((WORD64)nInput) << 3;
00795 
00796         pTiger( ((WORD64*)pTemp), pOutput );
00797 }
00798 
00799 #define PASSES 3
00800 
00801 #define t1 (m_pTable)
00802 #define t2 (m_pTable+256)
00803 #define t3 (m_pTable+256*2)
00804 #define t4 (m_pTable+256*3)
00805 
00806 #define save_abc \
00807       aa = a; \
00808       bb = b; \
00809       cc = c;
00810 
00811 #define round(a,b,c,x,mul) \
00812       c ^= x; \
00813       a -= t1[(BYTE)(c)] ^ \
00814            t2[(BYTE)(((DWORD)(c))>>(2*8))] ^ \
00815            t3[(BYTE)((c)>>(4*8))] ^ \
00816            t4[(BYTE)(((DWORD)((c)>>(4*8)))>>(2*8))] ; \
00817       b += t4[(BYTE)(((DWORD)(c))>>(1*8))] ^ \
00818            t3[(BYTE)(((DWORD)(c))>>(3*8))] ^ \
00819            t2[(BYTE)(((DWORD)((c)>>(4*8)))>>(1*8))] ^ \
00820            t1[(BYTE)(((DWORD)((c)>>(4*8)))>>(3*8))]; \
00821       b *= mul;
00822 
00823 #define pass(a,b,c,mul) \
00824       round(a,b,c,x0,mul) \
00825       round(b,c,a,x1,mul) \
00826       round(c,a,b,x2,mul) \
00827       round(a,b,c,x3,mul) \
00828       round(b,c,a,x4,mul) \
00829       round(c,a,b,x5,mul) \
00830       round(a,b,c,x6,mul) \
00831       round(b,c,a,x7,mul)
00832 
00833 #define key_schedule \
00834       x0 -= x7 ^ 0xA5A5A5A5A5A5A5A5; \
00835       x1 ^= x0; \
00836       x2 += x1; \
00837       x3 -= x2 ^ ((~x1)<<19); \
00838       x4 ^= x3; \
00839       x5 += x4; \
00840       x6 -= x5 ^ ((~x4)>>23); \
00841       x7 ^= x6; \
00842       x0 += x7; \
00843       x1 -= x0 ^ ((~x7)<<19); \
00844       x2 ^= x1; \
00845       x3 += x2; \
00846       x4 -= x3 ^ ((~x2)>>23); \
00847       x5 ^= x4; \
00848       x6 += x5; \
00849       x7 -= x6 ^ 0x0123456789ABCDEF;
00850 
00851 #define feedforward \
00852       a ^= aa; \
00853       b -= bb; \
00854       c += cc;
00855 
00856 #define compress \
00857       save_abc \
00858       for(pass_no=0; pass_no<PASSES; pass_no++) { \
00859         if(pass_no != 0) {key_schedule} \
00860         pass(a,b,c,(pass_no==0?5:pass_no==1?7:9)); \
00861         tmpa=a; a=c; c=b; b=tmpa;} \
00862       feedforward
00863 
00864 //void CTigerTree::Tiger(WORD64* str, WORD64* state)
00865 //{
00866 //      TigerTree_Tiger_p5(str,state);
00867 /*      register WORD64 x0, x1, x2, x3, x4, x5, x6, x7;
00868         register WORD64 a, b, c, tmpa;
00869         WORD64 aa, bb, cc;
00870         // register DWORD i;
00871         int pass_no;
00872 
00873         a = state[0];
00874         b = state[1];
00875         c = state[2];
00876 
00877         x0=str[0]; x1=str[1]; x2=str[2]; x3=str[3];
00878         x4=str[4]; x5=str[5]; x6=str[6]; x7=str[7];
00879 
00880         compress;
00881 
00882         state[0] = a;
00883         state[1] = b;
00884         state[2] = c; */
00885 //}
00886 
00888 // CTigerTree collapse stack
00889 
00890 void CTigerTree::Collapse()
00891 {
00892         ASSERT( m_pStackTop - m_pStackBase >= 2 );
00893 
00894         Tiger( NULL, TIGER_SIZE * 2, m_pStackTop->value, m_pStackTop[-2].value, m_pStackTop[-1].value );
00895 
00896         m_pStackTop -= 2;
00897         m_pStackTop[0] = m_pStackTop[2];
00898         m_pStackTop ++;
00899 }
00900 
00902 // CTigerTree convert a block sequence to a node
00903 
00904 void CTigerTree::BlocksToNode()
00905 {
00906         if ( m_pStackTop == m_pStackBase ) return;
00907 
00908         while ( m_pStackTop - 1 > m_pStackBase ) Collapse();
00909 
00910         CTigerNode* pNode = m_pNode + m_nNodeCount - m_nNodeBase + m_nNodePos++;
00911 
00912         pNode->v1               = m_pStackBase->v1;
00913         pNode->v2               = m_pStackBase->v2;
00914         pNode->v3               = m_pStackBase->v3;
00915         pNode->bValid   = TRUE;
00916 
00917         m_nBlockPos             = 0;
00918         m_pStackTop             = m_pStackBase;
00919 }

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