Important:
This is retired content. This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This content may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.
A version of this page is also available for
4/8/2010

If a message was encoded for a particular user, the CryptGenKeyfunction was used to create a random session key before the encryption was performed. Before decoding the message, the key BLOB containing the session key must be imported into the CSP with the CryptImportKeyfunction. This function uses the user's key exchange private key to decode the key BLOB and ensure that the originating key BLOB was created using the matching key exchange public key.

If the message was encoded so that any password holder can access the data, CryptImportKeyis not used. Instead, create the decryption session key with the CryptDeriveKeyfunction. You also need to supply the function with the password or other access token.

The session key's parameters must be configured in the same way as when the encryption was performed. These parameters can be specified using the CryptSetKeyParamfunction. For example, if the salt value was changed one or more times during the encryption process, it must also be changed during the decryption process in exactly the same manner.

The message is decoded using the CryptDecryptfunction. If the message is too large to fit comfortably in memory, it can be decoded in sections, through multiple calls to CryptDecrypt.

When the decryption is complete, be sure to destroy the session key, using the CryptDestroyKeyfunction. In addition to destroying the key, this frees CSP resources.

The following code example shows how to decode the file created in Sample Code: Encrypting a File. This decryption example uses the RC2 block cipher and writes out the plaintext data to a file named Test2.txt. The session key used to perform the decryption is read from the cipher file.

Copy Code
#include <windows.h>
#include <stdio.h>
#include <wincrypt.h>
   
#define BLOCK_SIZE			1000
#define BUFFER_SIZE		 1008

BOOL DecryptFile (LPTSTR, LPTSTR, LPTSTR);

/***********************************************************************

  WinMain

***********************************************************************/
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, 
					LPTSTR lpCmdLine, int nCmdShow)			
  
{
  LPTSTR lpszSource  = TEXT("test.xxx");
  LPTSTR lpszDestination = TEXT("test2.txt");
  LPTSTR lpszPassword  = TEXT("password");
 
  if (!DecryptFile (lpszSource, lpszDestination, lpszPassword)) 
  {
	wprintf (TEXT("Error encrypting file!\n"));
	return 1;
  }

  return 0;
}

/***********************************************************************

  DecryptFile

***********************************************************************/
BOOL DecryptFile (LPTSTR lpszSource, LPTSTR lpszDestination, 
				LPTSTR lpszPassword)
{
  FILE *hSrcFile = NULL, 
	 *hDestFile = NULL;

  HCRYPTPROV hProv = 0;
  HCRYPTHASH hHash = 0;
  HCRYPTKEY hKey = 0;

  PBYTE pbBuffer = NULL, 
		pbKeyBlob = NULL;

  BOOL bEOF = 0, 
	 bReturn = FALSE;

  DWORD dwCount, 
		dwKeyBlobLen;

  // Open the source file.
  if ((hSrcFile = _wfopen (lpszSource, TEXT("rb"))) == NULL) 
  {
	wprintf (TEXT("Error opening Ciphertext file!\n"));
	goto exit;
  }

  // Open the destination file.
  if ((hDestFile = _wfopen (lpszDestination, TEXT("wb"))) == NULL) 
  {
	wprintf (TEXT("Error opening Plaintext file!\n"));
	goto exit;
  }

  // Get the handle to the default provider.
  if (!CryptAcquireContext (&hProv, NULL, NULL, PROV_RSA_FULL,
0)) 
  {
	DWORD ret = GetLastError();
	if (ret !=  NTE_BAD_KEYSET)
	{
			wprintf (TEXT("Error 0x%x during
CryptAcquireContext!\n"), 
				ret);
			goto exit;
}
	else
	{
		if (!CryptAcquireContext (&hProv, NULL, NULL,
PROV_RSA_FULL, CRYPT_NEWKEYSET)) 
		{
			wprintf (TEXT("Error 0x%x during
CryptAcquireContext!\n"), 
				GetLastError());
			goto exit;
	}
}
  }
 

  if (lpszPassword == NULL) 
  {
	// Decrypt the file with the saved session key.
	// Read key BLOB length from the source file and allocate
memory.
	fread (&dwKeyBlobLen, sizeof (DWORD), 1, hSrcFile);
	if (ferror (hSrcFile) || feof (hSrcFile)) 
	{
	wprintf (TEXT("Error reading file header!\n"));
	goto exit;
}

	if ((pbKeyBlob = (PBYTE)malloc (dwKeyBlobLen)) == NULL) 
	{
	wprintf (TEXT("Out of memory or improperly formatted source
")
			 TEXT("file!\n"));
	goto exit;
}

	// Read the key BLOB from source file.
	fread (pbKeyBlob, 1, dwKeyBlobLen, hSrcFile);

	if (ferror (hSrcFile) || feof (hSrcFile)) 
	{
	wprintf (TEXT("Error reading file header!\n"));
	goto exit;
}

	// Import the key BLOB into the CSP.
	if (!CryptImportKey (hProv, pbKeyBlob, dwKeyBlobLen, 0, 0,
&hKey)) 
	{
	wprintf (TEXT("Error %x during CryptImportKey!\n"), 
			 GetLastError ());
	goto exit;
}
  } 
  else
  {
	// Decrypt the file with a session key derived from a password.
	// Create a hash object.
	if (!CryptCreateHash (hProv, CALG_MD5, 0, 0, &hHash)) 
	{
	wprintf (TEXT("Error %x during CryptCreateHash!\n"), 
			 GetLastError ());
	goto exit;
}
 
	// Hash in the password data.
	if (!CryptHashData (hHash, (PBYTE)lpszPassword, 
						wcslen (lpszPassword), 0)) 
	{
	wprintf (TEXT("Error %x during CryptHashData!\n"), 
			 GetLastError ());
	goto exit;
}

	// Derive a session key from the hash object.
	if (!CryptDeriveKey (hProv, CALG_RC2, hHash, 0, &hKey)) 
	{
	wprintf (TEXT("Error %x during CryptDeriveKey!\n"), 
			 GetLastError ());
	goto exit;
}
  }
 
  // Allocate memory.
  if ((pbBuffer = (PBYTE)malloc (BUFFER_SIZE)) == NULL) 
  {
	wprintf (TEXT("Out of memory!\n"));
	goto exit;
  }

  // Decrypt the source file and write to the destination file.
  do 
  {
	// Read up to BLOCK_SIZE bytes from the source file.
	dwCount = fread (pbBuffer, 1, BLOCK_SIZE, hSrcFile);

	if (ferror (hSrcFile)) 
	{
	wprintf (TEXT("Error reading Ciphertext!\n"));
	goto exit;
}

	bEOF = feof (hSrcFile);

	// Decrypt the data.
	if (!CryptDecrypt (hKey, 0, bEOF, 0, pbBuffer, &dwCount)) 
	{
	wprintf (TEXT("Error %x during CryptDecrypt!\n"), 
			 GetLastError ());
	goto exit;
}

	// Write the data to the destination file.
	fwrite (pbBuffer, 1, dwCount, hDestFile);
	if (ferror (hDestFile)) 
	{
	wprintf (TEXT("Error writing Plaintext!\n"));
	goto exit;
}
  } while (!bEOF);

  bReturn = TRUE;
  wprintf (TEXT("OK\n"));

exit:
  // Close the source files.
  if (hSrcFile) fclose (hSrcFile);
  if (hDestFile) fclose (hDestFile);

  // Free memory.
  if (pbKeyBlob) free (pbKeyBlob);
  if (pbBuffer) free (pbBuffer);

  // Destroy the session key.
  if (hKey) CryptDestroyKey (hKey);

  // Destroy the hash object.
  if (hHash) CryptDestroyHash (hHash);

  // Release the provider handle.
  if (hProv) CryptReleaseContext (hProv, 0);

  return bReturn;
}

See Also