home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 September / Chip_2002-09_cd1.bin / zkuste / vbasic / Data / Utils / XZipComp.exe / XceedEncryption.Cab / F112979_Hash.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-07-03  |  12.1 KB  |  382 lines

  1. /* Xceed Encryption Library - Hash Sample Application
  2.  * Copyright (c) 2001 Xceed Software Inc.
  3.  *
  4.  * [Hash.cpp]
  5.  *
  6.  * This console application shows how to hash a file, using different
  7.  * hashing methods. It specifically demonstrates:
  8.  *  - The ReadFile and Hash methods.
  9.  *  - The HashingMethod, HashSize and HashValue properties.
  10.  *
  11.  * [Example]
  12.  *
  13.  * The following command-line hashes file "source.bmp", and writes the
  14.  * hashing code in file "source.hash.txt".
  15.  *
  16.  *   HASH source.bmp source.hash.txt
  17.  *
  18.  * The following command-line hashes all console data you type, and 
  19.  * writes the hashing code in file "hash.txt".
  20.  *
  21.  *   HASH hash.txt
  22.  *
  23.  * This file is part of the Xceed Encryption Library sample 
  24.  * applications. The source code in this file is only intended as 
  25.  * a supplement to Xceed Encryption Library's documentation, 
  26.  * and is provided "as is", without warranty of any kind, either 
  27.  * expressed or implied. 
  28.  */
  29.  
  30. #include "stdafx.h"
  31. #include "Hash.h"
  32.  
  33. #include "utility.h"
  34.  
  35. //
  36. // Mapping between command-line and property values
  37. //
  38.  
  39. static SHashingMethod g_pxHashingMethods[] = 
  40. {
  41.   { "=SHA",   hmSHA },
  42.   { "=Haval", hmHaval }
  43. };
  44.  
  45.  
  46. //
  47. // Entry point of the application
  48. //
  49.  
  50. int main(int argc, char* argv[])
  51. {
  52.   CoInitialize( NULL );
  53.  
  54.   try
  55.   {
  56.     // Create an instance of the XceedHashing coclass, and
  57.     // use the "I" interface which manipulates byte arrays instead of
  58.     // Variants as the "D" interface does.
  59.     IXceedHashingPtr piHash;
  60.     piHash.CreateInstance( CLSID_XceedHashing );
  61.  
  62.     // Two BSTR variables that will contain the Input and Output file names.
  63.     _bstr_t bstrInputFileName;
  64.     _bstr_t bstrOutputFileName;
  65.  
  66.     // Extract the command line parameters and initialize the XceedHashing 
  67.     // instance piHash refers, according to the user specification. After 
  68.     // this call the instance is ready to hash.
  69.     if( !ExtractParameters( argc, argv, 
  70.                             piHash,
  71.                             bstrInputFileName, 
  72.                             bstrOutputFileName ) )
  73.     {
  74.       // There was an error extracting the command-line parameters or the
  75.       // user requested some help.
  76.       ShowHelp();
  77.       return 1;
  78.     }
  79.  
  80.     if( bstrInputFileName.length() == 0 )
  81.     {
  82.       // An input file name was not provided by the user.
  83.       // Get the source from the console
  84.  
  85.       printf( "Hashing from the console input. Press Ctrl-Z and Enter when done.\n\n" );
  86.  
  87.       char pcBuffer[ BUFFER_SIZE ];
  88.  
  89.       while( !feof( stdin ) )
  90.       {
  91.         // Read BUFFER_SIZE characters at a time from the console.
  92.         int nRead = fread( pcBuffer, sizeof( char ), BUFFER_SIZE, stdin );
  93.  
  94.         if( nRead )
  95.         {
  96.           // Hash the buffer read so far.
  97.           // We specify :
  98.           //  - The source buffer, with the size, since we want
  99.           //    to hash all the source buffer.
  100.           //  - The bEndOfData parameter set to FALSE, since we do the
  101.           //    processing in multiple block.
  102.           piHash->Hash( ( BYTE* )pcBuffer, nRead, FALSE );
  103.         }
  104.       }
  105.  
  106.       // Since we always called with bEndOfData to FALSE, we must
  107.       // make sure to flush the remaining data.
  108.       piHash->Hash( NULL, 0, TRUE );
  109.  
  110.       if( SaveHashToFile( bstrOutputFileName, piHash ) )
  111.       {
  112.         printf( "Successfully hashed the console input to file %s\n", ( const char* )bstrOutputFileName );
  113.       }
  114.     }
  115.     else
  116.     {
  117.       // An input file name was provided by the user.
  118.       // Read the input file and output the result to the specified file
  119.  
  120.       DWORD dwBytesRead     = 0;
  121.  
  122.       // Hash by reading a file.
  123.       // We specify :
  124.       //  - The source filename, without any offset or size, since we want
  125.       //    to hash all the source file.
  126.       //  - The processing we want to perform, in this case efpHash.
  127.       //  - The bEndOfData parameter set to TRUE, since we do all the
  128.       //    processing in a single block.
  129.       //  - The address of a DWORD that will receive the number of bytes
  130.       //    actually read from the source.
  131.       piHash->ReadFile( bstrInputFileName, 0, 0, efpHash, TRUE, &dwBytesRead );
  132.  
  133.       if( SaveHashToFile( bstrOutputFileName, piHash ) )
  134.       {
  135.         // Write the hashing statistics to the screen. 
  136.         printf( "Successfully hashed the file %s [%d] to file %s\n", 
  137.                 ( const char* )bstrInputFileName, dwBytesRead, 
  138.                 ( const char* )bstrOutputFileName );
  139.       }
  140.     }
  141.   }
  142.   catch( const _com_error& err )
  143.   {
  144.     // When using the "#import" directive, the compiler generates wrapper classes
  145.     // around all interface types. These wrapper classes throw exceptions when
  146.     // a method call returns an HRESULT which is a failure code.
  147.     printf( "Error %08x: %s\n", err.Error(), ( const char* )err.Description() );
  148.   }
  149.   catch( ... )
  150.   {
  151.     // Catch any other exceptions
  152.     printf( "An unknown error occured.\n" );
  153.   }
  154.  
  155.   // Close the COM library for the current thread
  156.   CoUninitialize();
  157.  
  158.     return 0;
  159. }
  160.  
  161. //--------------------------------------------------------------------------
  162. // Display usage information
  163. //--------------------------------------------------------------------------
  164. void ShowHelp()
  165. {
  166.   //      "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
  167.   printf( "Usage: Hash [options] [input_file] output_file\n\n"
  168.           "  input_file: the file to hash\n"
  169.           "  output_file: the destination file that will contain the hash value\n\n"
  170.           "  options: /m=[SHA | Haval]\n"
  171.           "              This is the hashing method. The default is 'SHA'\n"
  172.           "           /s=hash_size\n\n"
  173.           "              This is the size of the hash value produced by the hashing.\n" 
  174.           "              The accepted values are : for SHA : [160], 256, 384, 512;\n"
  175.           "                                        for Haval : [128], 160, 192, 224, 256.\n"
  176.           "              (default values are between brackets [])\n"
  177.           "           /h or /? : Show this help\n" );
  178. }
  179.  
  180. //--------------------------------------------------------------------------
  181. // Extract commands from the parameters
  182. //
  183. // In this function, we call the piHash interface and let exceptions
  184. // be caught by the caller.
  185. // This function returns false if an error occured parsing the command
  186. // line parameters or if the user requested help.
  187. //--------------------------------------------------------------------------
  188. bool ExtractParameters( int argc, char* argv[],
  189.                         IXceedHashingPtr piHash, 
  190.                         _bstr_t& bstrInputFileName,
  191.                         _bstr_t& bstrOutputFileName )
  192. {
  193.   // The variables used to initialize the Hashing Method property
  194.   // are set, here, to their default values.
  195.   SHashingMethod*  pxMethod = g_pxHashingMethods;
  196.   short            nHashSize = 0;
  197.   bool             bFound;
  198.  
  199.   // We parse each command line parameter
  200.   int   i = 0;
  201.   while( ++i < argc )
  202.   {
  203.     if( argv[ i ][ 0 ] == '/' )
  204.     {
  205.       // The parameter starts with a /
  206.       // Meaning it's an option parameter
  207.       switch( argv[ i ][ 1 ] )
  208.       {
  209.         case 'm':
  210.         case 'M':
  211.           // The user wants to set the hashing method
  212.           bFound = false;
  213.  
  214.           // We go through all the hashing methods in the 
  215.           // correspondence table, stopping when we find a 
  216.           // match.
  217.           for( pxMethod = g_pxHashingMethods;
  218.                pxMethod->pszCommandLine != NULL;
  219.                pxMethod++ )
  220.           {
  221.             if( lstrcmpi( argv[ i ] + 2, pxMethod->pszCommandLine ) == 0 )
  222.             {
  223.               bFound = true;
  224.               break;
  225.             }
  226.           }
  227.  
  228.           if( !bFound )
  229.           {
  230.             printf( "Invalid hashing method '%s'\n\n", argv[ i ] );
  231.             return false;
  232.           }
  233.  
  234.           break;
  235.  
  236.         case 's':
  237.         case 'S':
  238.           // The user wants to set the hash size
  239.           if( argv[i][2] != '=' )
  240.           {
  241.             printf("You did not specify the hash size value\n");
  242.             return false;
  243.           }
  244.  
  245.           nHashSize = atoi( argv[i] + 3 );
  246.           break;
  247.  
  248.         default:
  249.           printf( "Unknown command '%s'\n\n", argv[ i ] );
  250.           // Continue
  251.         case 'h':
  252.         case 'H':
  253.         case '?':
  254.           return false;
  255.       }
  256.     }
  257.   }
  258.  
  259.   // Check if the user provided an output file name
  260.   if( argc < 2 || argv[ argc - 1 ][ 0 ] == '/' || argv[ argc - 2 ][ 0 ] == '/' )
  261.   {
  262.     printf( "You did not specify an output filename\n\n" );
  263.     return false;
  264.   }
  265.   else if( argc < 3 || argv[ argc - 2 ][ 0 ] == '/' )
  266.   {
  267.     // Only an output file was specified
  268.     bstrOutputFileName = argv[ argc - 1 ];
  269.   }
  270.   else
  271.   {
  272.     // Both input and output file were specified
  273.     bstrInputFileName   = argv[ argc - 2 ];
  274.     bstrOutputFileName  = argv[ argc - 1 ];
  275.   }
  276.  
  277.   // According the hashing method chosen by the user, we set the HashSize
  278.   // property of an hashing method and prepare the Hashing interface (piHash).
  279.  
  280.   // For each hashing method, we begin by creating a temporary instance 
  281.   // of the appropriate hashing method. The HashSize property of this instance
  282.   // is then set and the instance is assign to the HashingMethod property
  283.   // of the XceedHashing instance. This adds a reference to the 
  284.   // Hashing method instance so that the instance will not be freed
  285.   // when it will fall out of scope.
  286.  
  287.   switch( pxMethod->eMethod )
  288.   {
  289.     case hmSHA :
  290.     {
  291.       IXceedSHAHashingMethodPtr piSHAMethod;
  292.  
  293.       piSHAMethod.CreateInstance( CLSID_XceedSHAHashingMethod );
  294.  
  295.       if( nHashSize > 0 )
  296.       {
  297.         // Set the hash size specified by the user
  298.         piSHAMethod->PutHashSize( nHashSize );
  299.       }
  300.  
  301.       piHash->HashingMethod = IXceedHashDataPtr( piSHAMethod );
  302.     }
  303.     break;
  304.  
  305.     case hmHaval :
  306.     {
  307.       IXceedHavalHashingMethodPtr piHavalMethod;
  308.  
  309.       piHavalMethod.CreateInstance( CLSID_XceedHavalHashingMethod );
  310.  
  311.       if( nHashSize > 0 )
  312.       {
  313.         // Set the hash size specified by the user
  314.         piHavalMethod->PutHashSize( nHashSize );
  315.       }
  316.  
  317.       piHash->HashingMethod = IXceedHashDataPtr( piHavalMethod );
  318.     }
  319.     break;
  320.   }
  321.  
  322.   return true;
  323. }
  324.  
  325. //--------------------------------------------------------------------------
  326. // Extract the calculated hash value from the XceedHashing object and
  327. // save it to the specified file
  328. //--------------------------------------------------------------------------
  329. bool SaveHashToFile( _bstr_t bstrOutputFileName, 
  330.                      IXceedHashingPtr piHash )
  331. {
  332.   BYTE* pcHash = NULL;
  333.   short nHashSize = 0;
  334.   IXceedHashDataPtr piHashData;
  335.   IXceedSHAHashingMethodPtr piSHA;
  336.  
  337.   // We need the HashingMethod instance (SHA or Haval to get the HashValue.
  338.   // We use the GetHashingMethod which returns an instance of IXceedHashData (used
  339.   // internally by the Xceed Encryption Library).
  340.   piHashData = piHash->GetHashingMethod();
  341.  
  342.   // We affect the instance of IXceedHashData to a IXceedSHAHashingMethod
  343.   // This is equivalent to piHashData->QueryInterface( IID_IXceedSHAHAshingMethod, &piSHA );
  344.   piSHA = piHashData;
  345.   if( piSHA == NULL )
  346.   {
  347.     IXceedHavalHashingMethodPtr piHaval;
  348.  
  349.     // The QueryInterface failed. The HashingMethod is not a SHAHashingMethod.
  350.     // We affect the instance of IXceedHashData to a IXceedHavalHashingMethod
  351.     piHaval = piHashData;
  352.     if( piHaval == NULL )
  353.     {
  354.       // The HashingMethod is not SHA nor Haval. We return an error.
  355.       printf( "Unkown HashingMethod instance\n" );
  356.       return false;
  357.     }
  358.     else
  359.     {
  360.       // We extract the HashValue calculated by Haval
  361.       piHaval->GetHashValue( &pcHash, &nHashSize );
  362.     }
  363.   }
  364.   else
  365.   {
  366.     // We extract the HashValue calculated by SHA
  367.     piSHA->GetHashValue( &pcHash, &nHashSize );
  368.   }
  369.  
  370.   // Save the hash value to the file in hexadecimal.
  371.   bool bSuccess = WriteHexValueToFile( bstrOutputFileName, pcHash, nHashSize );
  372.   
  373.   // Free the memory used by the hash value
  374.   CoTaskMemFree( pcHash );
  375.  
  376.   return bSuccess;
  377. }
  378.  
  379. //
  380. // END_OF_FILE
  381. //
  382.