📄 crypto.cpp
字号:
&dwCount ) )
nStringID = IDS_ERROR_DECRYPT_DECRYPTION_FAILED,
THROW_HRESULT( E_FAIL );
// Write decrypted data to the destination file
fwrite( lpData, sizeof(BYTE), dwCount, pDestinationFile );
if( ferror( pDestinationFile ) )
nStringID = IDS_ERROR_DECRYPT_WRITETODESTINATION_FAILED,
THROW_HRESULT( E_FAIL );
}
while( !feof( pSrcFile ) );
fflush( pDestinationFile );
// Determine the length of the digital signature
if( !DigitallySignHash( hDigSigHash ) )
nStringID = IDS_ERROR_DECRYPT_SIGNHASH_FAILED,
THROW_HRESULT( E_FAIL );
}
}
catch( HRESULT _hr )
{
CATCH_FAILED_HR( _hr );
}
///////////////////////////////////////////////////////////////////////
// Cleanup
if( hPrivateKey )
CryptDestroyKey( hPrivateKey );
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( 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 - if it exists
_unlink( FILE_INTERMEDIATE_FILENAME );
return hr;
}
STDMETHODIMP CCrypto::
EncryptString( BSTR bstrSrc, BSTR *pbstrResult )
{
USES_CONVERSION;
USES_CHECKHR_MSG( IID_ICrypto );
HRESULT hr = S_OK;
HCRYPTKEY hPrivateKey = NULL;
HCRYPTHASH hDigSigHash = NULL;
LPBYTE lpPrivateKey = NULL;
LPBYTE lpFinalBuffer = NULL;
LPBYTE lpSrcBytes = NULL;
LPBYTE lpEncodedBytes = NULL;
ATLASSERT( pbstrResult != NULL );
try
{
CComBSTR strSrc(bstrSrc);
ClearDigitalSignature();
if( !Initialize() )
nStringID = IDS_ERROR_INITIALIZATION_FAILED,
THROW_HRESULT( E_FAIL );
// Nothing to encrypt?
ATLASSERT( strSrc.Length() > 0 );
if( strSrc.Length() > 0 )
{
DWORD dwEncryptSize = 0;
DWORD dwEncodedBytes = 0;
DWORD dwPrivateKeySize= 0;
DWORD dwFinalBuffer = 0;
DWORD dwVersion = INMEMORY_FORMAT_VERSION;
DWORD dwEncryptedLen = strSrc.Length();
hPrivateKey = GeneratePrivateKey( &lpPrivateKey,
&dwPrivateKeySize,
INMEMORY_ENCRYPT_ALGORITHM );
if( hPrivateKey &&
lpPrivateKey )
{
CBase64Helper Base64Helper;
// Create the hash for digital signature
if( !CryptCreateHash( m_hContext,
HASHING_ALGORITHM, 0, 0,
&hDigSigHash ) )
nStringID = IDS_ERROR_HASHCREATE_FAILED,
THROW_HRESULT( E_FAIL );
// Copy the src string into a byte array
lpSrcBytes = (LPBYTE)malloc( sizeof(BYTE) * strSrc.Length() + 1 );
VERIFY_MALLOC( lpSrcBytes );
strcpy( (char*)lpSrcBytes, W2A(strSrc) );
// Calculate the size of the encrypted buffer
dwEncryptSize = strlen( (char*)lpSrcBytes );
// Encrypt the src string and initialize the digital signature hash
if( !CryptEncrypt( hPrivateKey,
hDigSigHash,
TRUE,
0,
lpSrcBytes,
&dwEncryptSize,
dwEncryptSize ) )
nStringID = IDS_ERROR_ENCRYPT_ENCRYPTION_FAILED,
THROW_HRESULT( E_FAIL );
// Calculate the total size of the resulting string (in bytes)
dwFinalBuffer = SIZE_VERSION +
SIZE_PRIVATEKEY_SIZE +
dwPrivateKeySize +
SIZE_ENCRYPTED_DATA +
dwEncryptSize;
// Create the final buffer
lpFinalBuffer = (LPBYTE)malloc( ( sizeof(BYTE) * dwFinalBuffer ) + 1 );
VERIFY_MALLOC( lpFinalBuffer );
// Build the encrypted blob in-memory
memcpy( lpFinalBuffer, &dwVersion, sizeof(dwVersion) );
memcpy( &lpFinalBuffer[ SIZE_VERSION ], &dwPrivateKeySize, sizeof(dwPrivateKeySize) );
memcpy( &lpFinalBuffer[ SIZE_VERSION + SIZE_PRIVATEKEY_SIZE ], lpPrivateKey, dwPrivateKeySize );
memcpy( &lpFinalBuffer[ SIZE_VERSION + SIZE_PRIVATEKEY_SIZE + dwPrivateKeySize ], &dwEncryptedLen, sizeof(dwEncryptedLen) );
memcpy( &lpFinalBuffer[ SIZE_VERSION + SIZE_PRIVATEKEY_SIZE + dwPrivateKeySize + SIZE_ENCRYPTED_DATA ], lpSrcBytes, dwEncryptSize );
// Prepare the encrypted blob for the caller
dwEncodedBytes = Base64Helper.Base64Encoder( lpFinalBuffer, dwFinalBuffer, (void**)&lpEncodedBytes );
// Convert encoded/encrypted bytes to zero-terminated string
lpSrcBytes = (LPBYTE)realloc( lpSrcBytes, dwEncodedBytes + 1 );
memcpy( lpSrcBytes, (PBYTE)GlobalLock( lpEncodedBytes ), dwEncodedBytes );
lpSrcBytes[ dwEncodedBytes ] = '\0';
// Grab the digital signature
if( !DigitallySignHash( hDigSigHash ) )
nStringID = IDS_ERROR_DIGITALSIGNATURE_ENCRYPT_STRING,
THROW_HRESULT( E_FAIL );
// Copy out to the caller
*pbstrResult = ::SysAllocString( A2W((char*)lpSrcBytes) );
}
}
}
catch( HRESULT _hr )
{
CATCH_FAILED_HR( _hr );
}
// Cleanup
if( hPrivateKey )
CryptDestroyKey( hPrivateKey );
SAFE_MALLOC_FREE( lpSrcBytes );
SAFE_MALLOC_FREE( lpFinalBuffer );
SAFE_MALLOC_FREE( lpPrivateKey );
if( hDigSigHash )
CryptDestroyHash( hDigSigHash );
if( lpEncodedBytes )
GlobalFree( lpEncodedBytes );
return hr;
}
STDMETHODIMP CCrypto::
DecryptString( BSTR bstrSrc, BSTR *pbstrResult )
{
USES_CONVERSION;
USES_CHECKHR_MSG( IID_ICrypto );
HRESULT hr = S_OK;
HCRYPTHASH hDigSigHash = NULL;
HCRYPTKEY hPrivateKey = NULL;
LPBYTE lpSrcBytes = NULL;
HGLOBAL hDecodedBytes = NULL;
PBYTE lpDecodedBytes = NULL;
LPBYTE lpEncryptedData = NULL;
LPBYTE lpPrivateKey = NULL;
ATLASSERT( pbstrResult != NULL );
try
{
CBase64Helper Base64;
CComBSTR bstrDecoded(bstrSrc);
ClearDigitalSignature();
if( !Initialize() )
nStringID = IDS_ERROR_INITIALIZATION_FAILED,
THROW_HRESULT( E_FAIL );
// Must be long enough
ATLASSERT( ::SysStringLen( bstrSrc ) > ( SIZE_VERSION + SIZE_PRIVATEKEY_SIZE ) );
if( ::SysStringLen( bstrSrc ) > ( SIZE_VERSION + SIZE_PRIVATEKEY_SIZE ) )
{
DWORD dwVersion = INVALID_FORMAT_VERSION;
DWORD dwPrivateKeySize = 0;
DWORD dwEncryptedData = 0;
DWORD dwDecodedBytes = 0;
// Create the hash for digital signature
if( !CryptCreateHash( m_hContext,
HASHING_ALGORITHM, 0, 0,
&hDigSigHash ) )
nStringID = IDS_ERROR_HASHCREATE_FAILED,
THROW_HRESULT( E_FAIL );
// Covert the src encoded, encrypted string into a byte array
lpSrcBytes = (LPBYTE)malloc( sizeof(BYTE) * bstrDecoded.Length() + 1 );
VERIFY_MALLOC( lpSrcBytes );
strcpy( (char*)lpSrcBytes, W2A(bstrDecoded) );
// Decode the bytes
dwDecodedBytes = Base64.Base64Decoder( lpSrcBytes,
strlen( (char*)lpSrcBytes ),
&hDecodedBytes );
lpDecodedBytes = (PBYTE)GlobalLock( hDecodedBytes );
// Grab the version and private key size
dwVersion = (*((DWORD*)lpDecodedBytes));
dwPrivateKeySize= (*((DWORD*)&lpDecodedBytes[ SIZE_VERSION ]));
// Validate the in-memory string format
if( dwVersion != INMEMORY_FORMAT_VERSION ||
dwDecodedBytes <= ( SIZE_VERSION + SIZE_PRIVATEKEY_SIZE + dwPrivateKeySize ) )
nStringID = IDS_ERROR_UNSUPORTED_INMEMORY_ENCRYPTION_VERSION,
THROW_HRESULT( E_FAIL );
// Grab the private key
lpPrivateKey = (LPBYTE)malloc( sizeof(BYTE) * dwPrivateKeySize );
VERIFY_MALLOC( lpPrivateKey );
memcpy( lpPrivateKey, &lpDecodedBytes[ SIZE_VERSION + SIZE_PRIVATEKEY_SIZE ], sizeof(BYTE) * dwPrivateKeySize );
// Import the private key into the CSP
if( !CryptImportKey( m_hContext,
lpPrivateKey,
dwPrivateKeySize, 0, 0,
&hPrivateKey ) )
nStringID = IDS_ERROR_IMPORTPRIVATEKEY_FAILED,
THROW_HRESULT( E_FAIL );
// Grab the encrypted data size
dwEncryptedData = (*((DWORD*)&lpDecodedBytes[ SIZE_VERSION + SIZE_PRIVATEKEY_SIZE + dwPrivateKeySize ]));
// Grab the encrypted data
lpEncryptedData = (LPBYTE)malloc( dwEncryptedData + 1 );
VERIFY_MALLOC( lpEncryptedData );
memcpy( lpEncryptedData, &lpDecodedBytes[ SIZE_VERSION + SIZE_PRIVATEKEY_SIZE + SIZE_ENCRYPTED_DATA + dwPrivateKeySize ], dwEncryptedData );
// Perform the decryption
if( !CryptDecrypt( hPrivateKey,
hDigSigHash,
TRUE, 0,
lpEncryptedData,
&dwEncryptedData ) )
nStringID = IDS_ERROR_DECRYPTSTRING_FAILED,
THROW_HRESULT( E_FAIL );
// Copy the result to the caller
lpEncryptedData[ dwEncryptedData ] = '\0';
*pbstrResult = ::SysAllocString( A2W((char*)lpEncryptedData) );
// Digital signature
if( !DigitallySignHash( hDigSigHash ) )
nStringID = IDS_ERROR_DIGITALSIGNATURE_DECRYPT_STRING,
THROW_HRESULT( E_FAIL );
}
// Bad format
else
nStringID = IDS_ERROR_UNSUPORTED_INMEMORY_ENCRYPTION_VERSION,
THROW_HRESULT( E_FAIL );
}
catch( HRESULT _hr )
{
CATCH_FAILED_HR( _hr );
}
SAFE_MALLOC_FREE( lpSrcBytes );
SAFE_MALLOC_FREE( lpPrivateKey );
SAFE_MALLOC_FREE( lpEncryptedData );
if( hPrivateKey )
CryptDestroyKey( hPrivateKey );
if( hDecodedBytes )
GlobalFree( hDecodedBytes );
if( hDigSigHash )
CryptDestroyHash( hDigSigHash );
return hr;
}
STDMETHODIMP CCrypto::
Base64EncodeString( BSTR bstrSrc, BSTR *pbstrResult )
{
CBase64Helper Base64;
CComBSTR bstrEncoded = Base64.Base64EncodeString( bstrSrc );
return bstrEncoded.CopyTo( pbstrResult );
}
STDMETHODIMP CCrypto::
Base64DecodeString( BSTR bstrSrc, BSTR *pbstrResult )
{
CBase64Helper Base64;
CComBSTR bstrDecoded = Base64.Base64DecodeString( bstrSrc );
return bstrDecoded.CopyTo( pbstrResult );
}
STDMETHODIMP CCrypto::
Base64EncodeFile( BSTR bstrSrc, VARIANT varDestination )
{
return Base64FileHelper( bstrSrc, varDestination );
}
STDMETHODIMP CCrypto::
Base64DecodeFile( BSTR bstrSrc, VARIANT varDestination )
{
return Base64FileHelper( bstrSrc, varDestination, FALSE );
}
STDMETHODIMP CCrypto::
Base64EncodeFileToString( BSTR bstrSrc,
BSTR* pbstrResult )
{
USES_CONVERSION;
USES_CHECKHR_MSG( IID_ICrypto );
FILE* pSrcFile = NULL;
HRESULT hr = S_OK;
LPBYTE lpData[ FILE_READBYTES ]= {0};
LPBYTE lpResultBlob = NULL;
HGLOBAL hEncodedBytes = NULL;
LPBYTE pEncodedBytes = NULL;
DWORD dwTotalRead = 0;
CComBSTR bstrResult;
ATLASSERT( pbstrResult != NULL );
try
{
pSrcFile = fopen( W2A(bstrSrc), "rb" );
ATLASSERT( pSrcFile != NULL );
// Make sure the files opened
if( pSrcFile == NULL )
nStringID = IDS_ERROR_ENCODEDFILE_FILEOPENFAILED,
THROW_HRESULT( E_FAIL );
// Read the file into memory - We need to anyway since the client wants a string back
do
{
LPBYTE lpTemp = NULL;
// Read up to FILE_READBYTES bytes from the source file
DWORD dwCount = fread( lpData, sizeof(BYTE), FILE_READBYTES, pSrcFile );
if( ferror( pSrcFile ) )
nStringID = IDS_ERROR_ENCODEDFILE_FILEIO,
THROW_HRESULT( E_FAIL );
// Append the bytes to what has already been read
dwTotalRead += dwCount;
lpTemp = (LPBYTE)realloc( lpResultBlob, dwTotalRead + 1 );
VERIFY_MALLOC( lpTemp );
lpResultBlob = lpTemp;
memcpy( &lpResultBlob[ dwTotalRead - dwCount ], lpData, dwCount );
}
while( !feof(pSrcFile) );
}
catch( HRESULT _hr )
{
CATCH_FAILED_HR( _hr );
}
// Clean up
if( pSrcFile )
fclose( pSrcFile );
if( SUCCEEDED( hr ) )
{
CBase64Helper Base64;
// Encode the bits
DWORD dwEncoded = Base64.Base64Encoder( (LPBYTE)lpResultBlob, dwTotalRead, &hEncodedBytes );
pEncodedBytes = (LPBYTE)GlobalLock( hEncodedBytes );
// Convert encoded bits to a BSTR
bstrResult.Append( (LPCSTR)pEncodedBytes );
hr = bstrResult.CopyTo( pbstrResult );
GlobalFree( hEncodedBytes );
}
SAFE_MALLOC_FREE( lpResultBlob );
return hr;
}
STDMETHODIMP CCrypto::
Base64DecodeStringToFile( BSTR bstrSrc,
BSTR bstrDestination )
{
USES_CONVERSION;
USES_CHECKHR_MSG( IID_ICrypto );
HRESULT hr = S_OK;
LPBYTE lpSrcBytes = NULL;
HGLOBAL hDecodedBytes = NULL;
FILE* pDestination = NULL;
CComBSTR cbstrSrc( bstrSrc );
try
{
CBase64Helper Base64;
DWORD dwDecoded = 0;
// Copy the source string to byte array
lpSrcBytes = (LPBYTE)malloc( sizeof(BYTE) * cbstrSrc.Length() + 1 );
VERIFY_MALLOC( lpSrcBytes );
strcpy( (char*)lpSrcBytes, W2A(cbstrSrc) );
dwDecoded = Base64.Base64Decoder( lpSrcBytes, strlen( (LPCSTR)lpSrcBytes ), &hDecodedBytes );
pDestination = fopen( W2A(bstrDestination), "w+b" );
if( pDestination )
{
LPBYTE lpDecodedBytes = (LPBYTE)GlobalLock( hDecodedBytes );
// Write the result to the destination file
fwrite( lpDecodedBytes, sizeof(BYTE), dwDecoded, pDestination );
fflush( pDestination );
if( ferror( pDestination ) )
nStringID = IDS_ERROR_DECODED_FILEIO,
THROW_HRESULT( E_FAIL );
}
}
catch( HRESULT _hr )
{
CATCH_FAILED_HR( _hr );
}
// Cleanup
SAFE_MALLOC_FREE( lpSrcBytes );
if( hDecodedBytes )
GlobalFree( hDecodedBytes );
if( pDestination )
fclose( pDestination );
return hr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -