bcrypts AES-256 GCM 加密会损坏 ZIP 文件吗?

问题描述 投票:0回答:1

我正在尝试在 C 中使用 AES-256 GCM 加密 ZIP 文件,并在 Python 中解密。这是我正在使用的 C 代码:

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;
}

我正在尝试使用以下 Python 代码解密数据:

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)

此代码似乎可以工作,例如仅使用“Hello, world!”加密 .txt 文件。所以它能够正确解密。

问题是,当我尝试像这样加密 .zip 文件时:

解密后的输出数据如下所示:

.txt 文件消失了,并且 test2.zip 在尝试打开时显示“已损坏”。 test1.zip 仍然可以正确打开。

算法会破坏它吗?还是我的代码有问题?

python c corruption aes-gcm
1个回答
0
投票

您需要以二进制模式打开

fd

_sopen_s(&fd, FileToEncrypt, _O_RDONLY, _SH_DENYRW, _S_IREAD);
应该是

_sopen_s(&fd, FileToEncrypt, _O_RDONLY | _O_BINARY, _SH_DENYRW, _S_IREAD);
    
© www.soinside.com 2019 - 2024. All rights reserved.