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

📄 crypto.cpp

📁 要在最低visual studio 2005的版本下运行
💻 CPP
字号:
#include "stdafx.h"
#include "Crypto.h"

//	Tell the linker to link the to the Cryptography API.
#pragma comment(lib, "Advapi32.lib")

using namespace MFC;

//	Constructor, intialises Crypto API.
CCrypto::CCrypto() : m_hCryptProv(NULL), m_hKey(NULL), m_hHash(NULL)
{
	//	Create the Crypt context.
	if(!::CryptAcquireContext(&m_hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) 
		return;

	//	Create an empty hash object.
	if(!::CryptCreateHash(m_hCryptProv, CALG_MD5, 0, 0, &m_hHash)) 
		return;

	//	Memory files are opened automatically on construction, we don't
	//	explcitly call open.
}

//	Destructor, frees Crypto stuff.
CCrypto::~CCrypto()
{
	//	Close the file.
	m_file.Close();

	// Clean up.
	if(m_hHash)
		::CryptDestroyHash(m_hHash);

	if(m_hKey)
		::CryptDestroyKey(m_hKey);

	if(m_hCryptProv)
		::CryptReleaseContext(m_hCryptProv, 0);
}

//	Derive a key from a password.
bool CCrypto::DeriveKey(CString strPassword)
{
	//	Return failure if we don't have a context or hash.
	if(m_hCryptProv == NULL || m_hHash == NULL)
		return false;

	//	If we already have a hash, trash it.
	if(m_hHash)
	{
		CryptDestroyHash(m_hHash);
		m_hHash = NULL;
		if(!CryptCreateHash(m_hCryptProv, CALG_MD5, 0, 0, &m_hHash)) 
			return false;
	}

	//	If we already have a key, destroy it.
	if(m_hKey)
	{
		::CryptDestroyKey(m_hKey);
		m_hKey = NULL;
	}

	//	Hash the password. This will have a different result in UNICODE mode, as it
	//	will hash the UNICODE string (this is by design, allowing for UNICODE passwords, but
	//	it's important to be aware of this behaviour.
	if(!CryptHashData(m_hHash, (const BYTE*)strPassword.GetString(), strPassword.GetLength() * sizeof(TCHAR), 0)) 
		return false;
	
	//	Create a session key based on the hash of the password.
	if(!CryptDeriveKey(m_hCryptProv, CALG_RC2, m_hHash, CRYPT_EXPORTABLE, &m_hKey))
		return false;

	//	And we're done.
	return true;
}

bool CCrypto::Encrypt(const CObject& serializable, CByteArray& arData)
{
	//	Return failure if we don't have a context or key.
	if(m_hCryptProv == NULL || m_hKey == NULL)
		return false;

	//	Return failure if the object is not serializable.
	if(serializable.IsSerializable() == FALSE)
		return false;

	//	Before we write to the file, trash it.
	m_file.SetLength(0);

	//	Create a storing archive from the memory file.
	CArchive ar(&m_file, CArchive::store);

	//	We know that serialzing an object will not change it's data, as we can
	//	safely use a const cast here.

	//	Write the data to the memory file.
	const_cast<CObject&>(serializable).Serialize(ar);
	
	//	Close the archive, flushing the write.
	ar.Close();

	//	Encrypt the contents of the memory file and store the result in the array.
	return InternalEncrypt(arData);
}

bool CCrypto::Decrypt(const CByteArray& arData, CObject& serializable)
{
	//	Return failure if we don't have a context or key.
	if(m_hCryptProv == NULL || m_hKey == NULL)
		return false;

	//	Return failure if the object is not serializable.
	if(serializable.IsSerializable() == FALSE)
		return false;

	//	Decrypt the contents of the array to the memory file.
	if(InternalDecrypt(arData) == false)
		return false;

	//	Create a reading archive from the memory file.
	CArchive ar(&m_file, CArchive::load);

	//	Read the data from the memory file.
	serializable.Serialize(ar);
	
	//	Close the archive.
	ar.Close();

	//	And we're done.
	return true;
}

bool CCrypto::Encrypt(const CString& str, CByteArray& arData)
{
	//	Return failure if we don't have a context or key.
	if(m_hCryptProv == NULL || m_hKey == NULL)
		return false;

	//	Before we write to the file, trash it.
	m_file.SetLength(0);

	//	Create a storing archive from the memory file.
	CArchive ar(&m_file, CArchive::store);

	//	Write the string to the memory file.
	ar << str;

	//	Close the archive, flushing the write.
	ar.Close();

	//	Encrypt the contents of the memory file and store the result in the array.
	return InternalEncrypt(arData);
}

bool CCrypto::Decrypt(const CByteArray& arData, CString& str)
{
	//	Return failure if we don't have a context or key.
	if(m_hCryptProv == NULL || m_hKey == NULL)
		return false;

	//	Decrypt the contents of the array to the memory file.
	if(InternalDecrypt(arData) == false)
		return false;

	//	Create a reading archive from the memory file.
	CArchive ar(&m_file, CArchive::load);

	//	Read the data from the memory file.
	ar >> str;
	
	//	Close the archive.
	ar.Close();

	//	And we're done.
	return true;
}

bool CCrypto::InternalEncrypt(CByteArray& arDestination)
{
	//	Get the length of the data in memory. Increase the capacity to handle the size of the encrypted data.
	ULONGLONG uLength = m_file.GetLength();
	ULONGLONG uCapacity = uLength * 2;
	m_file.SetLength(uCapacity);

	//	Acquire direct access to the memory.
	BYTE* pData = m_file.Detach();

	//	We need a DWORD to tell encrypt how much data we're encrypting.
	DWORD dwDataLength = static_cast<DWORD>(uLength);

	//	Now encrypt the memory file.
	if(!::CryptEncrypt(m_hKey, NULL, TRUE, 0, pData, &dwDataLength, static_cast<DWORD>(uCapacity)))
	{
		//	Free the memory we release from the memory file.
		delete [] pData;

		return false;
	}	

	//	Assign all of the data we have encrypted to the byte array- make sure anything 
	//	already in the array is trashed first.
	arDestination.RemoveAll();
	arDestination.SetSize(static_cast<INT_PTR>(dwDataLength));
	memcpy(arDestination.GetData(), pData, dwDataLength);

	//	Free the memory we release from the memory file.
	delete [] pData;

	return true;
}

bool CCrypto::InternalDecrypt(const CByteArray& arSource)
{
	//	Trash the file.
	m_file.SetLength(0);

	//	Write the contents of the byte array to the memory file.
	m_file.Write(arSource.GetData(), static_cast<UINT>(arSource.GetCount()));
	m_file.Flush();

	//	Acquire direct access to the memory file buffer.
	BYTE* pData = m_file.Detach();

	//	We need a DWORD to tell decrpyt how much data we're encrypting.
	DWORD dwDataLength = static_cast<DWORD>(arSource.GetCount());
	DWORD dwOldDataLength = dwDataLength;

	//	Now decrypt the data.
	if(!::CryptDecrypt(m_hKey, NULL, TRUE, 0, pData, &dwDataLength))
	{
		//	Free the memory we release from the memory file.
		delete [] pData;

		return false;
	}

	//	Set the length of the data file, write the decrypted data to it.
	m_file.SetLength(dwDataLength);
	m_file.Write(pData, dwDataLength);
	m_file.Flush();
	m_file.SeekToBegin();

	//	Free the memory we release from the memory file.
	delete [] pData;

	return true;
}

⌨️ 快捷键说明

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