尝试使用 libcrypto 对参数字符串进行 RSA 解密时出错
Error when trying to RSA-decrypt a parameter string with libcrypto
我是 libcrypto 库的初学者。我正在尝试将加密的字符串提供给一个函数,对其进行解密,然后 return 对其进行解密。该字符串使用我的 public 密钥进行编码,该密钥大小为 4096 位。
char* decodeStr(const char* str, const size_t sizeStr)
{
puts("Starting");
FILE* file = fopen(PRIVATE_KEY_PATH, "r");
if (file == NULL)
{
perror("Error while trying to access to Presto's private key.\n");
return NULL;
}
RSA *privateKey = RSA_new();
privateKey = PEM_read_RSAPrivateKey(file, &privateKey, NULL, NULL);
if (privateKey == NULL)
{
fprintf(stderr, "Error loading RSA private key.\n");
ERR_print_errors_fp(stderr);
return NULL;
}
char* res = malloc(sizeStr);
if (res == NULL)
{
perror("Memory allocating error ");
return NULL;
}
const int sizeDecoded = RSA_private_decrypt(sizeStr, str, res, privateKey, RSA_PKCS1_PADDING);
if (sizeDecoded == -1)
{
fprintf(stderr, "Error while decoding RSA-encoded wrapping key.\n");
ERR_print_errors_fp(stderr);
return NULL;
}
if ((res = realloc(res, (size_t)sizeDecoded)) == NULL)
{
perror("Memory allocating error ");
return NULL;
}
return res;
}
以下代码输出:
Starting
Error while decoding RSA-encoded wrapping key.
6928:error;04069506C:lib<4>:func<101>:reason<108>:.\crypto\rsa\rsa_eay.c:518:
由于错误是未知的,我在网上找不到任何相关信息,而且我是 libcrypto 的初学者,str
是否需要某种格式?
显然是这个破坏了程序,但我不能确定,我也不知道如何解决这个问题。
const int sizeDecoded = RSA_private_decrypt(sizeStr, str, res, privateKey, RSA_PKCS1_PADDING);
编辑: 我一直在与一个客户合作,该客户为我提供那些编码数据供我解密。我不知道它们是如何处理的。不幸的是,编码后的字符串比私钥本身更敏感,所以我不能分享它。它看起来像 0c79cc00deb89a614db6ebe42be748219089fb5356
,但有 1024 个字符。
问题
你的编码字符串
0c79cc00deb89a614db6ebe42be748219089fb5356 但有数千个字符。
看起来像是编码消息的十六进制表示。我认为您确实需要将消息转换为 原始数据 ,将十六进制转换为字节。
你的字符串由1024 (hex) chars
=> 512 bytes
组成(你需要两个十六进制数字来表示一个字节)=> 4096 bits
,等于密钥长度。
试试这个简单的函数。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
void hex_2_bytes(uint8_t *des, char *source, size_t size);
int main()
{
char *str = "0c79cc00deb89a614db6ebe42be748219089fb5356";
uint8_t *dest = (uint8_t *) malloc(sizeof(uint8_t) * strlen(str) / 2);
hex_2_bytes(dest, str, strlen(str));
for(int i = 0; i < strlen(str) / 2; i++) {
printf(" %02X ", dest[i]);
}
return 0;
}
void hex_2_bytes(uint8_t *des, char *source, size_t size) {
for(int i = 0; i < size - 1; i+=2) {
sscanf(source+i, "%02x", des + (i/2));
}
}
什么是原始数据?您的加密消息是一个字符串,它是一个字符数组。我只看到数字(从 0
到 9
)和从 a
到 f
的字母,这让我猜想你的原始消息(原来是一个二进制字符串, 原始数据) 已使用十六进制数字表示为非常长的数字。您需要将其转换回来。
如果您有一条由 n 字节组成的消息,存储为二进制字符串(原始数据),您将有一个十六进制表示,存储为文本,长度为 2*n 个字节。
示例:
uint8_t raw_data_message[] = {0x3c, 0x2f}; // 2 bytes
char hex_representation_as_string_message[] = {'3', 'c', '2', 'f'}; // 4 bytes
您的消息类似于 hex_representation_as_string_message
,但您需要它们 raw_data_message
。
解决方案
这是一个完整的示例:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#define PRIVATE_KEY_PATH ".ssh/id_rsa"
/*
* Generation of the encrypted message:
* echo "Hello, this is a super secret message" | openssl rsautl -encrypt -pubin -inkey ~/.ssh/id_rsa.pub.pem >message.encrypted
*
* Resulting encrypted message in hex representation:
* 917ab2ebd663bba1dcd0f22aef98b93b039f001e19c997f015d90eaaf35731eb1895c13dfb08250aa28a9dac4f3e1b5fefc53926d3f6422f8055124bb15c24e2b73645dc61f29486deaf278705987738e916a6288531aa923dff15b667dabf4465506e1ee68e6f27a06e3fb4f5040a7775ce69ba10ec337f5bc5ef45969a8fe7c672c9b51243296677385f1b613f4f3edceef620f6ab5dcadec5034c330331bf8e8c3b42554f01c6cf1c0dbc58f23c8f0068e750fc4bb97636b2b3455e7f3932ab9559ff4de5bfc6769bbafefec722441458066ab4a6fdfe99c78bfdd5c1851d411a451925c5ad7ecb0c93618304ae6bc5402193f58af6e6a65208075be35a00
* (converted with: hexdump -ve '1/1 "%.2x"' message.encrypted)
*/
void hex_2_bytes (uint8_t *des, char *source, size_t size);
int decode (uint8_t *dest, const uint8_t *src, const size_t size);
int main (int argc, char **argv) {
// Reading the encrypted message in hex representation
FILE *file = fopen(argv[1], "r");
printf("%s\n", argv[1]);
if (file == NULL) {
perror("Error while trying to access to the encrypted message"
".\n");
return -1;
}
fseek(file, 0, SEEK_END);
long fsize = ftell(file);
fseek(file, 0, SEEK_SET);
char *hex_repr = malloc(fsize);
fread(hex_repr, fsize, 1, file);
fclose(file);
printf("Hexadecimal representation of the encrypted message\n");
for (int i = 0; i < fsize; ++i) {
printf("%c", hex_repr[i]);
}
printf("\nSize: %d\n", fsize);
// Converting to raw data
size_t raw_data_size = fsize / 2;
uint8_t *raw_data = (uint8_t *) malloc(
raw_data_size * sizeof(uint8_t));
hex_2_bytes(raw_data, hex_repr, (size_t) fsize);
printf("Raw encrypted message\n");
for (int i = 0; i < raw_data_size; ++i) {
printf("%02X", raw_data[i]);
}
printf("\nSize: %d\n", raw_data_size);
// Decryption
char *res = malloc(raw_data_size * sizeof(char));
if (res == NULL) {
perror("Memory allocating error ");
return -1;
}
int msg_size = decode(res, raw_data, raw_data_size);
printf("Decrypted message:\n");
for (int j = 0; j < msg_size; ++j) {
printf("%c", res[j]);
}
printf("\nSize: %d\n", msg_size);
return 0;
}
void hex_2_bytes (uint8_t *des, char *source, size_t size) {
for (int i = 0; i < size - 1; i += 2) {
sscanf(source + i, "%02x", des + (i / 2));
}
}
int decode (uint8_t *res, const uint8_t *src, const size_t size) {
puts("Starting");
FILE *file = fopen(PRIVATE_KEY_PATH, "r");
if (file == NULL) {
perror("Error while trying to access to Presto's private key.\n");
return -1;
}
RSA *privateKey = RSA_new();
privateKey = PEM_read_RSAPrivateKey(file, &privateKey, NULL, NULL);
if (privateKey == NULL) {
fprintf(stderr, "Error loading RSA private key.\n");
ERR_print_errors_fp(stderr);
return -1;
}
const int sizeDecoded = RSA_private_decrypt(size, src, res,
privateKey,
RSA_PKCS1_PADDING);
if (sizeDecoded == -1) {
fprintf(stderr,
"Error while decoding RSA-encoded wrapping key.\n");
ERR_print_errors_fp(stderr);
return -1;
}
return sizeDecoded;
}
结果(作为工作证明):
请注意,我使用的是 2048 位 rsa 密钥。
我解决了部分问题。我补充说:
/* Load the human readable error strings for libcrypto */
ERR_load_crypto_strings();
在函数的开头。输出变成:
Starting
Error while decoding RSA-encoded wrapping key.
1124:errir:0406506C:rsa routines: RSA_EAY_PRIVATE_DECRYPT:data greater than mod len:.\crypto\rsa\rsa_eay.c:518:
我猜这意味着密钥的长度对于提供的数据来说太小了。还剩知道是不是数据错了,key错了,如何解决。
另外,为了避免以后犯这样的错误,我补充说:
const size_t sizeRSA = RSA_size(prestoPrivateKey);
if (sizeRSA < sizeWrappingKey)
{
fprintf(stderr, "Size of key : %d\n Size of data : %d\n The size of the key should higher than data length.\n", sizeRSA, sizeWrappingKey);
return NULL;
}
我是 libcrypto 库的初学者。我正在尝试将加密的字符串提供给一个函数,对其进行解密,然后 return 对其进行解密。该字符串使用我的 public 密钥进行编码,该密钥大小为 4096 位。
char* decodeStr(const char* str, const size_t sizeStr)
{
puts("Starting");
FILE* file = fopen(PRIVATE_KEY_PATH, "r");
if (file == NULL)
{
perror("Error while trying to access to Presto's private key.\n");
return NULL;
}
RSA *privateKey = RSA_new();
privateKey = PEM_read_RSAPrivateKey(file, &privateKey, NULL, NULL);
if (privateKey == NULL)
{
fprintf(stderr, "Error loading RSA private key.\n");
ERR_print_errors_fp(stderr);
return NULL;
}
char* res = malloc(sizeStr);
if (res == NULL)
{
perror("Memory allocating error ");
return NULL;
}
const int sizeDecoded = RSA_private_decrypt(sizeStr, str, res, privateKey, RSA_PKCS1_PADDING);
if (sizeDecoded == -1)
{
fprintf(stderr, "Error while decoding RSA-encoded wrapping key.\n");
ERR_print_errors_fp(stderr);
return NULL;
}
if ((res = realloc(res, (size_t)sizeDecoded)) == NULL)
{
perror("Memory allocating error ");
return NULL;
}
return res;
}
以下代码输出:
Starting
Error while decoding RSA-encoded wrapping key.
6928:error;04069506C:lib<4>:func<101>:reason<108>:.\crypto\rsa\rsa_eay.c:518:
由于错误是未知的,我在网上找不到任何相关信息,而且我是 libcrypto 的初学者,str
是否需要某种格式?
显然是这个破坏了程序,但我不能确定,我也不知道如何解决这个问题。
const int sizeDecoded = RSA_private_decrypt(sizeStr, str, res, privateKey, RSA_PKCS1_PADDING);
编辑: 我一直在与一个客户合作,该客户为我提供那些编码数据供我解密。我不知道它们是如何处理的。不幸的是,编码后的字符串比私钥本身更敏感,所以我不能分享它。它看起来像 0c79cc00deb89a614db6ebe42be748219089fb5356
,但有 1024 个字符。
问题
你的编码字符串
0c79cc00deb89a614db6ebe42be748219089fb5356 但有数千个字符。
看起来像是编码消息的十六进制表示。我认为您确实需要将消息转换为 原始数据 ,将十六进制转换为字节。
你的字符串由1024 (hex) chars
=> 512 bytes
组成(你需要两个十六进制数字来表示一个字节)=> 4096 bits
,等于密钥长度。
试试这个简单的函数。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
void hex_2_bytes(uint8_t *des, char *source, size_t size);
int main()
{
char *str = "0c79cc00deb89a614db6ebe42be748219089fb5356";
uint8_t *dest = (uint8_t *) malloc(sizeof(uint8_t) * strlen(str) / 2);
hex_2_bytes(dest, str, strlen(str));
for(int i = 0; i < strlen(str) / 2; i++) {
printf(" %02X ", dest[i]);
}
return 0;
}
void hex_2_bytes(uint8_t *des, char *source, size_t size) {
for(int i = 0; i < size - 1; i+=2) {
sscanf(source+i, "%02x", des + (i/2));
}
}
什么是原始数据?您的加密消息是一个字符串,它是一个字符数组。我只看到数字(从 0
到 9
)和从 a
到 f
的字母,这让我猜想你的原始消息(原来是一个二进制字符串, 原始数据) 已使用十六进制数字表示为非常长的数字。您需要将其转换回来。
如果您有一条由 n 字节组成的消息,存储为二进制字符串(原始数据),您将有一个十六进制表示,存储为文本,长度为 2*n 个字节。
示例:
uint8_t raw_data_message[] = {0x3c, 0x2f}; // 2 bytes
char hex_representation_as_string_message[] = {'3', 'c', '2', 'f'}; // 4 bytes
您的消息类似于 hex_representation_as_string_message
,但您需要它们 raw_data_message
。
解决方案
这是一个完整的示例:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#define PRIVATE_KEY_PATH ".ssh/id_rsa"
/*
* Generation of the encrypted message:
* echo "Hello, this is a super secret message" | openssl rsautl -encrypt -pubin -inkey ~/.ssh/id_rsa.pub.pem >message.encrypted
*
* Resulting encrypted message in hex representation:
* 917ab2ebd663bba1dcd0f22aef98b93b039f001e19c997f015d90eaaf35731eb1895c13dfb08250aa28a9dac4f3e1b5fefc53926d3f6422f8055124bb15c24e2b73645dc61f29486deaf278705987738e916a6288531aa923dff15b667dabf4465506e1ee68e6f27a06e3fb4f5040a7775ce69ba10ec337f5bc5ef45969a8fe7c672c9b51243296677385f1b613f4f3edceef620f6ab5dcadec5034c330331bf8e8c3b42554f01c6cf1c0dbc58f23c8f0068e750fc4bb97636b2b3455e7f3932ab9559ff4de5bfc6769bbafefec722441458066ab4a6fdfe99c78bfdd5c1851d411a451925c5ad7ecb0c93618304ae6bc5402193f58af6e6a65208075be35a00
* (converted with: hexdump -ve '1/1 "%.2x"' message.encrypted)
*/
void hex_2_bytes (uint8_t *des, char *source, size_t size);
int decode (uint8_t *dest, const uint8_t *src, const size_t size);
int main (int argc, char **argv) {
// Reading the encrypted message in hex representation
FILE *file = fopen(argv[1], "r");
printf("%s\n", argv[1]);
if (file == NULL) {
perror("Error while trying to access to the encrypted message"
".\n");
return -1;
}
fseek(file, 0, SEEK_END);
long fsize = ftell(file);
fseek(file, 0, SEEK_SET);
char *hex_repr = malloc(fsize);
fread(hex_repr, fsize, 1, file);
fclose(file);
printf("Hexadecimal representation of the encrypted message\n");
for (int i = 0; i < fsize; ++i) {
printf("%c", hex_repr[i]);
}
printf("\nSize: %d\n", fsize);
// Converting to raw data
size_t raw_data_size = fsize / 2;
uint8_t *raw_data = (uint8_t *) malloc(
raw_data_size * sizeof(uint8_t));
hex_2_bytes(raw_data, hex_repr, (size_t) fsize);
printf("Raw encrypted message\n");
for (int i = 0; i < raw_data_size; ++i) {
printf("%02X", raw_data[i]);
}
printf("\nSize: %d\n", raw_data_size);
// Decryption
char *res = malloc(raw_data_size * sizeof(char));
if (res == NULL) {
perror("Memory allocating error ");
return -1;
}
int msg_size = decode(res, raw_data, raw_data_size);
printf("Decrypted message:\n");
for (int j = 0; j < msg_size; ++j) {
printf("%c", res[j]);
}
printf("\nSize: %d\n", msg_size);
return 0;
}
void hex_2_bytes (uint8_t *des, char *source, size_t size) {
for (int i = 0; i < size - 1; i += 2) {
sscanf(source + i, "%02x", des + (i / 2));
}
}
int decode (uint8_t *res, const uint8_t *src, const size_t size) {
puts("Starting");
FILE *file = fopen(PRIVATE_KEY_PATH, "r");
if (file == NULL) {
perror("Error while trying to access to Presto's private key.\n");
return -1;
}
RSA *privateKey = RSA_new();
privateKey = PEM_read_RSAPrivateKey(file, &privateKey, NULL, NULL);
if (privateKey == NULL) {
fprintf(stderr, "Error loading RSA private key.\n");
ERR_print_errors_fp(stderr);
return -1;
}
const int sizeDecoded = RSA_private_decrypt(size, src, res,
privateKey,
RSA_PKCS1_PADDING);
if (sizeDecoded == -1) {
fprintf(stderr,
"Error while decoding RSA-encoded wrapping key.\n");
ERR_print_errors_fp(stderr);
return -1;
}
return sizeDecoded;
}
结果(作为工作证明):
请注意,我使用的是 2048 位 rsa 密钥。
我解决了部分问题。我补充说:
/* Load the human readable error strings for libcrypto */
ERR_load_crypto_strings();
在函数的开头。输出变成:
Starting
Error while decoding RSA-encoded wrapping key.
1124:errir:0406506C:rsa routines: RSA_EAY_PRIVATE_DECRYPT:data greater than mod len:.\crypto\rsa\rsa_eay.c:518:
我猜这意味着密钥的长度对于提供的数据来说太小了。还剩知道是不是数据错了,key错了,如何解决。
另外,为了避免以后犯这样的错误,我补充说:
const size_t sizeRSA = RSA_size(prestoPrivateKey);
if (sizeRSA < sizeWrappingKey)
{
fprintf(stderr, "Size of key : %d\n Size of data : %d\n The size of the key should higher than data length.\n", sizeRSA, sizeWrappingKey);
return NULL;
}