I'm trying to encrypt "Hello, world!" in C and decrypt in Python, the encryption process results in no errors, but the Python decryption errors with ValueError: MAC check failed, and can't seem to find the problem.
C Encryption code:
NTSTATUS generateRandomBytes(BYTE *buffer, ULONG length) {
BCRYPT_ALG_HANDLE hProvider;
NTSTATUS status = BCryptOpenAlgorithmProvider(&hProvider, BCRYPT_RNG_ALGORITHM, NULL, 0);
if (!NT_SUCCESS(status)) {
return status;
}
status = BCryptGenRandom(hProvider, buffer, length, 0);
BCryptCloseAlgorithmProvider(hProvider, 0);
return status;
}
NTSTATUS encrypt_AES_GCM(const BYTE *plainData, ULONG plainDataLength,
const BYTE *iv, ULONG ivLength,
const BYTE *key, ULONG keyLength,
BYTE *encryptedData, ULONG encryptedDataLength)
{
NTSTATUS status = 0;
DWORD bytesDone = 0;
BCRYPT_ALG_HANDLE algHandle = 0;
status = BCryptOpenAlgorithmProvider(&algHandle, BCRYPT_AES_ALGORITHM, NULL, 0);
if (!NT_SUCCESS(status))
{
return status;
}
status = BCryptSetProperty(algHandle, BCRYPT_CHAINING_MODE, (PBYTE)BCRYPT_CHAIN_MODE_GCM, sizeof(BCRYPT_CHAIN_MODE_GCM), 0);
if (!NT_SUCCESS(status))
{
BCryptCloseAlgorithmProvider(algHandle, 0);
return status;
}
BCRYPT_KEY_HANDLE keyHandle = 0;
status = BCryptGenerateSymmetricKey(algHandle, &keyHandle, NULL, 0, (PUCHAR)key, keyLength, 0);
if (!NT_SUCCESS(status))
{
BCryptCloseAlgorithmProvider(algHandle, 0);
return status;
}
BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO authInfo;
BCRYPT_INIT_AUTH_MODE_INFO(authInfo);
authInfo.pbNonce = (PUCHAR)iv;
authInfo.cbNonce = ivLength;
status = BCryptEncrypt(keyHandle, (PUCHAR)plainData, plainDataLength, &authInfo, NULL, 0, encryptedData, encryptedDataLength, &bytesDone, 0);
if (!NT_SUCCESS(status))
{
BCryptDestroyKey(keyHandle);
BCryptCloseAlgorithmProvider(algHandle, 0);
return status;
}
BCryptDestroyKey(keyHandle);
BCryptCloseAlgorithmProvider(algHandle, 0);
return status;
}
int main() {
char *input = "Hello, world!";
BYTE key[32];
BYTE iv[12];
BYTE keyAndIV[44];
BYTE *encrypted;
ULONG encryptedSize = 14 + 16; // Input size (Hello, world!) is 14 bytes, and the automatically generated AAD is 16, so the output size is 30
// Generate key n iv
generateRandomBytes(key, sizeof(key));
generateRandomBytes(iv, sizeof(iv));
// Concatenate key and IV
memcpy(keyAndIV, key, sizeof(key));
memcpy(keyAndIV + sizeof(key), iv, sizeof(iv));
// Print the infoo
printf("Key:\n");
for (int i = 0; i < sizeof(key); i++) {
printf("%02X", key[i]);
}
printf("\n");
printf("IV:\n");
for (int i = 0; i < sizeof(iv); i++) {
printf("%02X", iv[i]);
}
printf("\n");
encrypted = (BYTE *)malloc(encryptedSize);
// Encrypt
encrypt_AES_GCM((BYTE*)input, 14, iv, 12, key, 32, encrypted, encryptedSize);
printf("Encrypted bytes:\n");
for (ULONG i = 0; i < encryptedSize; i++) {
printf("%02X", encrypted[i]);
}
printf("\n");
free(encrypted);
return 0;
}
And the Python code:
from Crypto.Cipher import AES
key = bytes.fromhex('')
iv = bytes.fromhex('')
authTag = bytes.fromhex('')
ciphertext = bytes.fromhex('')
cipher = AES.new(key, AES.MODE_GCM, nonce=iv)
plaintext = cipher.decrypt_and_verify(ciphertext, authTag)
print("Decrypted plaintext:", plaintext.decode('utf-8'))
Example outputs of both: C
Key:
14D63CB4BDE1A3D164DB09E44B6C877613CB7C0E281148653BE3EDFC9D476C73
IV:
27FEF35218E2FC4391971C5F
Encrypted bytes:
A0660CFE8F01000050010CFE8F0100003A5C50726F6772616D2046696C65
Python
Traceback (most recent call last):
File "C:\Users\User\Documents\Projects\Testing code\test.py", line 64, in <module>
plaintext = cipher.decrypt_and_verify(ciphertext, authTag)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\User\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\Crypto\Cipher\_mode_gcm.py", line 567, in decrypt_and_verify
self.verify(received_mac_tag)
File "C:\Users\User\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\Crypto\Cipher\_mode_gcm.py", line 508, in verify
raise ValueError("MAC check failed")
ValueError: MAC check failed
The Python data is all added from the C output, the auth tag is set to the last 16 bytes of the encrypted data, and the first 14 as the ciphertext
I have tried changing the iv to 12x A's and made the key simpler, so seems to be a problem with the authentication tag.
Thanks in advance!