使用 Openssl EVP 加密时出现分段错误:EVP_EncryptUpdate()

Segmentation Fault While Encrypting with Openssl EVP: EVP_EncryptUpdate()

我想使用 EVP 和 OpenSSL API 将我读入 unsigned char * 的 .exe 文件中的二进制数据加密。我对这个 API 不是很熟悉,恐怕我做错了什么会导致我在编译时遇到分段错误。这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/aes.h>

void handleErrors(void){
  ERR_print_errors_fp(stderr);
  abort();
}

int main(){
  //read in the exe file and convert its bytes to a string
  FILE *inFile;
  inFile = fopen("Quasar.exe","rb");
  if (inFile == NULL){
    perror("Failed to read in file\n");
  }

  printf("File read in complete!\n");

  if(fseek(inFile , 0 , SEEK_END) == -1){
    perror("Offset error\n");
  };
    unsigned long lSize = ftell(inFile);
  if (lSize == -1){
    perror("Size error\n");
  }
    rewind(inFile);

  unsigned char *unencryptedText = (unsigned char*) malloc (sizeof(unsigned char)*lSize);
    fread(unencryptedText,1,lSize,inFile);
    fclose(inFile);

  unsigned char *encryptedText = (unsigned char*) malloc (3 *(sizeof(unsigned char)*lSize));

  //encrypt these bytes with open ssl
  printf("Encrypting...\n");
  int outlen, tmplen;
  unsigned char key[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
  unsigned char iv[] = {1,2,3,4,5,6,7,8};
  EVP_CIPHER_CTX *ctx = NULL;

  EVP_CIPHER_CTX_init(ctx);
  EVP_EncryptInit_ex(ctx, EVP_idea_cbc(), NULL, key, iv);

  if(!EVP_EncryptUpdate(ctx, encryptedText, &outlen, unencryptedText, lSize)){
    return 0;
  }
      
  if(!EVP_EncryptFinal_ex(ctx, encryptedText + outlen, &tmplen)){
    return 0;
  }
  outlen += tmplen;
  EVP_CIPHER_CTX_cleanup(ctx);

  return 0;
}

控制台输出如下:

File read in complete!
Encrypting...
zsh: segmentation fault  ./binary

这是制作脚本:

all: crypter.c 
    gcc -Wall -g -I/usr/local/include/openssl -L/usr/lib -lssl -lcrypto crypter.c -o binary
clean: 
    rm -f crypter
EVP_CIPHER_CTX *ctx = NULL;

EVP_CIPHER_CTX_init(ctx);
EVP_EncryptInit_ex(ctx, EVP_idea_cbc(), NULL, key, iv);

除了 NULL 之外,您绝不会为 ctx 分配任何值。您将 NULL 传递给上述两个函数。

您可能想要的是:

ECP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);

请注意这不会将 NULL 传递给 EVP_CIPHER_CTX_init

您正在将 NULL 对象传递给 EVP_CIPHER_CTX_init 此函数需要现有 EVP_CIPHER_CTX 对象的地址。

您可以通过创建 EVP_CIPHER_CTX 的实例并将其地址传递给需要它的每个函数来解决此问题,或者如果您想尽量减少对代码的更改,您可以将此对象的地址分配给现有 ctx 个指针。

EVP_CIPHER_CTX ctx_obj;
EVP_CIPHER_CTX *ctx = &ctx_obj;

编辑:

根据评论,您似乎使用的是 OpenSSL 1.1 或更高版本。在这种情况下,您想改用 EVP_CIPHER_CTX_new 来实例化一个新的上下文:

EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();