📄 mycngcryptfile.cpp
字号:
/ MyCNGCryptFile.cpp: implementation of the CMyCNGCryptFile class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "MyCNGCryptFile.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
/*
To use this class in vc++ 2005 you must add to the project proprieties this:
1. At C++ General in the "Additional Include Directories" this path "C:\Program Files\Microsoft CNG Development Kit\Include"
2. At "Linker General" in the "Additional Library Directories" this path "C:\Program Files\Microsoft CNG Development Kit\Lib\X86"
3. At "Linker Input" "Additional Dependecies" "bcrypt.lib"
*/
CMyCNGCryptFile::CMyCNGCryptFile()
{
m_sError.Empty();
m_iTotalByteRead = 0;
m_iLenghtFileToOpen = 0 ;
m_hAesAlg = NULL;
m_hKey = NULL;
m_pbKeyObject = NULL;
m_pbIV = NULL;
//Hash
m_hHash = NULL;
m_pbHashObject = NULL;
m_hHashAlg = NULL;
}
CMyCNGCryptFile::~CMyCNGCryptFile()
{
if(m_hAesAlg)
{
BCryptCloseAlgorithmProvider(m_hAesAlg,0);
}
if (m_hKey)
{
BCryptDestroyKey(m_hKey);
}
if(m_pbKeyObject)
{
HeapFree(GetProcessHeap(), 0, m_pbKeyObject);
}
if(m_pbIV!=NULL)
{
HeapFree(GetProcessHeap(), 0, m_pbIV);
}
//Hash
if (m_hHash )
BCryptDestroyHash(m_hHash);
if ( m_pbHashObject )
free(m_pbHashObject);
if ( m_hHashAlg )
BCryptCloseAlgorithmProvider(m_hHashAlg,0);
}
bool CMyCNGCryptFile::CryptFile(bool bEncrypt, CString sFileToOpen, CString sFileToCrypt, CString sKey)
{
CFile oFileToOpen, oFileToCrypt;
NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
DWORD cbKeyObject = 0;
DWORD cbIV = 0;
BOOL bFileToOpen = FALSE;
BOOL bFileToCrypt = FALSE;
UINT iBytesRead =0;
BYTE pbufFileToOpen[CHUNK_SIZE];
BYTE pbufFileToSave[CHUNK_SIZE*2];
if (!OpenMSPrimitiveProviderAES())
return false;
/* if(!CreateSymmetricKey_AES_CBC(cbKeyObject,cbIV))
return false;
*/
if(!CreateSymmetricKey_SHA1_Hash(sKey,cbKeyObject))
return false;
bFileToOpen = oFileToOpen.Open(sFileToOpen,CFile::modeRead|CFile::typeBinary);
if( bFileToOpen=FALSE)
{
m_sError.Format(_T("Error opening the file '%s'"),sFileToOpen);
return false;
}
bFileToCrypt= oFileToCrypt.Open(sFileToCrypt,CFile::modeWrite | CFile::shareExclusive | CFile::modeCreate);
if( bFileToCrypt=FALSE)
{
m_sError.Format(_T("Error opening the file '%s'"),sFileToOpen);
return false;
}
SetLenghtFileToOpen(oFileToOpen.GetLength());
DWORD iBufToSave=0;
while ( !LastCryptBuffRead() )
{
iBufToSave=0;
iBytesRead = oFileToOpen.Read( pbufFileToOpen, CHUNK_SIZE );
SetTotByteRead(iBytesRead);
if ( iBytesRead == 0 )
{
CString sError;
m_sError.Format(_T("Error reading the file '%s'"),sFileToOpen);
return false;
}
if (!LastCryptBuffRead())
{
if (!Crypt(bEncrypt,pbufFileToOpen,iBytesRead,cbIV,pbufFileToSave,iBufToSave))
return false;
oFileToCrypt.Write(pbufFileToSave,iBytesRead);
}
else //(!LastCryptBuffRead())
{
if(!CryptLastByte(bEncrypt,pbufFileToOpen,iBytesRead,cbIV,pbufFileToSave,iBufToSave))
return false;
oFileToCrypt.Write(pbufFileToSave,iBufToSave);
}
}
return true;
}
bool CMyCNGCryptFile::EnumProviders(CStringList *lstRegisteredProviders)
{
NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
DWORD cbBuffer = 0;
PCRYPT_PROVIDERS pProviders = NULL;
ntStatus = BCryptEnumRegisteredProviders(&cbBuffer, &pProviders);
CString sProvider;
if ( ntStatus != STATUS_SUCCESS )
{
m_sError.Format(_T("BCryptEnumRegisteredProviders failed with error code 0x%08x"), ntStatus);
return false;
}
if (pProviders == NULL)
{
m_sError.Format(_T("BCryptEnumRegisteredProviders returned a NULL"));
return false;
}
else
{
for ( DWORD i = 0; i < pProviders->cProviders; i++)
{
sProvider.Format(_T("%s\n"), pProviders->rgpszProviders[i]);
lstRegisteredProviders->AddHead(sProvider);
}
}
if (pProviders != NULL)
{
BCryptFreeBuffer(pProviders);
}
return true;
}
CString CMyCNGCryptFile::GetLastError()
{
return m_sError;
}
bool CMyCNGCryptFile::LastCryptBuffRead()
{
return (m_iLenghtFileToOpen<=m_iTotalByteRead);
}
void CMyCNGCryptFile::SetLenghtFileToOpen(ULONGLONG iLenghtFileToOpen )
{
m_iLenghtFileToOpen = iLenghtFileToOpen ;
}
void CMyCNGCryptFile::SetTotByteRead(UINT iByteRead)
{
m_iTotalByteRead += iByteRead ;
}
bool CMyCNGCryptFile::OpenMSPrimitiveProviderAES()
{
NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
ntStatus = BCryptOpenAlgorithmProvider( &m_hAesAlg, BCRYPT_AES_ALGORITHM, NULL, 0);
switch (ntStatus)
{
case STATUS_SUCCESS:
return true;
/* from msdn but not in NTSTATUS.H
case STATUS_NOT_FOUND:
m_sError.Format(_T("Error opening The algorithm handle. BCryptOpenAlgorithmProvider no provider was found for the specified algorithm ID. "));
break;
*/
case STATUS_INVALID_PARAMETER:
m_sError.Format(_T("Error opening The algorithm handle. BCryptOpenAlgorithmProvider one or more parameters are not valid. "));
break;
case STATUS_NO_MEMORY:
m_sError.Format(_T("Error opening The algorithm handle. BCryptOpenAlgorithmProvider a memory allocation failure occurred. "));
break;
default:
m_sError.Format(_T("Error opening The algorithm handle. BCryptOpenAlgorithmProvider return with error 0x%08x"), ntStatus);
break;
}
return false;
}
bool CMyCNGCryptFile::Crypt(bool bEncrypt,PUCHAR pbufFileToOpen, ULONG iBytesRead, ULONG cbIV, PBYTE pbufFileToSave, DWORD& iBufToSave)
{
NTSTATUS ntStatus =STATUS_UNSUCCESSFUL;
DWORD cbCipherText = 0;
if ( bEncrypt )
ntStatus = BCryptEncrypt( m_hKey, pbufFileToOpen, iBytesRead, NULL, m_pbIV, cbIV, pbufFileToSave, iBytesRead, &iBufToSave,0);
else
ntStatus = BCryptDecrypt( m_hKey, pbufFileToOpen, iBytesRead, NULL, m_pbIV, cbIV, pbufFileToSave, iBytesRead, &iBufToSave, 0);
switch(ntStatus)
{
case STATUS_SUCCESS:
return true;
case STATUS_BUFFER_TOO_SMALL :
m_sError.Format(_T("Error %s The size specified by the cbOutput parameter is not large enough to hold the ciphertext. Return with error 0x%08x"), bEncrypt?_T("BCryptEncrypt"):_T("BCryptDecrypt"), ntStatus);
break;
//Line found on msdn but not in bcrypt.h
// case STATUS_INVALID_BUFFER_SIZE :
// m_sError.Format(_T("Error %s The cbInput parameter is not a multiple of the algorithm's block size and the BCRYPT_BLOCK_PADDING or the BCRYPT_PAD_NONE flag was not specified in the dwFlags parameter. Return with error 0x%08x"), bEncrypt?"BCryptEncrypt":"BCryptDecrypt", ntStatus);
// break;
// case STATUS_INVALID_HANDLE :
// m_sError.Format(_T("Error %s The key handle in the hKey parameter is not valid. ", bEncrypt?"BCryptEncrypt":"BCryptDecrypt", ntStatus);
// break;
case STATUS_INVALID_PARAMETER :
m_sError.Format(_T("Error %s One or more parameters are not valid. Return with error 0x%08x"), bEncrypt?"BCryptEncrypt":"BCryptDecrypt", ntStatus);
break;
case STATUS_NOT_SUPPORTED :
m_sError.Format(_T("Error %s The algorithm does not support encryption. Return with error 0x%08x"), bEncrypt?"BCryptEncrypt":"BCryptDecrypt", ntStatus);
break;
default:
m_sError.Format(_T("Error %s return with error 0x%08x"), bEncrypt?"BCryptEncrypt":"BCryptDecrypt", ntStatus);
}
return false;
}
bool CMyCNGCryptFile::CryptLastByte(bool bEncrypt,PUCHAR pbufFileToOpen, ULONG iBytesRead, ULONG cbIV, PBYTE pbufFileToSave, DWORD& iBufToSave)
{
NTSTATUS ntStatus= STATUS_UNSUCCESSFUL;
DWORD cbCipherText = 0;
if (bEncrypt)
{
ntStatus = BCryptEncrypt(m_hKey, pbufFileToOpen, iBytesRead, NULL, m_pbIV, cbIV, NULL, 0, &cbCipherText, BCRYPT_BLOCK_PADDING);
if ( ntStatus != STATUS_SUCCESS )
{
m_sError.Format(_T("Error receiving the size required for the ciphertext. BCryptEncrypt return with error 0x%08x"), ntStatus);
return false;
}
ntStatus = BCryptEncrypt( m_hKey, pbufFileToOpen, iBytesRead, NULL, m_pbIV, cbIV, pbufFileToSave, cbCipherText, &cbCipherText, BCRYPT_BLOCK_PADDING);
switch(ntStatus)
{
case STATUS_SUCCESS:
iBufToSave = cbCipherText;
return true;
default:
m_sError.Format(_T("Error receiving ciphertext. BCryptEncrypt return with error 0x%08x"), ntStatus);
return false;
}
}
else
{
ntStatus = BCryptDecrypt( m_hKey, pbufFileToOpen, iBytesRead, NULL, m_pbIV, cbIV, NULL, 0, &cbCipherText, BCRYPT_BLOCK_PADDING);
if ( ntStatus != STATUS_SUCCESS )
{
m_sError.Format(_T("Error receiving the size required for the ciphertext. BCryptDecrypt return with error 0x%08x"), ntStatus);
return false;
}
ntStatus = BCryptDecrypt( m_hKey, pbufFileToOpen, iBytesRead, NULL, m_pbIV, cbIV, pbufFileToSave, cbCipherText, &cbCipherText, BCRYPT_BLOCK_PADDING);
switch(ntStatus)
{
case STATUS_SUCCESS:
iBufToSave = cbCipherText;
return true;
default:
m_sError.Format(_T("Error receiving ciphertext. BCryptDecrypt return with error 0x%08x"), ntStatus);
return false;
}
}
return false;
}
bool CMyCNGCryptFile::CreateSymmetricKey_SHA1_Hash(PCWSTR pwszText, DWORD cbKeyObject)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
BCRYPT_KEY_HANDLE hKey = NULL;
DWORD cbHashObject, cbResult;
BYTE rgbHash[20];
DWORD cbData = 0;
ntStatus = BCryptOpenAlgorithmProvider(&m_hHashAlg,BCRYPT_SHA1_ALGORITHM,NULL,0);
if(STATUS_SUCCESS != ntStatus)
{
m_sError.Format(_T("Error Open Algoritm for the key. BCryptOpenAlgorithmProvider failed with status: 0x%08x\n"), ntStatus);
return false;
}
ntStatus = BCryptGetProperty(m_hAesAlg, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbKeyObject, sizeof(DWORD), &cbData, 0);
if (ntStatus!=STATUS_SUCCESS)
{
m_sError.Format(_T("Error calculating the size of KeyObject. BCryptGetProperty return with error 0x%08x"), ntStatus);
return false;
}
m_pbKeyObject = (PBYTE)HeapAlloc (GetProcessHeap (), 0, cbKeyObject);
if(NULL == m_pbKeyObject)
{
m_sError.Format(_T("Error memory allocation key object on the heap failed"));
return false;
}
// Determine the size of the Hash object
ntStatus = BCryptGetProperty( m_hHashAlg,BCRYPT_OBJECT_LENGTH,(PBYTE) &cbHashObject,sizeof(DWORD),&cbResult,0);
if(STATUS_SUCCESS != ntStatus)
{
m_sError.Format(_T("Error determining the size of the Hash object. BCryptGetProperty failed with status: 0x%08x"), ntStatus);
return false;
}
m_pbHashObject = (PBYTE)malloc(cbHashObject);
if(NULL == m_pbHashObject)
{
m_sError.Format(_T("Error allocating Hash object memory"));
return false;
}
// Create the Hash object
ntStatus = BCryptCreateHash( m_hHashAlg, &m_hHash, m_pbHashObject, cbHashObject, NULL, 0, 0);
if(STATUS_SUCCESS != ntStatus)
{
m_sError.Format(_T("Error Creating the Hash object. BCryptCreateHash failed with status: 0x%08x"), ntStatus);
return false;
}
// Hash the data
ntStatus = BCryptHashData( m_hHash, (PBYTE)pwszText, (ULONG)wcslen(pwszText), 0 );
if(STATUS_SUCCESS != ntStatus)
{
m_sError.Format(_T("Error hashing the data. BCryptHashData failed with status: 0x%08x"), ntStatus);
return false;
}
// Finish the hash
ntStatus = BCryptFinishHash( m_hHash, rgbHash, sizeof(rgbHash), 0);
if(STATUS_SUCCESS != ntStatus)
{
m_sError.Format(_T("Error finish the hash. BCryptFinishHash failed with status: 0x%08x"), ntStatus);
return false;
}
ntStatus = BCryptGenerateSymmetricKey( m_hAesAlg, &hKey, m_pbKeyObject, cbKeyObject, rgbHash, SYMM_KEY_SIZE_SECRET, 0);
if(STATUS_SUCCESS != ntStatus)
{
m_sError.Format(_T("Error creating the key. BCryptGenerateSymmetricKey failed with status: 0x%08x"), ntStatus);
hKey = NULL;
}
m_hKey =hKey ;
return true;
}
bool CMyCNGCryptFile::CreateSymmetricKey_AES_CBC(DWORD &cbKeyObject, DWORD &cbIV )
{
NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
DWORD cbData = 0;
cbKeyObject = 0;
cbIV = 0;
ntStatus = BCryptGetProperty(m_hAesAlg, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbKeyObject, sizeof(DWORD), &cbData, 0);
if (ntStatus!=STATUS_SUCCESS)
{
m_sError.Format(_T("Error calculating the size of KeyObject. BCryptGetProperty return with error 0x%08x"), ntStatus);
return false;
}
m_pbKeyObject = (PBYTE)HeapAlloc (GetProcessHeap (), 0, cbKeyObject);
if(NULL == m_pbKeyObject)
{
m_sError.Format(_T("Error memory allocation key object on the heap failed"));
return false;
}
ntStatus = BCryptGetProperty( m_hAesAlg, BCRYPT_BLOCK_LENGTH, (PBYTE)&cbIV, sizeof(DWORD), &cbData, 0);
if (ntStatus!=STATUS_SUCCESS)
{
m_sError.Format(_T("Error calculating the block length for the IV. BCryptGetProperty return with error 0x%08x"), ntStatus);
return false;
}
if (cbIV > sizeof (rgbIV))
{
m_sError.Format(_T("Block length is longer than the provided IV length\n"));
return false;
}
m_pbIV= (PBYTE) HeapAlloc (GetProcessHeap (), 0, cbIV);
if(NULL == m_pbIV)
{
m_sError.Format(_T("Error memory allocation buffer for the IV on the heap failed"));
return false;
}
memcpy(m_pbIV, rgbIV, cbIV);
ntStatus = BCryptSetProperty(m_hAesAlg, BCRYPT_CHAINING_MODE, (PBYTE)BCRYPT_CHAIN_MODE_CBC, sizeof(BCRYPT_CHAIN_MODE_CBC), 0);
if (ntStatus!=STATUS_SUCCESS)
{
m_sError.Format(_T("Error setting the ChainingMode CBC. BCryptSetProperty return with error 0x%08x"), ntStatus);
return false;
}
// generate the key from supplied input key bytes
ntStatus = BCryptGenerateSymmetricKey(m_hAesAlg, &m_hKey, m_pbKeyObject, cbKeyObject, (PBYTE)rgbAES128Key, sizeof(rgbAES128Key), 0);
/* PBYTE pKey;
memcpy(pKey, sKey, sKey.GetLength());
ntStatus = BCryptGenerateSymmetricKey(m_hAesAlg, &m_hKey, m_pbKeyObject, cbKeyObject, (PBYTE) pKey, sKey.GetLength(), 0);
*/
if (ntStatus!=STATUS_SUCCESS)
{
m_sError.Format(_T("Error generate the key. BCryptGenerateSymmetricKey return with error 0x%08x"), ntStatus);
return false;
}
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -