【发布时间】:2014-09-11 10:32:33
【问题描述】:
我想要做什么: 用 C 语言编写一个程序,打开一个任意大小的文件并读取其内容。读取内容后,它将在 AES 256 CBC 中对其进行加密,并将密文保存到名为 ciphertext 的文件中。保存后,它将关闭这两个文件。然后将从刚刚保存的文件中打开密文并解密密文并将其保存到一个名为decrypted的文件中。
我的问题: 它似乎永远不会解密我的密文。我得到垃圾,我不知道我做错了什么。请帮忙。
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
void encrypt(FILE *ifp, FILE *ofp)
{
//Get file size
fseek(ifp, 0L, SEEK_END);
int fsize = ftell(ifp);
//set back to normal
fseek(ifp, 0L, SEEK_SET);
int outLen1 = 0; int outLen2 = 0;
unsigned char *indata = malloc(fsize);
unsigned char *outdata = malloc(fsize*2);
unsigned char ckey[] = "thiskeyisverybad";
unsigned char ivec[] = "dontusethisinput";
//Read File
fread(indata,sizeof(char),fsize, ifp);//Read Entire File
//Set up encryption
EVP_CIPHER_CTX ctx;
EVP_EncryptInit(&ctx,EVP_aes_256_cbc(),ckey,ivec);
EVP_EncryptUpdate(&ctx,outdata,&outLen1,indata,fsize);
EVP_EncryptFinal(&ctx,outdata,&outLen2);
fwrite(outdata,sizeof(char),fsize,ofp);
}
void decrypt(FILE *ifp, FILE *ofp)
{
//Get file size
fseek(ifp, 0L, SEEK_END);
int fsize = ftell(ifp);
//set back to normal
fseek(ifp, 0L, SEEK_SET);
int outLen1 = 0; int outLen2 = 0;
unsigned char *indata = malloc(fsize);
unsigned char *outdata = malloc(fsize*2);
unsigned char ckey[] = "thiskeyisverybad";
unsigned char ivec[] = "dontusethisinput";
//Read File
fread(indata,sizeof(char),fsize, ifp);//Read Entire File
//setup decryption
EVP_CIPHER_CTX ctx;
EVP_DecryptInit(&ctx,EVP_aes_256_cbc(),ckey,ivec);
EVP_DecryptUpdate(&ctx,outdata,&outLen1,indata,fsize);
EVP_DecryptFinal(&ctx,outdata,&outLen2);
fwrite(outdata,sizeof(char),fsize,ofp);
}
int main(int argc, char *argv[])
{
FILE *fIN, *fOUT;
fIN = fopen("plain.txt", "rb");//File to be encrypted; plain text
fOUT = fopen("cyphertext.txt", "wb");//File to be written; cipher text
encrypt(fIN, fOUT);
fclose(fIN);
fclose(fOUT);
//Decrypt file now
fIN = fopen("cyphertext.txt", "rb");//File to be written; cipher text
fOUT = fopen("decrypted.txt", "wb");//File to be written; cipher text
decrypt(fIN,fOUT);
fclose(fIN);
fclose(fOUT);
return 0;
}
注意:可能有一些拼写错误。 编辑:似乎我在密钥和 IV 上犯了一个错误,它们都是 128 位的,我正在尝试使用 256 位的 CBC。这是我的问题,一旦我将其更改为
EVP_aes_128_cbc()
【问题讨论】:
-
您假设输出文件的长度与输入的长度相同是错误的。另外,您确定您的 C 编译器支持动态数组吗?通常你必须
mallocindata 和 outdata。 -
好的,所以如果我说输出文件至少是输入大小的 2 倍,我会安全吗?或者,还有更好的方法?同样在动态数组方面,我不确定我的编译器是否这样做(代码块默认,应该是 GCC)。不管我做了 malloc(fsize) 和 malloc(fsize*2)。它仍然给我垃圾数据。
-
您的 EVP_*Update() 方法正在覆盖 outdata 数组的开头。你需要像
EVP_EncryptFinal(&ctx,outdata + outLen1,&outLen2);这样的东西。解密也是一样。 -
不完全确定它是如何工作的,不是第二个参数 unsigned char * 并且如果我添加一个 int 如何防止方法被覆盖?
-
感谢 GregS 得到了我的答复。虽然我仍然不确定为什么这个技巧有效,但确实有效。
标签: c encryption cryptography openssl aes