aes-256-cbc加密/解密密钥不起作用

时间:2021-01-06 18:33:35

I made a simple file encryptor/decryptor. It takes the mode and the file to operate with as arguments. When encrypting, it generates random string and encrypts the file using that. When decrypting a file, it prompts the user for password and uses that when decrypting.

我做了一个简单的文件加密器/解密器。它将模式和文件作为参数进行操作。加密时,它会生成随机字符串并使用该字符串对文件进行加密。解密文件时,会提示用户输入密码,并在解密时使用该密码。

My problem is that I get gibberish instead of the plaintext when decrypting even though I carefully write the same key to the input.

我的问题是,即使我仔细地将相同的密钥写入输入,但在解密时我得到的是乱码而不是明文。

I tracked the problem to the passwords since everything worked flawlessly when I used constant password like

我跟踪密码的问题,因为当我使用常量密码时,一切都完美无缺

unsigned char constkey[] = "asd123";

and used it for both encryption and decryption.

并将其用于加密和解密。

What is making my keys different?

是什么让我的钥匙与众不同?

Big thanks for James K Polk for the encryption/decryption code!

非常感谢James K Polk的加密/解密代码!

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <time.h>
#include <errno.h>

#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif


/* Encrypt or decrypt, depending on flag 'should_encrypt' */
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 = malloc(BUFSIZE);
    unsigned char *cipher_buf;
    unsigned blocksize;
    int out_len;
    EVP_CIPHER_CTX ctx;

    EVP_CipherInit(&ctx, EVP_aes_256_cbc(), ckey, ivec, should_encrypt);
    blocksize = EVP_CIPHER_CTX_block_size(&ctx);
    cipher_buf = 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 rand_string(char *str, size_t size)
{
    size_t n;
    const char charset[] = "ABCDEFGHIJKLMNOPQRSTUWVXYZO1234567890";

    for (n = 0; n < size; n++) {
        int key = rand() % (int) (sizeof charset - 1);
        str[n] = charset[key];
    }

    str[size] = '\0';
    return 0;
}

void copyfile(FILE* from, FILE* to)
{
    fseek(from, 0, SEEK_END);
    long filesize = ftell(from);
    fseek(from, 0, SEEK_SET);
    char b[2];
    long a;

    for(a=0; a<filesize; a++)
    {
        fread(b, 1, 1, from);
        fwrite(b, 1, 1, to);
    }
}

int main(int argc, char *argv[]) {

    if (argc != 3) { printf("usage: %s mode file\n", argv[0]); return 0; }

    unsigned char ivec[] = "dontusethisinput";
    FILE *fIN, *fOUT;

    if (!strcmp(argv[1],"e"))
    {
        srand(time(NULL)); /* seed random */

        char passkey[6];
        rand_string(passkey,5); /* generate random password */

        if((fIN = fopen(argv[2], "rb")) == NULL){ printf("ERROR: %s\n", strerror(errno)); return 0; }
        fOUT = fopen("tempfile", "wb+");

        en_de_crypt(TRUE, fIN, fOUT, (unsigned char*)passkey, ivec); /* encrypt the file */

        fclose(fIN);
        fclose(fOUT);

        if((fIN = fopen(argv[2], "wb+")) == NULL){ printf("ERROR: %s\n", strerror(errno)); return 0; }
        fOUT = fopen("tempfile", "rb");

        copyfile(fOUT, fIN); /* replace the file with encrypted one */

        fclose(fIN);
        fclose(fOUT);

        printf("file encrypted with key [%s]\n", passkey);
    }
    else if(!strcmp(argv[1],"d"))
    {
        char key[6];
        printf("Password: ");
        fgets(key, 6, stdin); /* prompt for the key */
        key[5] = '\0';

        if((fIN = fopen(argv[2], "rb")) == NULL){ printf("ERROR: %s\n", strerror(errno)); return 0; }
        fOUT = fopen("tempfile", "wb+");

        en_de_crypt(FALSE, fIN, fOUT, (unsigned char*)key, ivec); /* decrypt the file */

        fclose(fIN);
        fclose(fOUT);

        if((fIN = fopen(argv[2], "wb+")) == NULL){ printf("ERROR: %s\n", strerror(errno)); return 0; }
        fOUT = fopen("tempfile", "rb");

        copyfile(fOUT, fIN); /* replace the file with decrypted one */

        fclose(fIN);
        fclose(fOUT);

        printf("file decrypted with key [%s]\n",key);
    }
    else { printf("invalid mode\n"); return 0; }

    remove("tempfile");
    return 0;
}

1 个解决方案

#1


2  

I tracked the problem to the passwords since everything worked flawlessly when I used constant password like

我跟踪密码的问题,因为当我使用常量密码时,一切都完美无缺

unsigned char constkey[] = "asd123";

unsigned char constkey [] =“asd123”;

and used it for both encryption and decryption.

并将其用于加密和解密。

AES don't use passwords it uses (binary) keys. In the case of AES-256, it expects a 256 bit long key. As OpenSSL will treat your constkey as a 256 bit key, it will read beyond what you provided and end up with some random data in the end of the key (if you are lucky to avoid any access violations).

AES不使用它使用的密码(二进制)密钥。在AES-256的情况下,它需要256位长的密钥。由于OpenSSL会将您的constkey视为256位密钥,因此它将超出您提供的内容,并最终在密钥的末尾添加一些随机数据(如果您幸运,可以避免任何访问冲突)。

If you do this within the same program, you properly end up with the same random data in the key on both encrypt and decrypt - and everything seems fine.

如果你在同一个程序中执行此操作,则在加密和解密时,您可以在密钥中正确地获得相同的随机数据 - 而且一切似乎都很好。

Try with correct key length.

尝试正确的密钥长度。

#1


2  

I tracked the problem to the passwords since everything worked flawlessly when I used constant password like

我跟踪密码的问题,因为当我使用常量密码时,一切都完美无缺

unsigned char constkey[] = "asd123";

unsigned char constkey [] =“asd123”;

and used it for both encryption and decryption.

并将其用于加密和解密。

AES don't use passwords it uses (binary) keys. In the case of AES-256, it expects a 256 bit long key. As OpenSSL will treat your constkey as a 256 bit key, it will read beyond what you provided and end up with some random data in the end of the key (if you are lucky to avoid any access violations).

AES不使用它使用的密码(二进制)密钥。在AES-256的情况下,它需要256位长的密钥。由于OpenSSL会将您的constkey视为256位密钥,因此它将超出您提供的内容,并最终在密钥的末尾添加一些随机数据(如果您幸运,可以避免任何访问冲突)。

If you do this within the same program, you properly end up with the same random data in the key on both encrypt and decrypt - and everything seems fine.

如果你在同一个程序中执行此操作,则在加密和解密时,您可以在密钥中正确地获得相同的随机数据 - 而且一切似乎都很好。

Try with correct key length.

尝试正确的密钥长度。