C++中OpenSSL RC4加解密不一致

Inconsistent encryption and decryption with OpenSSL RC4 in C++

首先,我知道 RC4 不是最安全的加密方法,而且它已经过时了,这只是一个学校项目。只是想我把它放在那里,因为人们可能会问。

我正在使用 OpenSSL 的 RC4 来用 C++ 制作一个简单的加密和解密程序。我注意到加密和解密不一致。这是我目前所拥有的:

#include <fcntl.h>
#include <openssl/evp.h>
#include <openssl/rc4.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
int inputFile = open(argv[1], O_RDONLY);
if (inputFile < 0) {
    printf("Error opening file\n");
    return 1;
}

unsigned char *keygen = reinterpret_cast<unsigned char*>(argv[2]);
RC4_KEY key;

size_t size = lseek(inputFile, 0, SEEK_END);
lseek(inputFile, 0, SEEK_SET);

unsigned char *fileIn = (unsigned char*) calloc(size, 1);

if (pread(inputFile, fileIn, size, 0) == -1) {
    perror("Error opening read\n");
    return 1;
}

unsigned char *fileOut = (unsigned char*) calloc(size, 1);

unsigned char *actualKey;
EVP_BytesToKey(EVP_rc4(), EVP_sha256(), NULL, keygen, sizeof(keygen), 1, actualKey, NULL);

RC4_set_key(&key, sizeof(actualKey), actualKey);
RC4(&key, size, fileIn, fileOut);

int outputFile = open(argv[3], O_WRONLY | O_TRUNC | O_CREAT, 0644);
if (outputFile < 0) {
    perror("Error opening output file");
    return 1;
}
if (pwrite(outputFile, fileOut, size, 0) == -1) {
    perror("error writing file");
    return 1;
}

close(inputFile);
close(outputFile);

free(fileIn);
free(fileOut);

return 0;
}

在 Ubuntu 中 运行 的语法是:

./myRC4 test.txt pass123 testEnc.txt

大多数情况下这工作正常,加密和解密文件。但是偶尔我会遇到分段错误。如果我这样做,我会再次 运行 完全相同的命令,它加密或解密都很好,至少对于 .txt 文件是这样。

当我在 .jpg 文件或任何更大的文件上进行测试时,问题似乎更常见且不一致。我注意到有时图像似乎已被解密(没有分段错误)但实际上并没有,我通过在原始文件和解密文件之间进行比较来测试。

关于为什么我会遇到这些不一致的问题,有什么想法吗?这与我如何为 fileOut 和 fileIn 分配内存有关吗?

提前致谢

在将

actualKey 传递给 EVP_BytesToKey 之前,

actualKey 需要指向适当大小的缓冲区。事实上,您正在传递一个未初始化的指针,这可以解释您不一致的结果。

EVP_BytesToKeydocumentation 是这样说的:

If data is NULL, then EVP_BytesToKey() returns the number of bytes needed to store the derived key.

所以可以在data参数设置为NULL的情况下调用一次EVP_BytesToKey来确定actualKey的长度,然后分配一个合适的缓冲区再调用actualKey 指向那个缓冲区。

正如其他人指出的那样,将 sizeof(keygen) 传递给 EVP_BytesToKey 也是不正确的。你的意思可能是 strlen (argv [2]).

同样,将 sizeof(actualKey) 传递给 RC4_set_key 也是一个错误。相反,您应该传递 EVP_BytesToKey.

返回的值