BCryptDecrypt plaintext size is different from previous CryptDecrypt wincrypt APIS

Ritu Varkey 41 Reputation points
2023-05-11T08:31:39.3033333+00:00

I am tryng to update the encrypting algorithms from the old wincrypt APIs to the latest Bcrypt CNG APIs. The data is getting decrypted correctly except for the fact that the resultant plaintext size is different in both. In the new APIs the resultant plaintext data size is exactly same as the cipher text. In the older APIs the size of the decrypted plaintext is longer than the encrypted text. This change in size is resulting in the CRC check failing in the later parts of my code.

Is this expected behavior or am I missing something?

Windows development Windows API - Win32
Windows for business Windows Client for IT Pros User experience Other
Developer technologies C++
{count} votes

3 answers

Sort by: Most helpful
  1. kwikc 136 Reputation points
    2023-05-17T17:00:08.23+00:00

    Hello. I write a simple program with the old crypt APIs. I cannot find the problem you said. Can you provide some more information?

    The program is as below:

    #include <windows.h>
    #include <strsafe.h>
    #include <iostream>
    
    
    HCRYPTKEY  g_hkey = NULL;
    
    
    extern bool encrypt_text(const char*, DWORD* pdwDataLen, DWORD buffer_len);
    extern bool decrypt_text(BYTE*, DWORD* pdwDataLen);
    
    
    int main()
    {
        std::cout << "Test crypt APIs.\n";
    
    	char pText[100];
    	int buffer_size = _countof(pText);
    
    
    	// Copy text.
    	if (FAILED(StringCchCopyA(pText, buffer_size, "Test line.---"))) {
    		std::cout << "StringCchCopyA() failed.\n";
    		return 0;
    	}
    
    	// Calculate length.
    	size_t len;
    	if (FAILED(StringCchLengthA(pText, buffer_size, &len))) {
    		std::cout << "StringCchLengthA() failed.\n";
    		return 0;
    	}
    	std::cout << "[Before encrypted, length = " << len << "]: \"" << pText << "\"\n";
    
    	// Encrypt with null terminator.
    	DWORD dwDataLen = (DWORD)(len + 1);
    	if (!encrypt_text(pText, &dwDataLen, buffer_size))
    		return 0;
    
    	// Decrypt.
    	if (!decrypt_text((BYTE*)pText, &dwDataLen))
    		return 0;
    
    	// Calculate length again.
    	if (FAILED(StringCchLengthA(pText, buffer_size, &len))) {
    		std::cout << "StringCchLengthA() failed (2).\n";
    		return 0;
    	}
    	std::cout << "[After decrypted, length = " << len << "]: \"" << pText << "\"\n";
    
    	return 0;
    }
    
    
    bool encrypt_text(const char* pText, DWORD* pdwDataLen, DWORD buffer_len)
    {
    	HCRYPTPROV hprov = NULL;
    	DWORD dwProvType = PROV_RSA_FULL;
    	if (!CryptAcquireContext(&hprov, NULL, NULL, dwProvType, CRYPT_VERIFYCONTEXT)) {
    		std::cout << "CryptAcquireContext() failed.\n";
    		return false;
    	}
    
    	ALG_ID algid = CALG_3DES;
    	if (!CryptGenKey(hprov, algid, 0, &g_hkey)) {
    		std::cout << "CryptGenKey() failed.\n";
    		return false;
    	}
    
    	DWORD data_len = *pdwDataLen;
    	if (!CryptEncrypt(g_hkey, NULL, TRUE, 0, NULL, &data_len, 0)) {
    		std::cout << "CryptEncrypt() failed.\n";
    		return false;
    	}
    	if (data_len > buffer_len) {
    		std::cout << "Buffer is too small.\n";
    		return false;
    	}
    	if (!CryptEncrypt(g_hkey, NULL, TRUE, 0, (BYTE*)pText, pdwDataLen, buffer_len)) {
    		std::cout << "CryptEncrypt() failed (2).\n";
    		return false;
    	}
    
    	return true;
    }
    
    
    bool decrypt_text(BYTE* pbData, DWORD* pdwDataLen)
    {
    	if (!CryptDecrypt(g_hkey, 0, TRUE, 0, pbData, pdwDataLen)) {
    		std::cout << "CryptDecrypt() failed 2.\n";
    		return false;
    	}
    
    	return true;
    }
    
    

    The output is:

    Test crypt APIs.
    [Before encrypted, length = 13]: "Test line.---"
    [After decrypted, length = 13]: "Test line.---"
    
    
    0 comments No comments

  2. kwikc 136 Reputation points
    2023-05-17T17:06:23.3533333+00:00

    Hello. I write a simple program with the old crypt APIs. I cannot find the problem you said. Can you provide some more information?

    The program is as below:

    #include <windows.h>
    #include <strsafe.h>
    #include <iostream>
    
    
    HCRYPTKEY  g_hkey = NULL;
    
    
    extern bool encrypt_text(const char*, DWORD* pdwDataLen, DWORD buffer_len);
    extern bool decrypt_text(BYTE*, DWORD* pdwDataLen);
    
    
    int main()
    {
        std::cout << "Test crypt APIs.\n";
    
    	char pText[100];
    	int buffer_size = _countof(pText);
    
    
    	// Copy text.
    	if (FAILED(StringCchCopyA(pText, buffer_size, "Test line.---"))) {
    		std::cout << "StringCchCopyA() failed.\n";
    		return 0;
    	}
    
    	// Calculate length.
    	size_t len;
    	if (FAILED(StringCchLengthA(pText, buffer_size, &len))) {
    		std::cout << "StringCchLengthA() failed.\n";
    		return 0;
    	}
    	std::cout << "[Before encrypted, length = " << len << "]: \"" << pText << "\"\n";
    
    	// Encrypt with null terminator.
    	DWORD dwDataLen = (DWORD)(len + 1);
    	if (!encrypt_text(pText, &dwDataLen, buffer_size))
    		return 0;
    
    	// Decrypt.
    	if (!decrypt_text((BYTE*)pText, &dwDataLen))
    		return 0;
    
    	// Calculate length again.
    	if (FAILED(StringCchLengthA(pText, buffer_size, &len))) {
    		std::cout << "StringCchLengthA() failed (2).\n";
    		return 0;
    	}
    	std::cout << "[After decrypted, length = " << len << "]: \"" << pText << "\"\n";
    
    	return 0;
    }
    
    
    bool encrypt_text(const char* pText, DWORD* pdwDataLen, DWORD buffer_len)
    {
    	HCRYPTPROV hprov = NULL;
    	DWORD dwProvType = PROV_RSA_FULL;
    	if (!CryptAcquireContext(&hprov, NULL, NULL, dwProvType, CRYPT_VERIFYCONTEXT)) {
    		std::cout << "CryptAcquireContext() failed.\n";
    		return false;
    	}
    
    	ALG_ID algid = CALG_3DES;
    	if (!CryptGenKey(hprov, algid, 0, &g_hkey)) {
    		std::cout << "CryptGenKey() failed.\n";
    		return false;
    	}
    
    	DWORD data_len = *pdwDataLen;
    	if (!CryptEncrypt(g_hkey, NULL, TRUE, 0, NULL, &data_len, 0)) {
    		std::cout << "CryptEncrypt() failed.\n";
    		return false;
    	}
    	if (data_len > buffer_len) {
    		std::cout << "Buffer is too small.\n";
    		return false;
    	}
    	if (!CryptEncrypt(g_hkey, NULL, TRUE, 0, (BYTE*)pText, pdwDataLen, buffer_len)) {
    		std::cout << "CryptEncrypt() failed (2).\n";
    		return false;
    	}
    
    	return true;
    }
    
    
    bool decrypt_text(BYTE* pbData, DWORD* pdwDataLen)
    {
    	if (!CryptDecrypt(g_hkey, 0, TRUE, 0, pbData, pdwDataLen)) {
    		std::cout << "CryptDecrypt() failed 2.\n";
    		return false;
    	}
    
    	return true;
    }
    
    

    The output is:

    Test crypt APIs.
    [Before encrypted, length = 13]: "Test line.---"
    [After decrypted, length = 13]: "Test line.---"
    
    
    0 comments No comments

  3. Ritu Varkey 41 Reputation points
    2023-05-22T04:07:52.0266667+00:00

    I have found the solution. I was making a mistake with the padding. Thank you so much for the efforts.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.