OpenSSL的AES-256每次都会产生不同的密文

nic*_*ona 2 c++ encryption openssl aes

这是代码:

#include <QCoreApplication>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <iostream>

void en_de_crypt(int should_encrypt, FILE *ifp, FILE *ofp, unsigned char *ckey, unsigned char *ivec) {

    const unsigned BUFSIZE=4096;
    unsigned char *read_buf = (unsigned char*)malloc(BUFSIZE);
    unsigned char *cipher_buf;
    unsigned blocksize;
    int out_len;
    EVP_CIPHER_CTX ctx;

    for(int i=0; i<8;i++)
    {
        printf("%c\n",ckey[i]);
    }

     printf("\n\n");

    for(int i=0; i<8;i++)
    {
        printf("%c\n",ivec[i]);
    }

    EVP_CipherInit(&ctx, EVP_aes_256_cbc(), ckey, ivec, should_encrypt);
    blocksize = EVP_CIPHER_CTX_block_size(&ctx);
    cipher_buf = (unsigned char *)malloc(BUFSIZE + blocksize);

    while (1) {

        // Read in data in blocks until EOF. Update the ciphering with each read.

        int numRead = fread(read_buf, sizeof(unsigned char), BUFSIZE, ifp);
        EVP_CipherUpdate(&ctx, cipher_buf, &out_len, read_buf, numRead);
        fwrite(cipher_buf, sizeof(unsigned char), out_len, ofp);
        if (numRead < BUFSIZE) { // EOF
            break;
        }
    }

    // Now cipher the final block and write it out.

    EVP_CipherFinal(&ctx, cipher_buf, &out_len);
    fwrite(cipher_buf, sizeof(unsigned char), out_len, ofp);

    // Free memory

    free(cipher_buf);
    free(read_buf);
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    std::string pathToFiles = "C:/Temp/testEnc/dqdokoleda.7z";
    unsigned char ckey[8];
    unsigned char ivec[8];

    ckey[0] = 'p';
    ckey[1] = 'a';
    ckey[2] = 's';
    ckey[3] = 's';
    ckey[4] = 'w';
    ckey[5] = 'o';
    ckey[6] = 'r';
    ckey[7] = 'd';

    ivec[0] = 'a';
    ivec[1] = 'c';
    ivec[2] = 'g';
    ivec[3] = 't';
    ivec[4] = 'i';
    ivec[5] = 'j';
    ivec[6] = 'o';
    ivec[7] = 'r';



    FILE *fIN, *fOUT;

    // First encrypt the file

    fIN = fopen((pathToFiles).c_str(), "rb"); //File to be encrypted; plain text
    fOUT = fopen((pathToFiles+".enc").c_str(), "wb"); //File to be written; cipher text

    en_de_crypt(1, fIN, fOUT, ckey, ivec);

    fclose(fIN);
    fclose(fOUT);

    //Decrypt file now

    fIN = fopen((pathToFiles+".enc").c_str(), "rb"); //File to be read; cipher text
    fOUT = fopen((pathToFiles+".decrypted").c_str(), "wb"); //File to be written; cipher text

    en_de_crypt(0, fIN, fOUT, ckey, ivec);

    fclose(fIN);
    fclose(fOUT);

    std::cout << "END" << std::endl;

    return a.exec();
}
Run Code Online (Sandbox Code Playgroud)

问题是当我对.enc文件具有不同内容时对解密部分进行评论时.然后,如果我尝试解密分别取消注释解密和注释加密部分代码,文件没有被正确解密(7zip说它无法打开它).如果我不评论代码的任何部分,则加密和解密成功完成.

我使用QT5.5.1和文件的加密和解密之间我打扫卫生,运行的qmake,重建并与MSVC 12.0编译调试模式下运行(这并不重要,但如果程序正常工作适合你 - 尝试之间的清洁和建筑加密和解密一个文件,看它不像它应该工作).

Art*_* B. 6

AES支持128位的块大小,密钥大小为128,192和256位.在许多模式中,IV必须与块大小相同,特别是在CBC模式下.问题是你只使用64位的IV和64位的密钥.您需要提供16字节IV(适用于所有AES变体)和32字节密钥(适用于AES-256).

我的猜测是EVP_CipherInit将尝试读取完整的IV和密钥,因此将读入未初始化的内存,在每个程序执行中可能有任意数据.

请记住,必须为每个加密随机生成IV,以提供语义安全性.如果IV是静态的并且您使用相同的密钥,那么攻击可能会推断您仅通过观察密文来加密相同的消息.因此,随机化密文是一种安全属性.如果要检查加密是否有效,则需要尝试解密并将结果与​​原始明文进行比较.您可以将IV存储在密文文件格式的开头.

看起来您想要使用密码作为加密密钥.不要将密码与密钥混淆.密码具有非常小的熵,而密钥通常看起来像噪声.如果要使用密码,则需要从密码派生密钥.这通常与PBKDF2做(PKCS5_PBKDF2_HMACEVP_sha256,如果你想AES-256键)用随机盐和多次迭代(至少60万人,可以是几百万).您可以将盐存储在IV旁边的密文文件格式的开头.