我一直在研究这个问题几个小时,首先我想解释一下我要做的事情;使用OpenSSL在C中加密/解密文件。问题似乎出现在解密方法中。文档很少,我把它拼凑在一起,还有书籍等。
运行代码时,输出中没有问题。打开预期的解密文件时,它实际上仍然是加密的......
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <openssl/aes.h>
#include <openssl/bio.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include <string.h>
#include <openssl/evp.h>
#include <sys/stat.h>
#include <errno.h>
/*=========================================================================|
Encryption Method below, This Will Take The File And Use The Keys And IV
To Encrypt The Data/File. We Use Long Here Because Int Only Is Good For <2GB
Data Size And Will Get ERRORS If File Is Larger Than >= 2GB Which Is As Common
as gold-diggers. */
void encrypt_process()
{
unsigned char key[] = "badidea";
unsigned char vec[] = "again";
FILE *Input_File;
FILE *Output_file;
Input_File =fopen("french.txt", "rb");
Output_file = fopen("ult.txt", "wb");//File to be written; cipher text
fseek(Input_File, 0, SEEK_END);
unsigned long len = (unsigned long)ftell(Input_File); // use long as the file if >2GB will blow past int
printf("length of the file is : %lu", len);
unsigned long outLen1 = 0;
unsigned long outLen2 = 0;
unsigned char *indata = malloc(len);
unsigned char *outdata = malloc(len);
fread(indata,sizeof(char),len, Input_File);//Read Entire File
/*-----------------------------------------------------------------*\
<||| Set Up Encryption As Defined in OPENSSH using their syntax etc.>>>
*-----------------------------------------------------------------*/
//initiating cipher
EVP_CIPHER_CTX ctx;
EVP_EncryptInit(&ctx,EVP_aes_128_cbc(),key,vec);
EVP_EncryptUpdate(&ctx,outdata,&outLen1,indata,len);
EVP_EncryptFinal(&ctx,outdata + outLen1,&outLen2);
fwrite(outdata,sizeof(char),outLen1 + outLen2,Output_file);
fclose(Input_File); // free all pointers and clean up
fclose(Output_file);
Input_File = NULL;
printf("\n Encryption Process Complete");
}
/*=========================================================================|
Decryption Method below, This Will Take The File And Use The Keys And IV
To Decrypt The Data/File. We Use Long Here Because Int Only Is Good For <= 2GB
Data Size And Will Get ERRORS If File Is Larger Than 2GB Which Is As Common
as gold-diggers */
void decrypt_process()
{
unsigned char key[] = "badidea";
unsigned char vec[] = "again";
FILE *Input_File;
FILE *Output_file;
Input_File =fopen("ult.txt", "rb");
Output_file = fopen("claro.txt", "wb");
fseek(Input_File, 0, SEEK_END);
unsigned long len = (unsigned long)ftell(Input_File); // use long as the file if >2GB will blow past int
printf("length of the file is : %lu", len); //xcode underlines this?
unsigned long outLen1 = 0;
unsigned long outLen2 = 0;
unsigned char *indata = malloc(len);
unsigned char *outdata = malloc(len);
fread(indata,sizeof(char),len, Input_File);//Read Entire File
/*-----------------------------------------------------------------*\
<||| Set Up Decryption As Defined in OPENSSH using their syntax etc.>>>
*-----------------------------------------------------------------*/
//initiating decrypt
EVP_CIPHER_CTX ctx;
EVP_DecryptInit(&ctx,EVP_aes_128_cbc(),key,vec);
EVP_DecryptUpdate(&ctx,outdata,&outLen1,indata,len);
EVP_DecryptFinal(&ctx,outdata + outLen1,&outLen2);
fwrite(outdata,sizeof(char),outLen1 + outLen2,Output_file);
fclose(Input_File); // free all pointers and clean up
fclose(Output_file);
Input_File = NULL;
printf("\n Decryption Process Complete");
}
// main entry point
int main(int argc, const char * argv[])
{
char option[5]; //local buffer to get input
printf("\n **********Welcome To Encryption And Decryption Services!");
printf("****** \n Type e for ecryption or d for decryption (more options later) ");
scanf("%s", option); // should use fgets
if(strcmp(option, "e")== 0){
printf("********* Encryption Process Initiated \n What File Do You Want To Encrypt? Complete Path Needed");
encrypt_process(); // our encryption method
}
else if(strcmp(option,"d")== 0){
printf("********* Decryption Process Initiated");
decrypt_process();
}
return 0;
}
答案 0 :(得分:0)
这里的第一个主要问题是你没有进行任何错误检查。所以当出现问题时你无法知道。
应检查所有I / O例程(fopen
,fread
,fwrite
,fseek
)是否存在错误,并使用perror
打印错误代码。
同样,应检查所有OpenSSL函数是否存在错误。 ERR_error_string
和ERR_get_error
函数会告诉您错误是什么。您需要在程序开头调用ERR_load_crypto_strings
来加载错误字符串。
话虽如此,有两件事可以解决你的问题。
首先,当您从输入文件中读取(在加密和解密例程中)时,您已经在文件的末尾,因此您不会读取任何内容。在阅读之前,您需要将文件指针重置为文件的开头。
fseek(Input_File, 0, SEEK_SET);
fread(indata,sizeof(char),len, Input_File);//Read Entire File
另一个问题是你的钥匙和IV的大小:
unsigned char key[] = "badidea";
unsigned char vec[] = "again";
因为没有为这些数组提供明确的大小,所以它们的初始化程序一样大,在这种情况下分别为8和6个字节(一个用于字符串中的每个字符加一个用于nul终止字节)。 AES-128需要32个字节用于密钥,16个字节用于IV。由于这些数组不够大,因此加密/解密例程会读取这些数组的末尾,从而生成undefined behavior。
为这些数组提供明确的大小:
unsigned char key[32] = "badidea";
unsigned char vec[16] = "again";
因为每个变量都有一个初始化器,所以未显式初始化的任何剩余字节都设置为0。