AES-256 GCM Encryption in C (bcrypt.h) does not decrypt in Python

53 Views Asked by At

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!

0

There are 0 best solutions below