home *** CD-ROM | disk | FTP | other *** search
- /* Xceed Encryption Library - Hash Sample Application
- * Copyright (c) 2001 Xceed Software Inc.
- *
- * [Hash.cpp]
- *
- * This console application shows how to hash a file, using different
- * hashing methods. It specifically demonstrates:
- * - The ReadFile and Hash methods.
- * - The HashingMethod, HashSize and HashValue properties.
- *
- * [Example]
- *
- * The following command-line hashes file "source.bmp", and writes the
- * hashing code in file "source.hash.txt".
- *
- * HASH source.bmp source.hash.txt
- *
- * The following command-line hashes all console data you type, and
- * writes the hashing code in file "hash.txt".
- *
- * HASH hash.txt
- *
- * 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 "Hash.h"
-
- #include "utility.h"
-
- //
- // Mapping between command-line and property values
- //
-
- static SHashingMethod g_pxHashingMethods[] =
- {
- { "=SHA", hmSHA },
- { "=Haval", hmHaval }
- };
-
-
- //
- // Entry point of the application
- //
-
- int main(int argc, char* argv[])
- {
- CoInitialize( NULL );
-
- try
- {
- // Create an instance of the XceedHashing coclass, and
- // use the "I" interface which manipulates byte arrays instead of
- // Variants as the "D" interface does.
- IXceedHashingPtr piHash;
- piHash.CreateInstance( CLSID_XceedHashing );
-
- // Two BSTR variables that will contain the Input and Output file names.
- _bstr_t bstrInputFileName;
- _bstr_t bstrOutputFileName;
-
- // Extract the command line parameters and initialize the XceedHashing
- // instance piHash refers, according to the user specification. After
- // this call the instance is ready to hash.
- if( !ExtractParameters( argc, argv,
- piHash,
- bstrInputFileName,
- bstrOutputFileName ) )
- {
- // There was an error extracting the command-line parameters or the
- // user requested some help.
- ShowHelp();
- return 1;
- }
-
- if( bstrInputFileName.length() == 0 )
- {
- // An input file name was not provided by the user.
- // Get the source from the console
-
- printf( "Hashing from the console input. Press Ctrl-Z and Enter when done.\n\n" );
-
- char pcBuffer[ BUFFER_SIZE ];
-
- while( !feof( stdin ) )
- {
- // Read BUFFER_SIZE characters at a time from the console.
- int nRead = fread( pcBuffer, sizeof( char ), BUFFER_SIZE, stdin );
-
- if( nRead )
- {
- // Hash the buffer read so far.
- // We specify :
- // - The source buffer, with the size, since we want
- // to hash all the source buffer.
- // - The bEndOfData parameter set to FALSE, since we do the
- // processing in multiple block.
- piHash->Hash( ( BYTE* )pcBuffer, nRead, FALSE );
- }
- }
-
- // Since we always called with bEndOfData to FALSE, we must
- // make sure to flush the remaining data.
- piHash->Hash( NULL, 0, TRUE );
-
- if( SaveHashToFile( bstrOutputFileName, piHash ) )
- {
- printf( "Successfully hashed the console input to file %s\n", ( const char* )bstrOutputFileName );
- }
- }
- else
- {
- // An input file name was provided by the user.
- // Read the input file and output the result to the specified file
-
- DWORD dwBytesRead = 0;
-
- // Hash by reading a file.
- // We specify :
- // - The source filename, without any offset or size, since we want
- // to hash all the source file.
- // - The processing we want to perform, in this case efpHash.
- // - The bEndOfData parameter set to TRUE, since we do all the
- // processing in a single block.
- // - The address of a DWORD that will receive the number of bytes
- // actually read from the source.
- piHash->ReadFile( bstrInputFileName, 0, 0, efpHash, TRUE, &dwBytesRead );
-
- if( SaveHashToFile( bstrOutputFileName, piHash ) )
- {
- // Write the hashing statistics to the screen.
- printf( "Successfully hashed the file %s [%d] to file %s\n",
- ( const char* )bstrInputFileName, dwBytesRead,
- ( const char* )bstrOutputFileName );
- }
- }
- }
- catch( const _com_error& err )
- {
- // When using the "#import" directive, the compiler generates wrapper classes
- // around all interface types. These wrapper classes throw exceptions when
- // a method call returns an HRESULT which is a failure code.
- printf( "Error %08x: %s\n", err.Error(), ( const char* )err.Description() );
- }
- catch( ... )
- {
- // Catch any other exceptions
- printf( "An unknown error occured.\n" );
- }
-
- // Close the COM library for the current thread
- CoUninitialize();
-
- return 0;
- }
-
- //--------------------------------------------------------------------------
- // Display usage information
- //--------------------------------------------------------------------------
- void ShowHelp()
- {
- // "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
- printf( "Usage: Hash [options] [input_file] output_file\n\n"
- " input_file: the file to hash\n"
- " output_file: the destination file that will contain the hash value\n\n"
- " options: /m=[SHA | Haval]\n"
- " This is the hashing method. The default is 'SHA'\n"
- " /s=hash_size\n\n"
- " This is the size of the hash value produced by the hashing.\n"
- " The accepted values are : for SHA : [160], 256, 384, 512;\n"
- " for Haval : [128], 160, 192, 224, 256.\n"
- " (default values are between brackets [])\n"
- " /h or /? : Show this help\n" );
- }
-
- //--------------------------------------------------------------------------
- // Extract commands from the parameters
- //
- // In this function, we call the piHash interface and let exceptions
- // be caught by the caller.
- // This function returns false if an error occured parsing the command
- // line parameters or if the user requested help.
- //--------------------------------------------------------------------------
- bool ExtractParameters( int argc, char* argv[],
- IXceedHashingPtr piHash,
- _bstr_t& bstrInputFileName,
- _bstr_t& bstrOutputFileName )
- {
- // The variables used to initialize the Hashing Method property
- // are set, here, to their default values.
- SHashingMethod* pxMethod = g_pxHashingMethods;
- short nHashSize = 0;
- bool bFound;
-
- // We parse each command line parameter
- int i = 0;
- while( ++i < argc )
- {
- if( argv[ i ][ 0 ] == '/' )
- {
- // The parameter starts with a /
- // Meaning it's an option parameter
- switch( argv[ i ][ 1 ] )
- {
- case 'm':
- case 'M':
- // The user wants to set the hashing method
- bFound = false;
-
- // We go through all the hashing methods in the
- // correspondence table, stopping when we find a
- // match.
- for( pxMethod = g_pxHashingMethods;
- pxMethod->pszCommandLine != NULL;
- pxMethod++ )
- {
- if( lstrcmpi( argv[ i ] + 2, pxMethod->pszCommandLine ) == 0 )
- {
- bFound = true;
- break;
- }
- }
-
- if( !bFound )
- {
- printf( "Invalid hashing method '%s'\n\n", argv[ i ] );
- return false;
- }
-
- break;
-
- case 's':
- case 'S':
- // The user wants to set the hash size
- if( argv[i][2] != '=' )
- {
- printf("You did not specify the hash size value\n");
- return false;
- }
-
- nHashSize = atoi( argv[i] + 3 );
- break;
-
- default:
- printf( "Unknown command '%s'\n\n", argv[ i ] );
- // Continue
- case 'h':
- case 'H':
- case '?':
- return false;
- }
- }
- }
-
- // Check if the user provided an output file name
- if( argc < 2 || argv[ argc - 1 ][ 0 ] == '/' || argv[ argc - 2 ][ 0 ] == '/' )
- {
- printf( "You did not specify an output filename\n\n" );
- return false;
- }
- else if( argc < 3 || argv[ argc - 2 ][ 0 ] == '/' )
- {
- // Only an output file was specified
- bstrOutputFileName = argv[ argc - 1 ];
- }
- else
- {
- // Both input and output file were specified
- bstrInputFileName = argv[ argc - 2 ];
- bstrOutputFileName = argv[ argc - 1 ];
- }
-
- // According the hashing method chosen by the user, we set the HashSize
- // property of an hashing method and prepare the Hashing interface (piHash).
-
- // For each hashing method, we begin by creating a temporary instance
- // of the appropriate hashing method. The HashSize property of this instance
- // is then set and the instance is assign to the HashingMethod property
- // of the XceedHashing instance. This adds a reference to the
- // Hashing method instance so that the instance will not be freed
- // when it will fall out of scope.
-
- switch( pxMethod->eMethod )
- {
- case hmSHA :
- {
- IXceedSHAHashingMethodPtr piSHAMethod;
-
- piSHAMethod.CreateInstance( CLSID_XceedSHAHashingMethod );
-
- if( nHashSize > 0 )
- {
- // Set the hash size specified by the user
- piSHAMethod->PutHashSize( nHashSize );
- }
-
- piHash->HashingMethod = IXceedHashDataPtr( piSHAMethod );
- }
- break;
-
- case hmHaval :
- {
- IXceedHavalHashingMethodPtr piHavalMethod;
-
- piHavalMethod.CreateInstance( CLSID_XceedHavalHashingMethod );
-
- if( nHashSize > 0 )
- {
- // Set the hash size specified by the user
- piHavalMethod->PutHashSize( nHashSize );
- }
-
- piHash->HashingMethod = IXceedHashDataPtr( piHavalMethod );
- }
- break;
- }
-
- return true;
- }
-
- //--------------------------------------------------------------------------
- // Extract the calculated hash value from the XceedHashing object and
- // save it to the specified file
- //--------------------------------------------------------------------------
- bool SaveHashToFile( _bstr_t bstrOutputFileName,
- IXceedHashingPtr piHash )
- {
- BYTE* pcHash = NULL;
- short nHashSize = 0;
- IXceedHashDataPtr piHashData;
- IXceedSHAHashingMethodPtr piSHA;
-
- // We need the HashingMethod instance (SHA or Haval to get the HashValue.
- // We use the GetHashingMethod which returns an instance of IXceedHashData (used
- // internally by the Xceed Encryption Library).
- piHashData = piHash->GetHashingMethod();
-
- // We affect the instance of IXceedHashData to a IXceedSHAHashingMethod
- // This is equivalent to piHashData->QueryInterface( IID_IXceedSHAHAshingMethod, &piSHA );
- piSHA = piHashData;
- if( piSHA == NULL )
- {
- IXceedHavalHashingMethodPtr piHaval;
-
- // The QueryInterface failed. The HashingMethod is not a SHAHashingMethod.
- // We affect the instance of IXceedHashData to a IXceedHavalHashingMethod
- piHaval = piHashData;
- if( piHaval == NULL )
- {
- // The HashingMethod is not SHA nor Haval. We return an error.
- printf( "Unkown HashingMethod instance\n" );
- return false;
- }
- else
- {
- // We extract the HashValue calculated by Haval
- piHaval->GetHashValue( &pcHash, &nHashSize );
- }
- }
- else
- {
- // We extract the HashValue calculated by SHA
- piSHA->GetHashValue( &pcHash, &nHashSize );
- }
-
- // Save the hash value to the file in hexadecimal.
- bool bSuccess = WriteHexValueToFile( bstrOutputFileName, pcHash, nHashSize );
-
- // Free the memory used by the hash value
- CoTaskMemFree( pcHash );
-
- return bSuccess;
- }
-
- //
- // END_OF_FILE
- //
-