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

📄 mycngcryptfile.cpp

📁 用vs2005 CNG写的一个加密文件及产生Product key 的demon
💻 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 + -