📄 crypto.cpp
字号:
}
BOOL CCrypto::
Initialize() const
{
BOOL bSuccess = TRUE;
if( !m_hContext )
{
bSuccess = InitializeContainer();
if( bSuccess )
{
bSuccess = InitializeDigitalSignatureEngine();
if( bSuccess )
bSuccess = InitializeEncryptionEngine();
// If we failed to initialize digital signatures or encryption, then reset
if( !bSuccess )
{
CryptReleaseContext( m_hContext, 0 );
m_hContext = NULL;
}
}
}
return bSuccess;
}
BOOL CCrypto::
InitializeContainer() const
{
USES_CONVERSION;
BOOL bSuccess = FALSE;
int nStringID= IDS_UNKNOWN_ERROR;
ATLASSERT( !m_hContext );
bSuccess = CryptAcquireContext( &m_hContext,
W2T(m_bstrContainerName.m_str),
MS_DEF_PROV,
PROV_RSA_FULL, 0 );
// Container doesn't exist - Possibly try to create a new container
if( !bSuccess )
{
int nLastError = GetLastError();
if( nLastError == NTE_BAD_KEYSET )
{
// Creating the key container for the first time
bSuccess = CryptAcquireContext( &m_hContext,
W2T(m_bstrContainerName.m_str),
MS_DEF_PROV,
PROV_RSA_FULL, CRYPT_NEWKEYSET );
if( !bSuccess )
nStringID = IDS_ERROR_INITIALIZATION_CREATE_NEW_CONTAINER_FAILED;
}
else
nStringID = LookupCryptErrorStringID( nLastError );
}
if( !bSuccess )
CRYPTO_OUTPUT_DEBUGSTRING( nStringID );
return bSuccess;
}
BOOL CCrypto::
InitializeDigitalSignatureEngine() const
{
BOOL bSuccess = FALSE;
HCRYPTKEY hKey = NULL;
int nStringID= IDS_UNKNOWN_ERROR;
// Check the key pair for digital signatures
if( !CryptGetUserKey( m_hContext, AT_SIGNATURE, &hKey ) )
{
if( GetLastError() == NTE_NO_KEY )
{
// There is a container but no key - Create signature key pair
if( !CryptGenKey( m_hContext, AT_SIGNATURE, 0, &hKey ) )
nStringID = IDS_ERROR_INITIALIZATION_CREATE_DIGSIGKEYS;
else
bSuccess = TRUE;
}
else
nStringID = IDS_ERROR_INITIALIZATION_CREATE_DIGSIGKEYS;
}
// Key pair already available
else
bSuccess = TRUE;
if( hKey )
CryptDestroyKey( hKey );
if( !bSuccess )
CRYPTO_OUTPUT_DEBUGSTRING( nStringID );
return bSuccess;
}
BOOL CCrypto::
InitializeEncryptionEngine() const
{
BOOL bSuccess = FALSE;
HCRYPTKEY hKey = NULL;
int nStringID= IDS_UNKNOWN_ERROR;
// Check the key pair for encryption
if( !CryptGetUserKey( m_hContext, AT_KEYEXCHANGE, &hKey ) )
{
if( GetLastError() == NTE_NO_KEY )
{
// There is a container but no key - Create an encryption key pair
if( !CryptGenKey( m_hContext, AT_KEYEXCHANGE, 0, &hKey ) )
nStringID = IDS_ERROR_INITIALIZATION_CREATE_ENCRYPTIONKEYS;
else
bSuccess = TRUE;
}
else
nStringID = IDS_ERROR_INITIALIZATION_CREATE_ENCRYPTIONKEYS;
}
// Key pair already available
else
bSuccess = TRUE;
if( hKey )
CryptDestroyKey( hKey );
if( !bSuccess )
CRYPTO_OUTPUT_DEBUGSTRING( nStringID );
return bSuccess;
}
void CCrypto::
ClearDigitalSignature()
{
SAFE_MALLOC_FREE( m_lpDigitalSignature );
m_dwDigitalSignatureLen = 0;
}
BOOL CCrypto::
WritePrivateKey( FILE* pDestination,
HCRYPTKEY& hPrivateKey )
{
BOOL bSuccess = FALSE;
DWORD dwBlobLen = 0;
LPBYTE lpPrivateKey= NULL;
ATLASSERT( pDestination != NULL );
// Get a private key
hPrivateKey = GeneratePrivateKey( &lpPrivateKey, &dwBlobLen, FILE_ENCRYPT_ALGORITHM );
// If we succeeded in getting a private key...
if( lpPrivateKey )
{
// Write the size of the private key to the destination file
if( fwrite( &dwBlobLen, sizeof(dwBlobLen), 1, pDestination ) )
{
// Write the private key (encrypted) to the destination file
if( fwrite( lpPrivateKey, sizeof(BYTE), dwBlobLen, pDestination ) == dwBlobLen )
bSuccess = TRUE;
}
}
SAFE_MALLOC_FREE( lpPrivateKey );
return bSuccess;
}
BOOL CCrypto::
ReadPrivateKey( FILE* pSrcFile, HCRYPTKEY& hPrivateKey ) const
{
BOOL bSuccess = FALSE;
DWORD dwKeySize = 0;
LPBYTE lpPrivateKey = NULL;
ATLASSERT( pSrcFile != NULL );
// Read in the key size
if( fread( &dwKeySize, sizeof(DWORD), 1, pSrcFile ) )
{
// Allocate room to hold the private key
lpPrivateKey = (LPBYTE)malloc( sizeof(BYTE)*dwKeySize );
ATLASSERT( lpPrivateKey != NULL );
if( lpPrivateKey )
{
// Read in the private key
if( fread( lpPrivateKey,
sizeof(BYTE),
dwKeySize,
pSrcFile ) == dwKeySize )
{
// Import the private key into the CSP
bSuccess = CryptImportKey( m_hContext,
lpPrivateKey,
dwKeySize, 0, 0,
&hPrivateKey );
}
}
}
SAFE_MALLOC_FREE( lpPrivateKey );
return bSuccess;
}
BOOL CCrypto::
WriteFileFormatVersion( FILE* pDestination ) const
{
DWORD dwFileFormat = FILE_BINARY_FORMAT_VERSION;
ATLASSERT( pDestination != NULL );
// Stamp the file with the version header
return( fwrite( &dwFileFormat, sizeof(DWORD), 1, pDestination ) );
}
BOOL CCrypto::
ReadFileFormatVersion( FILE* pSrc ) const
{
BOOL bSuccess = FALSE;
DWORD dwFileFormat = INVALID_FORMAT_VERSION;
ATLASSERT( pSrc != NULL );
if( fread( &dwFileFormat, sizeof(DWORD), 1, pSrc ) )
{
ATLASSERT( dwFileFormat == FILE_BINARY_FORMAT_VERSION );
if( dwFileFormat == FILE_BINARY_FORMAT_VERSION )
bSuccess = TRUE;
}
return bSuccess;
}
HCRYPTKEY CCrypto::
GeneratePrivateKey( LPBYTE* lpPrivateKeyBlob,
LPDWORD lpdwBlobSize,
int enumAlgorithm )
{
HCRYPTKEY hPrivateKey = NULL;
HCRYPTKEY hPublicKey = NULL;
// Generate the private key
ClearDigitalSignature();
if( Initialize() &&
CryptGenKey( m_hContext,
enumAlgorithm,
CRYPT_EXPORTABLE, &hPrivateKey ) )
{
// Get handle to the encrypter's exchange public key
if( CryptGetUserKey( m_hContext, AT_KEYEXCHANGE, &hPublicKey ) )
{
// Determine size of the key blob
if( CryptExportKey( hPrivateKey,
hPublicKey,
SIMPLEBLOB,
0, NULL,
lpdwBlobSize ) )
{
(*lpPrivateKeyBlob) = (LPBYTE)malloc( sizeof(BYTE) * (*lpdwBlobSize) );
ATLASSERT( lpPrivateKeyBlob != NULL );
if( lpPrivateKeyBlob )
// Encrypt and export private key
CryptExportKey( hPrivateKey,
hPublicKey,
SIMPLEBLOB,
0,
(*lpPrivateKeyBlob),
lpdwBlobSize );
}
}
}
if( hPublicKey )
CryptDestroyKey( hPublicKey );
return hPrivateKey;
}
BOOL CCrypto::
DigitallySignHash( HCRYPTHASH hHash )
{
BOOL bSuccess = FALSE;
ATLASSERT( hHash );
// Clear existing signature
ClearDigitalSignature();
// Determine the length of the digital signature
if( CryptSignHash( hHash,
AT_SIGNATURE, NULL,
0, NULL, &m_dwDigitalSignatureLen ) )
{
ATLASSERT( m_lpDigitalSignature == NULL );
m_lpDigitalSignature = (LPBYTE)malloc( m_dwDigitalSignatureLen + 1 );
if( m_lpDigitalSignature )
// Sign the original (decrypted) data
bSuccess = CryptSignHash( hHash,
AT_SIGNATURE, NULL, 0,
m_lpDigitalSignature,
&m_dwDigitalSignatureLen );
}
return bSuccess;
}
HRESULT CCrypto::
Base64FileHelper( BSTR bstrSrc,
VARIANT varDestination,
BOOL bEncode ) const
{
USES_CONVERSION;
USES_CHECKHR_MSG( IID_ICrypto );
HRESULT hr = S_OK;
LPBYTE lpData[ FILE_READBYTES ]= {0};
FILE* pSrcFile = NULL;
FILE* pDestinationFile = NULL;
HGLOBAL hEncodedBytes = NULL;
BOOL bSrcIsDestination = PARAM_IS_MISSING( varDestination );
try
{
CBase64Helper Base64;
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_ENCODEDFILE_FILEOPENFAILED,
THROW_HRESULT( E_FAIL );
do
{
// Read up to FILE_READBYTES_BLOCKSIZE bytes from the source file
DWORD dwEncoded = 0;
DWORD dwCount = fread( lpData,
sizeof(BYTE),
FILE_READBYTES,
pSrcFile );
if( ferror( pSrcFile ) )
nStringID = IDS_ERROR_ENCODEDFILE_FILEIO,
THROW_HRESULT( E_FAIL );
// Encode or decode the bits
dwEncoded = bEncode ? Base64.Base64Encoder( (LPBYTE)lpData, dwCount, &hEncodedBytes ) :
Base64.Base64Decoder( (LPBYTE)lpData, dwCount, &hEncodedBytes );
// Write encoded/decoded data to the destination file
fwrite( GlobalLock(hEncodedBytes),
sizeof(BYTE),
dwEncoded,
pDestinationFile );
GlobalFree( hEncodedBytes );
if( ferror( pDestinationFile ) )
nStringID = IDS_ERROR_ENCODEDFILE_FILEIO,
THROW_HRESULT( E_FAIL );
}
while( !feof(pSrcFile) );
fflush( pDestinationFile );
}
catch( HRESULT _hr )
{
CATCH_FAILED_HR( _hr );
}
if( pSrcFile )
fclose( pSrcFile );
if( pDestinationFile )
fclose( pDestinationFile );
// Caller wants to overwrite src - Copy Destination to Source
if( SUCCEEDED(hr) &&
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
_unlink( FILE_INTERMEDIATE_FILENAME );
return hr;
}
int CCrypto::
LookupCryptErrorStringID( int nLastError ) const
{
int nStringID;
switch( nLastError )
{
case ERROR_NOT_ENOUGH_MEMORY:
case NTE_NO_MEMORY:
nStringID = IDS_ERROR_OUTOFMEMORY;
break;
case NTE_BAD_FLAGS:
nStringID = IDS_ERROR_INITIALIZE_NTE_BAD_FLAGS;
break;\
case NTE_BAD_KEYSET_PARAM:
nStringID = IDS_ERROR_INITIALIZE_NTE_BAD_KEYSET_PARAM;
break;
case NTE_BAD_PROV_TYPE:
nStringID = IDS_ERROR_INITIALIZATION_NTE_BAD_PROV_TYPE;
break;
case NTE_BAD_SIGNATURE:
nStringID = IDS_ERROR_INITIALIZATION_NTE_BAD_SIGNATURE;
break;
case NTE_EXISTS:
nStringID = IDS_ERROR_INITIALIZATION_NTE_EXISTS;
break;
case NTE_KEYSET_ENTRY_BAD:
nStringID = IDS_ERROR_INITIALIZATION_NTE_KEYSET_ENTRY_BAD;
break;
case NTE_KEYSET_NOT_DEF:
nStringID = IDS_ERROR_INITIALIZATION_NTE_KEYSET_NOT_DEF;
break;
case NTE_PROV_DLL_NOT_FOUND:
nStringID = IDS_ERROR_INITIALIZATION_NTE_PROV_DLL_NOT_FOUND;
break;
case NTE_PROV_TYPE_ENTRY_BAD:
nStringID = IDS_ERROR_INITIALIZATION_NTE_PROV_TYPE_ENTRY_BAD;
break;
case NTE_PROV_TYPE_NO_MATCH:
nStringID = IDS_ERROR_INITIALIZATION_NTE_PROV_TYPE_NO_MATCH;
break;
case NTE_PROV_TYPE_NOT_DEF:
nStringID = IDS_ERROR_INITIALIZATION_NTE_PROV_TYPE_NOT_DEF;
break;
case NTE_PROVIDER_DLL_FAIL:
nStringID = IDS_ERROR_INITIALIZATION_NTE_PROVIDER_DLL_FAIL;
break;
case NTE_SIGNATURE_FILE_BAD:
nStringID = IDS_ERROR_INITIALIZATION_NTE_SIGNATURE_FILE_BAD;
break;
default:
nStringID = IDS_UNKNOWN_ERROR;
break;
}
return nStringID;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -