解密文件仍然是加密的

时间:2017-01-08 05:06:20

标签: c encryption openssl cryptography

我一直在研究这个问题几个小时,首先我想解释一下我要做的事情;使用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;
}

1 个答案:

答案 0 :(得分:0)

这里的第一个主要问题是你没有进行任何错误检查。所以当出现问题时你无法知道。

应检查所有I / O例程(fopenfreadfwritefseek)是否存在错误,并使用perror打印错误代码。

同样,应检查所有OpenSSL函数是否存在错误。 ERR_error_stringERR_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。