⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 crypto.cpp

📁 使用Windows加密API的例子
💻 CPP
📖 第 1 页 / 共 3 页
字号:
////////////////////////////////////////////////////////////////////////////////
//
//	Title:		Cryptography Object
//	File:		TSDocCrypto.cpp
//	Author:		Chad Slater
//	Date:		January 2001
//
//	Current Encrypted File Binary Format:
//---------------------------------------
//
//	+-----------+
//	|  4 BYTES	| <-- Binary format version (reserved)
//	|-----------|
//	|  4 BYTES	| <-- Size of the private key
//	|-----------|
//	|			|
//	| VARIABLE	| <-- Private key (typically ~76 bytes)
//	|   SIZE	|
//	|___________|
//	|			|
//	| VARIABLE	|
//	|	SIZE	| <-- Encrypted data
//	|			|
//	|-----------|
//	|	 EOF	|
//	|___________|
//
//
//	Current String Binary Format (In-memory Encryption):
//-----------------------------------------------------
//		
// +---------------+
// | BASE64 ENCODED|<---- Base64 Encoded BSTR
// |    WRAPPER	   |
// | +-----------+ |
// | |  4 BYTES	 |<---- Binary format version (reserved)
// | |-----------| |
// | |  4 BYTES	 |<---- Size of the private key
// | |-----------| |
// | |			 | |
// | | VARIABLE	 |<---- Private key (typically ~76 bytes)
// | |   SIZE	 | |
// | |-----------| |
// | |  4 BYTES	 |<---- Size of the encrypted data
// | |-----------| |
// | |			 | |
// | | VARIABLE	 | |
// | |	SIZE	 |<---- Encrypted data
// | |___________| |
// |_______________|
//
//
//	Revision History:
//	---------------------------------------------------------------------
//
//	cslater		01/26/2001	Initial revision
//	cslater		01/29/2001	Implemented EncryptDoc and DecryptDoc
//	cslater		01/30/2001	Initial attempt at in-memory encryption with 
//							128-bit encryption + Base64 encoding (failed...)
//	cslater		01/31/2001	Fixed the in-memory encryption algorithms so they
//							actually work (royal pain in the neck)
//	cslater		02/01/2001	Fixed memory leaks
//	cslater		02/02/2001  Added Base64EncodeFile and Base64DecodeFile
//	cslater		02/06/2001	Added Base64EncodeFileToString and
//								  Base64DecodeFileToString
//
//
///////////////////////////////////////////////////////////////////////////////


#include "stdafx.h"
#include "Base64Helper.h"
#include "Common.h"
#include "Crypto.h"


	//	Types
typedef		BYTE*							LPBYTE;


	//	Algorithm to use for encryption
#define		FILE_ENCRYPT_ALGORITHM			CALG_RC2 
#define		INMEMORY_ENCRYPT_ALGORITHM		CALG_RC4
#define		HASHING_ALGORITHM				CALG_MD5

	//	Key container name - Unique per application
#define		CRYPTO_KEY_CONTAINER_NAME		_T("ICRYPTO_VERSION_1_0")

	//	Binary file format version (encrypted files)
#define		INVALID_FORMAT_VERSION			0xFFFFFFFF
#define		BINARY_FORMAT_MAJOR_VERSION		((WORD)0x0001)
#define		BINARY_FORMAT_MINOR_VERSION		((WORD)0x0000)
#define		FILE_BINARY_FORMAT_VERSION		MAKELONG(BINARY_FORMAT_MINOR_VERSION,\
													 BINARY_FORMAT_MAJOR_VERSION)
#define		INMEMORY_FORMAT_VERSION			MAKELONG(BINARY_FORMAT_MINOR_VERSION,\
													 BINARY_FORMAT_MAJOR_VERSION)

	//	General defines
#define		FILE_INTERMEDIATE_FILENAME		"INTERMEDIATE.CRP"
#define		FILE_READBYTES					0x00000200
#define		SIZE_VERSION					sizeof(DWORD)
#define		SIZE_PRIVATEKEY_SIZE			sizeof(DWORD)
#define		SIZE_ENCRYPTED_DATA				sizeof(DWORD)

	//	General macros
#define		VERIFY_MALLOC(lpData)			{\
											if(!lpData)\
												nStringID=IDS_ERROR_OUTOFMEMORY,\
												THROW_HRESULT( E_OUTOFMEMORY );\
											}

#define		CRYPTO_OUTPUT_DEBUGSTRING(nStringID) {\
													{\
													TCHAR	szMessage[ MAX_MSG ] = { 0 }; \
													if(::LoadString( _Module.GetResourceInstance(),\
																	 nStringID,\
																	 szMessage,\
																	 MAX_MSG ) ) \
														::OutputDebugString( szMessage ); \
													}\
												}

CCrypto::
CCrypto()
	:
	m_hContext( NULL ),
	m_lpDigitalSignature( NULL ),
	m_dwDigitalSignatureLen( 0 ),
	m_bstrContainerName( CRYPTO_KEY_CONTAINER_NAME )
	{}


CCrypto::
~CCrypto()
	{
	if( m_hContext )
		{
		CryptReleaseContext( m_hContext, 0 );
		m_hContext = NULL;
		}
	ClearDigitalSignature();	
	}


STDMETHODIMP CCrypto::
InterfaceSupportsErrorInfo( REFIID riid )
	{
	static const IID* arr[] =  { &IID_ICrypto };
	for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
		{
		if( ::InlineIsEqualGUID( *arr[i], riid ) )
			return S_OK;
		}
	return S_FALSE;
	}


STDMETHODIMP CCrypto::
get_DigitalSignature( BSTR* pVal )
	{
	HRESULT hr				= E_FAIL;
	HGLOBAL hDigSig			= NULL;
	LPBYTE	lpEncodedBytes	= NULL; 
	
	ATLASSERT( pVal );
	if( pVal )
		{
		if( m_lpDigitalSignature	&&
			m_dwDigitalSignatureLen > 0 )
			{
			PBYTE			lpEncodedDigSig	=	NULL;
			DWORD			dwEncodedDigSig =   0;
			CBase64Helper	Base64;

				//	Encode the digital signature
			dwEncodedDigSig = Base64.Base64Encoder(	m_lpDigitalSignature, 
													m_dwDigitalSignatureLen, 
													&hDigSig );
			
			lpEncodedDigSig = (LPBYTE)GlobalLock( hDigSig );
			ATLASSERT( lpEncodedDigSig );
			if( lpEncodedDigSig )
				{
					//	Convert to a zero-terminated string
				lpEncodedBytes = (LPBYTE)malloc( sizeof(BYTE) * dwEncodedDigSig + 1 );
				if( lpEncodedBytes )
					{
					USES_CONVERSION;

						//	Copy out to the caller
					memcpy( lpEncodedBytes, lpEncodedDigSig, dwEncodedDigSig );
					lpEncodedBytes[ dwEncodedDigSig ] = '\0';
					*pVal = ::SysAllocString( A2W((char*)lpEncodedBytes) );
					if( (*pVal) && 
						::SysStringLen( *pVal ) > 0 )
						hr = S_OK;
					else
						hr = Error( IDS_ERROR_OUTOFMEMORY, IID_ICrypto, E_OUTOFMEMORY );
					}
				else
					hr = Error( IDS_ERROR_OUTOFMEMORY, IID_ICrypto, E_OUTOFMEMORY );
				}

			else
				hr = Error( IDS_ERROR_OUTOFMEMORY, IID_ICrypto, E_OUTOFMEMORY );
			}
		else
			hr = Error( IDS_ERROR_DIGITALSIGNATURE_NOTAVAILABLE, 
						IID_ICrypto, E_FAIL );
		}
	else
		hr = Error( IDS_ERROR_INVALID_ARG, IID_ICrypto, E_INVALIDARG );

	if( hDigSig )
		GlobalFree( hDigSig );

	SAFE_MALLOC_FREE(lpEncodedBytes);
	return hr;
	}


STDMETHODIMP CCrypto::
get_ContainerName( BSTR *pVal )
	{
	return m_bstrContainerName.CopyTo( pVal );
	}


STDMETHODIMP CCrypto::
put_ContainerName( BSTR newVal )
	{
	m_bstrContainerName = newVal;	
	return S_OK;
	}



STDMETHODIMP CCrypto::
VerifyDigitalSignature( BSTR bstrDigitalSig, BOOL* pbMatches )
	{
	HRESULT		hr = S_OK;
	CComBSTR	bstrSrcDigSig( bstrDigitalSig );
	CComBSTR	bstrDigSig;

	ATLASSERT( pbMatches != NULL );

	if( pbMatches != NULL )
		{
		if( m_lpDigitalSignature &&
			m_dwDigitalSignatureLen > 0  )
			{
				//	Get the encoded string version of the digital signature
			hr = get_DigitalSignature( &bstrDigSig );
			if( SUCCEEDED( hr ) )
				*pbMatches = ( bstrDigSig == bstrDigitalSig );
			}
		else
			hr = Error( IDS_ERROR_DIGITALSIGNATURE_NOTAVAILABLE, 
						IID_ICrypto, E_FAIL );
		}
	else
		hr = Error( IDS_ERROR_INVALID_ARG, IID_ICrypto, E_INVALIDARG );

	return hr;
	}




STDMETHODIMP CCrypto::
EncryptDoc( BSTR		bstrSrc, 
			VARIANT		varDestination	)
	{
	USES_CONVERSION;
	USES_CHECKHR_MSG( IID_ICrypto );
	HRESULT		hr					= S_OK;
	HCRYPTKEY	hPrivateKey			= NULL;
	HCRYPTHASH	hDigSigHash			= NULL;
	LPBYTE		lpPrivateKey		= NULL;
	LPBYTE		lpData				= NULL; 
	FILE*		pSrcFile			= NULL;
	FILE*		pDestinationFile	= NULL;
	BOOL		bSrcIsDestination	= PARAM_IS_MISSING( varDestination );
	
	try
		{
		pSrcFile = fopen( W2A(bstrSrc), "rb" );

			//	Open destination with intentions of destroying existing contents
		if( pSrcFile )
			pDestinationFile	= bSrcIsDestination ? 
										fopen( FILE_INTERMEDIATE_FILENAME,  "w+b" ) :
										fopen( W2A(varDestination.bstrVal), "w+b" );

		ATLASSERT( pSrcFile			!= NULL );
		ATLASSERT( pDestinationFile != NULL );

			//	Make sure the files opened
		if( pSrcFile			== NULL ||
			pDestinationFile	== NULL		)
			nStringID = IDS_ERROR_ENCRYPTFILE_FILEOPENFAILED,
			THROW_HRESULT( E_FAIL );

		if( !WriteFileFormatVersion( pDestinationFile ) )
			nStringID = IDS_ERROR_ENCRYPT_WRITEFILEFORMATVERSION,
			THROW_HRESULT( E_FAIL );

			//	Write the private key to the destination file
		ClearDigitalSignature();
		if(	Initialize()	&&
			WritePrivateKey( pDestinationFile, 
							 hPrivateKey		) )
			{
			lpData = (LPBYTE)malloc( FILE_READBYTES * sizeof( BYTE ) );
			VERIFY_MALLOC( lpData );
			
				//	Create the hash for digital signature 
			if( !CryptCreateHash( m_hContext, 
								  HASHING_ALGORITHM, 0, 0, 
								  &hDigSigHash ) )
				nStringID = IDS_ERROR_HASHCREATE_FAILED,
				THROW_HRESULT( E_FAIL );


				//	Read in the data from the source file, encrypt it and write to the destination
			do 
				{ 
				DWORD dwCount = fread(	lpData, 
										sizeof(BYTE), 
										FILE_READBYTES, 
										pSrcFile ); 							
				if( ferror( pSrcFile ) )
					nStringID = IDS_ERROR_ENCRYPT_READING_SOURCE,
					THROW_HRESULT( E_FAIL );

					// If encryption fails, give some useful information back to caller
				if( !CryptEncrypt(	hPrivateKey, 
									hDigSigHash, 
									feof(pSrcFile), 
									0, lpData, 
									&dwCount, FILE_READBYTES ) )
					nStringID = IDS_ERROR_ENCRYPT_ENCRYPTION_FAILED,
					THROW_HRESULT( E_FAIL );
				
					// Write encrypted data to the destination file
				fwrite( lpData, 
						sizeof(BYTE), 
						dwCount, 
						pDestinationFile ); 
				if( ferror( pDestinationFile ) )
					nStringID = IDS_ERROR_ENCRYPT_WRITETODESTINATION_FAILED,
					THROW_HRESULT( E_FAIL );
				} 
			while( !feof( pSrcFile ) ); 
			fflush( pDestinationFile );

			if( !DigitallySignHash( hDigSigHash ) )
				nStringID = IDS_ERROR_ENCRYPT_SIGNHASH_FAILED,
				THROW_HRESULT( E_FAIL );
		 	}

		else
			nStringID = IDS_ERROR_INITIALIZATION_FAILED,
			THROW_HRESULT( E_FAIL );
		}
	catch( HRESULT _hr )
		{
		CATCH_FAILED_HR(_hr);
		}
      
		////////////////////
		//	Cleanup

	if( hPrivateKey )
		CryptDestroyKey( hPrivateKey );

	SAFE_MALLOC_FREE( lpPrivateKey );
	
	if( pSrcFile )
		fclose( pSrcFile );

	if( pDestinationFile )
		fclose( pDestinationFile );

	SAFE_MALLOC_FREE( lpData );

	if( hDigSigHash )
		CryptDestroyHash( hDigSigHash );

		//	Caller wants to overwrite src - Copy Destination to Source
	if( bSrcIsDestination )
		{
			//	CopyFile fails if file is readonly
		SetFileAttributes( W2T(bstrSrc), FILE_ATTRIBUTE_NORMAL );
		if( !CopyFile( A2T(FILE_INTERMEDIATE_FILENAME), W2T(bstrSrc), FALSE ) )
			hr = Error( IDS_ERROR_DECRYPT_COPYDESTINATIONTOSOURCE_FAILED,
						IID_ICrypto, E_FAIL );
		}

		//	Delete the intermediate file - if it exists
	_unlink( FILE_INTERMEDIATE_FILENAME );

	return hr;
	}


STDMETHODIMP CCrypto::
DecryptDoc( BSTR		bstrSrc, 
		    VARIANT		varDestination	)
	{
	USES_CONVERSION;
	USES_CHECKHR_MSG( IID_ICrypto );
	HRESULT		hr					= S_OK;
	HCRYPTKEY	hPrivateKey			= NULL;
	HCRYPTHASH	hDigSigHash			= NULL;
	LPBYTE		lpData				= NULL; 
	FILE*		pSrcFile			= NULL;
	FILE*		pDestinationFile	= NULL;
	BOOL		bSrcIsDestination	= PARAM_IS_MISSING( varDestination );
	
	try
		{
		pSrcFile = fopen( W2A(bstrSrc), "rb" );

			//	Open destination with intentions of destroying existing contents
		if( pSrcFile )
			pDestinationFile	= bSrcIsDestination ? 
										fopen( FILE_INTERMEDIATE_FILENAME,  "w+b" ) :
										fopen( W2A(varDestination.bstrVal), "w+b" );

		ATLASSERT( pSrcFile			!= NULL );
		ATLASSERT( pDestinationFile != NULL );

			//	Make sure the files opened
		if( pSrcFile			== NULL ||
			pDestinationFile	== NULL		)
			nStringID = IDS_ERROR_DECRYPTFILE_FILEOPENFAILED,
			THROW_HRESULT( E_FAIL );

			//	Read the version stamp and make sure its a version that we can read
		if( !ReadFileFormatVersion( pSrcFile ) )
			nStringID = IDS_ERROR_DECRYPTFILE_READINGFILEVERSION,
			THROW_HRESULT( E_FAIL );

			//	Read the private key and import into CSP
		ClearDigitalSignature();
		if(	Initialize() &&
			ReadPrivateKey( pSrcFile, hPrivateKey ) )
			{	
			lpData	   = (LPBYTE)malloc( FILE_READBYTES * sizeof( BYTE ) );
			VERIFY_MALLOC( lpData );
				
				//	Create the hash for digital signature 
			if( !CryptCreateHash( m_hContext, 
								  HASHING_ALGORITHM, 0, 0, 
								  &hDigSigHash ) )
				nStringID = IDS_ERROR_HASHCREATE_FAILED,
				THROW_HRESULT( E_FAIL );

				//	Read in the data from the source file, encrypt it and write to the destination
			do 
				{ 
				DWORD dwCount = fread(	lpData, 
										sizeof(BYTE), 
										FILE_READBYTES, 
										pSrcFile ); 							
				if( ferror( pSrcFile ) )
					nStringID = IDS_ERROR_DECRYPT_READING_SOURCE,
					THROW_HRESULT( E_FAIL );

					// If encryption fails, give some useful information back to caller
				if( !CryptDecrypt(	hPrivateKey, 
									hDigSigHash, 
									feof(pSrcFile), 
									0, lpData, 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -