home *** CD-ROM | disk | FTP | other *** search
- /* Xceed Encryption Library - TestVector Sample Application
- * Copyright (c) 2001 Xceed Software Inc.
- *
- * [TestVector.cpp]
- *
- * This console application tests the results of some Xceed Encryption Library
- * functions against some static test vectors.
- * It specifically tests:
- * - The Encrypt and Hash methods.
- *
- * This file is part of the Xceed Encryption Library sample
- * applications. The source code in this file is only intended as
- * a supplement to Xceed Encryption Library's documentation,
- * and is provided "as is", without warranty of any kind, either
- * expressed or implied.
- */
-
- #include "stdafx.h"
-
- #include <stdio.h>
- #include "TestVector.h"
-
- // --------------------------------------------------------------------------
- //
- // Entry point of the application
- //
- // --------------------------------------------------------------------------
- int main( int argc, char* argv[] )
- {
- CoInitialize( NULL );
-
- try
- {
- // Create an instance of the XceedEncryption coclass
- IXceedEncryptionPtr piEnc;
- piEnc.CreateInstance( CLSID_XceedEncryption );
-
- // Create an instance of the XceedHashing coclass
- IXceedHashingPtr piHash;
- piHash.CreateInstance( CLSID_XceedHashing );
-
- bool bAllPassed = true;
-
- // Test the Rijndael encryption method
- if( !TestRijndael( piEnc ) )
- bAllPassed = false;
-
- // Test the Twofish encryption method
- if( !TestTwoFish( piEnc ) )
- bAllPassed = false;
-
- // Test the SHA hashing method
- if( !TestSHA( piHash ) )
- bAllPassed = false;
-
- // Test the Haval hashing method
- if( !TestHaval( piHash ) )
- bAllPassed = false;
-
- if( bAllPassed )
- {
- printf( "\n\nAll tests passed!" );
- }
- else
- {
- printf( "\n\nSome test(s) failed!" );
- }
- }
- catch( const _com_error& err )
- {
- // The generated wrapper classes throw _com_error exceptions when a COM error
- // occurs.
- printf( "Error %08x: %s\n", err.Error(), ( const char* )err.Description() );
- }
- catch( ... )
- {
- printf( "An unknown error occured.\n" );
- }
-
- CoUninitialize();
-
- return 0;
- }
-
- // --------------------------------------------------------------------------
- //
- // Test some Rijndael encryption results
- //
- // --------------------------------------------------------------------------
- bool TestRijndael( IXceedEncryptionPtr piEnc )
- {
- // Create an instance of the XceedRijndaelEncryptionMethod coclass
- IXceedRijndaelEncryptionMethodPtr piAES;
- piAES.CreateInstance( CLSID_XceedRijndaelEncryptionMethod );
-
- // Assign the encryption method created above to the encryption object
- piEnc->PutRefEncryptionMethod( IXceedEncryptDataPtr( piAES ) );
-
- // We use the templatized function TestSymmetricCipher, passing it the
- // encryption object, the Rijndael method and the path and file name containing
- // the test vectors.
- return TestSymmetricCipher<IXceedRijndaelEncryptionMethodPtr>( piEnc, piAES, DATA_PATH "Rijndael.txt" );
- }
-
- // --------------------------------------------------------------------------
- //
- // Test some TwoFish encryption results
- //
- // --------------------------------------------------------------------------
- bool TestTwoFish( IXceedEncryptionPtr piEnc )
- {
- // Create an instance of the XceedTwofishEncryptionMethod coclass
- IXceedTwofishEncryptionMethodPtr piTwofish;
- piTwofish.CreateInstance( CLSID_XceedTwofishEncryptionMethod );
-
- // Assign the encryption method created above to the encryption object
- piEnc->PutRefEncryptionMethod( IXceedEncryptDataPtr( piTwofish ) );
-
- // We use the templatized function TestSymmetricCipher, passing it the
- // encryption object, the Twofish method and the path and file name containing
- // the test vectors.
- return TestSymmetricCipher<IXceedTwofishEncryptionMethodPtr>( piEnc, piTwofish, DATA_PATH "TwoFish.txt" );
- }
-
- // --------------------------------------------------------------------------
- //
- // Test some SHA hash results
- //
- // --------------------------------------------------------------------------
- bool TestSHA( IXceedHashingPtr piHash )
- {
- // Create an instance of the XceedSHAHashingMethod coclass
- IXceedSHAHashingMethodPtr piSHA;
- piSHA.CreateInstance( CLSID_XceedSHAHashingMethod );
-
- // Assign the hashing method created above to the hashing object
- piHash->PutRefHashingMethod( IXceedHashDataPtr( piSHA ) );
-
- // We use the templatized function TestHash, passing it the
- // encryption object, the SHA method and the path and file name containing
- // the test vectors.
- return TestHash<IXceedSHAHashingMethodPtr>( piHash, piSHA, DATA_PATH "SHA.txt" );
- }
-
- // --------------------------------------------------------------------------
- //
- // Test some Haval hash results
- //
- // --------------------------------------------------------------------------
- bool TestHaval( IXceedHashingPtr piHash )
- {
- // Create an instance of the XceedHavalHashingMethod coclass
- IXceedHavalHashingMethodPtr piHav;
- piHav.CreateInstance( CLSID_XceedHavalHashingMethod );
-
- // Assign the hashing method created above to the hashing object
- piHash->PutRefHashingMethod( IXceedHashDataPtr( piHav ) );
-
- // We use the templatized function TestHash, passing it the
- // encryption object, the Haval method and the path and file name containing
- // the test vectors.
- return TestHash<IXceedHavalHashingMethodPtr>( piHash, piHav, DATA_PATH "Haval.txt" );
- }
-
- // --------------------------------------------------------------------------
- //
- // Generic function to test symmetric encryptions (Rijndael, Two-Fish)
- // This function assume that the different symmetric encryption method
- // have the same interface.
- //
- // --------------------------------------------------------------------------
- template <typename T>
- bool TestSymmetricCipher( IXceedEncryptionPtr piEnc,
- T piMethod,
- const char* szFileName )
- {
- bool bTestAllPassed = true;
-
- //Open the file containing the test vectors
- HANDLE hFicIn = OpenTestVectorFile( szFileName );
-
- if( hFicIn != INVALID_HANDLE_VALUE )
- {
- BYTE pcKey[MAX_KEY_SIZE];
- short nKeySize = 0;
- BYTE pcPlainText[MAX_PLAIN_TEXT_SIZE];
- DWORD dwPlainTextSize = 0;
- BYTE pcCipherText[MAX_CIPHER_TEXT_SIZE];
- DWORD dwCipherTextSize = 0;
- BYTE pcInitVector[MAX_CIPHER_TEXT_SIZE];
- short nInitVectorSize = 0;
- int CptTest = 1;
-
- // Read each Test vector contained in the files. See the comment in the test
- // vector files for more information.
- while( ReadEncryptionTestVector( hFicIn,
- pcKey, &nKeySize,
- pcInitVector, &nInitVectorSize,
- pcPlainText, &dwPlainTextSize,
- pcCipherText, &dwCipherTextSize ) )
- {
- BYTE* pcEncrypted = NULL;
- DWORD dwEncryptedSize = 0;
- BYTE* pcDecrypted = NULL;
- DWORD dwDecryptedSize = 0;
- long lIdentical = FALSE;
-
- // Initialize the secret key read in the test vector file
- piMethod->SetSecretKey( pcKey, nKeySize );
-
- if( nInitVectorSize > 0 )
- {
- // There was an InitVector in the test vector. Tell the encryption method that
- // we are performing a CBC mode encryption and initialize the InitVector.
- piMethod->EncryptionMode = emoChainedBlocks;
- piMethod->SetInitVector( pcInitVector, nInitVectorSize );
- }
- else
- {
- // No initialization vector was provided in the current test vector. Tell
- // the encryption method that we are performing a ECB mode encryption.
- piMethod->EncryptionMode = emoFreeBlocks;
- }
-
- // Encrypt the plain text
- piEnc->Encrypt( pcPlainText, dwPlainTextSize, TRUE, &pcEncrypted, &dwEncryptedSize );
-
- if( nInitVectorSize > 0 )
- {
- // Compare the encrypted text produced by Xceed Encryption Library with
- // the test vector cipher text. We ignore the first 128 bit (16 bytes) of the
- // encrypted text which contains the InitVector in the clear.
- piEnc->Compare( pcEncrypted + 16, dwCipherTextSize, pcCipherText, dwCipherTextSize, &lIdentical );
- }
- else
- {
- // Compare the encrypted text produced by Xceed Encryption Library with
- // the test vector cipher text.
- piEnc->Compare( pcEncrypted, dwCipherTextSize, pcCipherText, dwCipherTextSize, &lIdentical );
- }
-
- // Display the result of the comparison.
- printf( "Test #%02d %s... Decryption ", CptTest, lIdentical ? "passed" : "failed" );
-
- if( !lIdentical )
- {
- bTestAllPassed = false;
- }
-
- // Test the decrypt process
- // Decrypt the cipher text
- piEnc->Decrypt( pcEncrypted, dwEncryptedSize, TRUE, &pcDecrypted, &dwDecryptedSize );
-
- // Compare the decrypted text to the original plain text
- piEnc->Compare( pcDecrypted, dwDecryptedSize, pcPlainText, dwPlainTextSize, &lIdentical );
-
- // Display the result of the comparison
- printf( lIdentical ? "passed" : "failed" );
- if( !lIdentical )
- {
- bTestAllPassed = false;
- }
-
- // Free the memory allocated by the Xceed Encryption Library
- CoTaskMemFree( pcEncrypted );
- CoTaskMemFree( pcDecrypted );
- printf( "\n" );
- CptTest++;
- }
-
- // Close the test vector file
- CloseHandle( hFicIn );
- }
- else
- {
- printf( "Error opening test vector file\n" );
- bTestAllPassed = false;
- }
-
- return bTestAllPassed;
- }
-
- // --------------------------------------------------------------------------
- //
- // Generic function to test hash function (SHA, Haval)
- // This function assume that the different symmetric encryption method
- // have the same interface.
- //
- // --------------------------------------------------------------------------
- template <typename T>
- bool TestHash( IXceedHashingPtr piHash,
- T piMethod,
- const char* szHashFileName )
- {
- bool bTestAllPassed = true;
-
- //Open the file containing the test vectors
- HANDLE hFicIn = OpenTestVectorFile( szHashFileName );
-
- if( hFicIn != INVALID_HANDLE_VALUE )
- {
- BYTE pcMessage[MAX_MESSAGE_SIZE];
- DWORD dwMessageSize = 0;
- BYTE pcDigest[MAX_MESSAGE_SIZE];
- DWORD dwDigestSize = 0;
- int CptTest = 1;
-
- // Read each Test vector contained in the files. See the comment in the test
- // vector files for more information.
- while( ReadTestVectorHash( hFicIn,
- pcMessage, &dwMessageSize,
- pcDigest, &dwDigestSize ) )
- {
- BYTE* pcHash = NULL;
- short nHashSize = 0;
- long lIdentical = FALSE;
-
- // Initialize the resulting hash size for the current test vector. The size
- // is provided in bits to the Encryption Library; hence the "* 8".
- piMethod->HashSize = static_cast<short>( dwDigestSize * 8 );
-
- // Hash the current test vector "message"
- piHash->Hash( pcMessage, dwMessageSize, TRUE );
-
- // Extract the calculated hash value from the previous call
- piMethod->GetHashValue( &pcHash, &nHashSize );
-
- // Compare the hash value calculated to the expected hash value of the
- // current test vector.
- piHash->Compare( pcDigest, dwDigestSize, pcHash, nHashSize, &lIdentical );
-
- // Display the comparison result
- printf( "Test #%02d %s\n", CptTest, lIdentical ? "passed" : "failed" );
-
- if( !lIdentical )
- {
- bTestAllPassed = false;
- }
-
- // Free the memory allocated by the Xceed Encryption Library
- CoTaskMemFree( pcHash );
- CptTest++;
- }
-
- // Close the test vector file
- CloseHandle( hFicIn );
- }
- else
- {
- printf( "Error opening test vector file\n" );
- bTestAllPassed = false;
- }
-
- return bTestAllPassed;
- }
-
- // --------------------------------------------------------------------------
- //
- // Open the test vector file specified
- //
- // --------------------------------------------------------------------------
- HANDLE OpenTestVectorFile( const char* szFileName )
- {
- HANDLE hFicIn = CreateFile( szFileName, GENERIC_READ, FILE_SHARE_WRITE & FILE_SHARE_READ,
- NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
-
- return hFicIn;
- }
-
- // --------------------------------------------------------------------------
- //
- // Read a test vector from the specified encryption test vector file
- // returns true if succeeded.
- //
- // --------------------------------------------------------------------------
- bool ReadEncryptionTestVector( HANDLE hFicIn,
- BYTE* pcKey, short* pnKeySize,
- BYTE* pcInitVector, short* pnInitVectorSize,
- BYTE* pcPlainText, DWORD* pdwPlainTextSize,
- BYTE* pcCipherText, DWORD* pdwCipherTextSize )
- {
- bool bVectorComplete = false;
- bool bEndOfLine = false;
- BYTE pcBuffer[BUFFER_SIZE] = "";
- DWORD dwTotalRead = 0;
- BYTE cByteRead;
- DWORD dwRead = 0;
- BYTE* pcBinaryBuffer = NULL;
- DWORD dwBinaryBufferSize = 0;
-
- *pnKeySize = 0;
- *pdwPlainTextSize = 0;
- *pdwCipherTextSize = 0;
- *pnInitVectorSize = 0;
-
- // Read one character at a time
- while( ReadFile( hFicIn, &cByteRead, 1, &dwRead, NULL) &&
- dwRead > 0 )
- {
- // Fill the buffer
- if( dwTotalRead > sizeof( pcBuffer ) )
- {
- printf( "Buffer overflow while reading encryption test vector" );
- break;
- }
-
- if( cByteRead == 13 || cByteRead == 10 )
- {
- // We reach a end of line delimiter
- bEndOfLine = true;
- }
- else
- {
- if( !bEndOfLine )
- {
- // The end of line is not reached already. We add the character
- // read to the buffer.
- pcBuffer[dwTotalRead] = cByteRead;
- pcBuffer[dwTotalRead + 1] = '\0';
- dwTotalRead++;
- }
- else
- {
- // The previous character(s) were end of line delimiter.
- // We process the previous line read.
- bEndOfLine = false;
-
- // We want to re-read the current character (the beginning of line)
- // So we move the current file pointer to the previous character.
- SetFilePointer( hFicIn, -1, 0, FILE_CURRENT );
-
- // We ignore blank lines
- if( dwTotalRead > 0 )
- {
- if ( pcBuffer[0] == '.' )
- {
- // We display this line skipping the beginning '.' which tell
- // us that it's a comment line.
- printf( "%s\n", pcBuffer + 1 );
- }
- else if ( pcBuffer[0] == 'k' && pcBuffer[1] == '=' )
- {
- // It's a secret key line
- // Convert the hexadecimal representation of this key to a binary form
- HexToBinary( (char*)(pcBuffer + 2), &pcBinaryBuffer, &dwBinaryBufferSize );
-
- // We return the secret key and the secret key size.
- CopyMemory( pcKey, pcBinaryBuffer, dwBinaryBufferSize );
- *pnKeySize = static_cast<short>(dwBinaryBufferSize);
-
- delete [] pcBinaryBuffer;
- }
- else if ( pcBuffer[0] == 'p' && pcBuffer[1] == '=' )
- {
- // It's a plain text line
-
- // Convert the hexadecimal representation of this key to a binary form
- HexToBinary( (char*)(pcBuffer + 2), &pcBinaryBuffer, &dwBinaryBufferSize );
-
- // We return the plain text and the plain text size.
- CopyMemory( pcPlainText, pcBinaryBuffer, dwBinaryBufferSize );
- *pdwPlainTextSize = dwBinaryBufferSize;
-
- delete [] pcBinaryBuffer;
- }
- else if ( pcBuffer[0] == 'c' && pcBuffer[1] == '=' )
- {
- // It's a cipher text line
-
- // Convert the hexadecimal representation of this cipher text to a binary form
- HexToBinary( (char*)(pcBuffer + 2), &pcBinaryBuffer, &dwBinaryBufferSize );
-
- // We return the cipher text and the cipher text size.
- CopyMemory( pcCipherText, pcBinaryBuffer, dwBinaryBufferSize );
- *pdwCipherTextSize = dwBinaryBufferSize;
-
- delete [] pcBinaryBuffer;
- }
- else if ( pcBuffer[0] == 'i' && pcBuffer[1] == '=' )
- {
- // It's a initialization vector line
-
- // Convert the hexadecimal representation of this InitVector to a binary form
- HexToBinary( (char*)(pcBuffer + 2), &pcBinaryBuffer, &dwBinaryBufferSize );
-
- // We return the InitVector and the InitVector size.
- CopyMemory( pcInitVector, pcBinaryBuffer, dwBinaryBufferSize );
- *pnInitVectorSize = static_cast<short>(dwBinaryBufferSize);
-
- delete [] pcBinaryBuffer;
- }
- }
-
- // Clear the temporary buffer
- dwTotalRead = 0;
- pcBuffer[0] = '\0';
-
- if( *pnKeySize && *pdwPlainTextSize && *pdwCipherTextSize )
- {
- // So far, we have read the key, the plain text and the cipher
- // text. We consider the test vector complete assuming that an
- // initialization vector would have been read before.
- bVectorComplete = true;
- break;
- }
- }
- }
- }
-
- return bVectorComplete;
- }
-
- // --------------------------------------------------------------------------
- //
- // Read a test vector from a Hash test vector file
- // returns true if succeeded.
- //
- // --------------------------------------------------------------------------
- bool ReadTestVectorHash( HANDLE hFicIn,
- BYTE* pcMessage, DWORD* pdwMessageSize,
- BYTE* pcDigest, DWORD* pdwDigestSize )
- {
- bool bVectorComplete = false;
- bool bEndOfLine = false;
- BYTE pcBuffer[MAX_MESSAGE_SIZE] = "";
- DWORD dwTotalRead = 0;
- BYTE cByteRead;
- DWORD dwRead = 0;
-
- *pdwMessageSize = 0;
- *pdwDigestSize = 0;
-
- // Read one character at a time
- while( ReadFile( hFicIn, &cByteRead, 1, &dwRead, NULL) &&
- dwRead > 0 )
- {
- // Fill the buffer
- if( dwTotalRead > sizeof( pcBuffer ) )
- {
- printf( "Buffer overflow while reading hash test vector" );
- break;
- }
-
- if( cByteRead == 13 || cByteRead == 10 )
- {
- // We reach a end of line delimiter
- bEndOfLine = true;
- }
- else
- {
- if( !bEndOfLine )
- {
- // The end of line is not reached already. We add the character
- // read to the buffer.
- pcBuffer[dwTotalRead] = cByteRead;
- pcBuffer[dwTotalRead + 1] = '\0';
- dwTotalRead++;
- }
- else
- {
- // The previous character(s) were end of line delimiter.
- // We process the previous line read.
- bEndOfLine = false;
-
- // We want to re-read the current character (the beginning of line)
- // So we move the current file pointer to the previous character.
- SetFilePointer( hFicIn, -1, 0, FILE_CURRENT );
-
- // We ignore blank lines
- if( dwTotalRead > 0 )
- {
- if ( pcBuffer[0] == '.' )
- {
- // We display this line skipping the beginning '.' which tell
- // us that it's a comment line.
- printf( "%s\n", pcBuffer + 1 );
- }
- else if ( pcBuffer[0] == 'm' && pcBuffer[1] == '=' )
- {
- // It's a "message" line (to hash)
- // Return the message and the message size
- lstrcpy( (char*)pcMessage, (char*)( pcBuffer + 2 ) );
- *pdwMessageSize = lstrlen( (char*)pcMessage );
- }
- else if ( pcBuffer[0] == 'd' && pcBuffer[1] == '=' )
- {
- // It's a message digest line (expected hash value)
-
- BYTE* pcBinaryBuffer = NULL;
- DWORD dwBinaryBufferSize = 0;
-
- // Convert the hexadecimal representation of this message digest
- // to a binary form
- HexToBinary( (char*)(pcBuffer + 2), &pcBinaryBuffer, &dwBinaryBufferSize );
-
- // We return the message digest and the message digest size.
- CopyMemory( pcDigest, pcBinaryBuffer, dwBinaryBufferSize );
- *pdwDigestSize = dwBinaryBufferSize;
-
- delete [] pcBinaryBuffer;
- }
- }
-
- //Clear the temporary buffer
- dwTotalRead = 0;
- pcBuffer[0] = '\0';
-
- if( *pdwDigestSize && *pdwMessageSize )
- {
- // So far, we have read the message and the message digest
- // We consider the test vector complete.
- bVectorComplete = true;
- break;
- }
- }
- }
- }
-
- return bVectorComplete;
- }
-
- //------------------------------------------------------------------------------------
- // Convert a hexadecimal string to a byte array
- //------------------------------------------------------------------------------------
- void HexToBinary( LPCSTR sHexValue, BYTE** pcBinValue, DWORD* dwBinValueSize )
- {
- long lHexLen = lstrlen( sHexValue );
-
- *pcBinValue = NULL;
- *dwBinValueSize = 0;
-
- if( lHexLen > 0 )
- {
- *pcBinValue = new BYTE[ lHexLen / 2 + 1 ];
- *dwBinValueSize = 0;
-
- long I = 0;
- while( I < lstrlen( sHexValue ) )
- {
- int nTemp;
-
- sscanf( sHexValue + I, "%2x", &nTemp );
- (*pcBinValue)[ *dwBinValueSize ] = (BYTE)nTemp;
- (*dwBinValueSize)++;
- I += 2;
- }
- }
- }
-
-