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_BytesToKey
的 documentation 是这样说的:
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
.
返回的值
首先,我知道 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_BytesToKey
的 documentation 是这样说的:
If
data
isNULL
, thenEVP_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
.