I'm trying to encrypt a ZIP file using AES-256 GCM in C and decrypting it in Python. Here is the C code I'm using:
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,
BYTE *authTag, ULONG authTagLength)
{
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;
authInfo.pbTag = authTag;
authInfo.cbTag = authTagLength;
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 GCM_Encrypt_File(char *FileToEncrypt, char *keys, char *OutputFile)
{
int fd;
long file_size;
char *input;
_sopen_s(&fd, FileToEncrypt, _O_RDONLY, _SH_DENYRW, _S_IREAD);
file_size = _filelength(fd);
input = (char *)malloc(file_size);
size_t bytes_read = fread(input, 1, file_size, _fdopen(fd, "rb"));
BYTE key[32];
BYTE iv[12];
BYTE KeyTagIV[60];
BYTE *encrypted;
ULONG encryptedSize = file_size;
ULONG authTagLength = 16;
BYTE authTag[16];
// Generate key and iv
generateRandomBytes(key, sizeof(key));
generateRandomBytes(iv, sizeof(iv));
// Concatenate key and IV
memcpy(KeyTagIV, key, sizeof(key));
memcpy(KeyTagIV + sizeof(key), iv, sizeof(iv));
// Print the info
encrypted = (BYTE *)malloc(encryptedSize);
// Encrypt
encrypt_AES_GCM((BYTE *)input, file_size, iv, 12, key, 32, encrypted, encryptedSize, authTag, authTagLength);
// Print data
printf("KEY:\n");
for (ULONG i = 0; i < sizeof(key); i++)
{
printf("%02X", key[i]);
}
printf("\n");
printf("IV:\n");
for (ULONG i = 0; i < sizeof(iv); i++)
{
printf("%02X", iv[i]);
}
printf("\n");
printf("Authentication tag:\n");
for (ULONG i = 0; i < authTagLength; i++)
{
printf("%02X", authTag[i]);
}
printf("\n");
// Add authentication tag to the KeyTagIV variable
memcpy(KeyTagIV + 44, authTag, authTagLength);
memcpy(keys, KeyTagIV, 60);
printf("FULL:\n");
for (ULONG i = 0; i < 60; i++)
{
printf("%02X", KeyTagIV[i]);
}
printf("\n");
FILE *encryptedFile = fopen(OutputFile, "wb");
fwrite(encrypted, sizeof(char), file_size, encryptedFile);
free(encrypted);
return 1;
}
int main()
{
// GCM Encrypt the File.
char key_data[60];
char path[] = "test.txt";
char path1[] = "test.enc";
GCM_Encrypt_File(path, key_data, path1);
printf("Decryption Data:");
for (int i = 0; i < 60; i++) {
printf("%02X ", key_data[i]);
}
return 0;
}
and I'm trying to decrypt the data with this Python code:
import rsa
from Crypto.Cipher import AES
import base64
import os
if __name__ == '__main__':
# Decryption data in HEX KEY; IV; TAG
KEYS = """540AA548ADBBF19820FEC1DDF9BC19B6230A746C0CF0EA87E083FDF314867DA525F299D2B9FEBC26A864A9F149D3A60B05E03CA9C3328E5AB10228DB"""
encrypted_keys = bytearray.fromhex(KEYS)
ENC_PATH = "test.enc"
keys_data = encrypted_keys
key = keys_data[:32]
iv = keys_data[32:44]
authTag = keys_data[44:60]
ciphertext = open(ENC_PATH, mode="rb").read()
cipher = AES.new(key, AES.MODE_GCM, nonce=iv)
plaintext = cipher.decrypt_and_verify(ciphertext, authTag)
with open('decrypted_test.txt', 'wb') as f:
f.write(plaintext)
print("Done.")
#decrypt_rsa(input_filename, output_filename)
This code seems to work, when for example encrypting a .txt file with just "Hello, world!". So it's able to decrypt it correctly.
The problem is that when I try and encrypt a .zip file like this:
The decrypted output data looks like this:
The .txt file is gone, and the test2.zip says "Corrupted" when trying to open. The test1.zip still opens correctly.
Could the algorithm be corrupting it? Or is there something wrong in my code?
You need to open fd
in binary mode.
_sopen_s(&fd, FileToEncrypt, _O_RDONLY, _SH_DENYRW, _S_IREAD);
should be
_sopen_s(&fd, FileToEncrypt, _O_RDONLY | _O_BINARY, _SH_DENYRW, _S_IREAD);