C++ CryptoAPI: How to encrypt file for distribution to multiple receivers

0

I've updated this to more thoroughly describe what's going on. Hope I haven't broken any rules in doing so.

Second update: changed decryption on the application side (After "The following adapted from...").

I have a text file which I encrypt on a source machine. The resulting file needs to be distributed to a number of destination machines and decrypted on the fly for presentation there. Transmission security is not an issue; our primary concern is with data integrity for reporting purposes; the end user should not be able to edit a free text file - hence, the encryption. On the source machine, my encryption and decryption work fine. This is the source encryption:

HCRYPTPROV m_hCryptProv;
HCRYPTKEY m_hSigKey;
HCRYPTKEY m_hExchKey;
HCRYPTHASH m_hHash;
CMemFile m_file;
CString m_strPassword;
CString m_strData;
CByteArray arData;
CFile file;
DWORD dwBlobLen = 0;
BYTE* pbKeyBlob;

CryptAcquireContext(&m_hCryptProv, NULL, NULL, PROV_RSA_FULL, 0);
CryptCreateHash(m_hCryptProv, CALG_MD5, 0, 0, &m_hHash);
CryptHashData(m_hHash, (const BYTE*)strPassword.GetString(), strPassword.GetLength() * sizeof(TCHAR), 0);
CryptDeriveKey(m_hCryptProv, CALG_RC2, m_hHash, CRYPT_EXPORTABLE, &m_hSigKey);

// m_strData is input to be encrypted
m_crypto.Encrypt(m_strData, arData);
file.Write(arData.GetData(), static_cast<UINT>(arData.GetCount()));
file.Flush();
file.Close();

// encrypted file "file" copied to target machine as "GlobalOperator.dat".

// Generate exchange key and write to file.
CryptGetUserKey(m_hCryptProv, AT_KEYEXCHANGE, &m_hExchKey);
CryptExportKey(m_hExchKey, 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen);
pbKeyBlob = (BYTE*)malloc(dwBlobLen);
//CryptExportKey(m_hExchKey, 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen);
CryptExportKey(m_hExchKey, 0, PUBLICKEYBLOB, 0, pbKeyBlob, &dwBlobLen);
file.Write(pbKeyBlob, dwBlobLen);
file.Flush();
file.Close();

// key file "file" copied to target machine as "key.dat".

The target machine(s) run an application an attempts to read the encrypted file:

CString m_strData;
CByteArray arData;
CFile GlobalOperatorFile;

GlobalOperatorFile.Open("GlobalOperator.dat")
arData.SetSize(static_cast<INT_PTR>(GlobalOperatorFile.GetLength()));
GlobalOperatorFile.Read(arData.GetData(), static_cast<UINT>(GlobalOperatorFile.GetLength()));
GlobalOperatorFile.Close();

// Try to deserialize the data.
DWORD dwBlobLen = 0;
CMemFile m_file;
m_file.SetLength(0);

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

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

DWORD dwDataLength = static_cast<DWORD>(arData.GetCount());

// The following adapted from https://docs.microsoft.com/en-us/windows/win32/seccrypto/example-c-program-decrypting-a-file
CryptCreateHash(m_hCryptProv, CALG_MD5, 0, 0, &m_hHash);
CString pwd = "EncryptionKey";
CryptHashData(m_hHash, (const BYTE*)pwd.GetString(), pwd.GetLength() * sizeof(TCHAR), 0);
CryptDeriveKey(m_hCryptProv, CALG_RC2, m_hHash, CRYPT_EXPORTABLE, &m_hKey);
CryptDecrypt(m_hKey, NULL, TRUE, 0, pData, &dwDataLength);

// The above call to CryptDecrypt fails with error code 0x80090005: NTE_BAD_DATA

So I clearly have no idea what I'm doing with encryption/decryption.

Can anyone help?


c++
encryption
cryptoapi
asked on Stack Overflow Jul 19, 2019 by P. S. Underwood • edited Jul 23, 2019 by P. S. Underwood

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0