【问题标题】:aes-256-cbc encryption/decryption keys don't workaes-256-cbc 加密/解密密钥不起作用
【发布时间】:2016-03-21 09:25:22
【问题描述】:

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

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

我跟踪了密码问题,因为当我使用像

这样的常量密码时,一切都完美无缺
unsigned char constkey[] = "asd123";

并将其用于加密和解密。

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

非常感谢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;
}

【问题讨论】:

  • EVP_CipherInit() 的返回值是多少?如果fread() 返回0-1 会发生什么? fwrite() 返回什么?
  • unsigned char constkey[] = "asd123"; - 看起来你已经很幸运了……

标签: c string encryption input openssl


【解决方案1】:

由于一切正常,我跟踪了密码问题 当我使用恒定密码时完美无瑕,例如

unsigned char constkey[] = "asd123";

并将其用于两种加密 和解密。

AES 不使用它使用(二进制)密钥的密码。对于 AES-256,它需要 256 位 长密钥。由于 OpenSSL 会将您的 constkey 视为 256 位 密钥,因此它将读取超出您提供的内容并在密钥末尾得到一些随机数据(如果您幸运地避免了任何访问违规) .

如果您在同一个程序中执行此操作,您最终会在密钥中正确地加密和解密相同的随机数据 - 并且一切似乎都很好。

尝试使用正确的密钥长度。

【讨论】:

  • 嗨,我在使用 AES 256 加密时遇到问题。我目前正在加密一个字段并存储在数据库中,现在当我尝试在另一个文件中解密它时它不起作用。我不断收到错误:错误:0606506D:数字信封例程:EVP_DecryptFinal_ex:最终块长度错误。另外,我的 iv 和 key 的值应该是多少?
猜你喜欢
  • 1970-01-01
  • 2013-08-11
  • 1970-01-01
  • 2021-05-11
  • 1970-01-01
  • 1970-01-01
  • 2017-11-26
  • 2015-07-19
  • 1970-01-01
相关资源
最近更新 更多