无法从文件加载 RSA public 密钥
Trouble loading RSA public key from file
我最近一直在我的 C++ 项目中使用 openssl 库,但我遇到了一个我自己无法解决的问题。
我实际上是在尝试加载存储在文件中的 RSA public 密钥并加密 64 字节。
当我的代码使用使用函数 RSA_generate_key 生成的 public 键时,它可以工作,但是当我使用我自己的 public 键时,由于某种原因它将不再工作。
我怀疑密钥格式来自 pkcs1 pkcs8,尝试了 PEM_read_RSAPublicKey 和 PEM_read_RSA_PUBKEY,但由于某种原因仍然无法正常工作...
这是我的 public 密钥:
-----BEGIN RSA PUBLIC KEY-----
MEYCQQDE91cW7INdIyVon5H/he2b/DIR25wWT0GFLiZOVp0oAgCAVKDvRZ5+Pqu4
f65XbnNUNNHRJLMLEb1t4JgUhgFVAgER
-----END RSA PUBLIC KEY-----
来自 Openssl 库的 RSA_generate_key 函数的密钥,它正在工作:
-----BEGIN RSA PUBLIC KEY-----
MEYCQQDsg/4Qm153/Pr8JRruC0SnVvTrWg/lIPheezIpkwVeWjNz9lMDXNUjdK8v
QgfNUCRJYbnxYIeruAdwTzS/bDXbAgER
-----END RSA PUBLIC KEY-----
这是我的代码:
RSA.h :
#include <iostream>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <string>
#ifndef RSA_ALGORITHM_H
#define RSA_ALGORITHM_H
#define KEY_LENGTH 512
#define PUBLIC_EXPONENT 17
#define PUBLIC_KEY_PEM 1
#define PRIVATE_KEY_PEM 0
#define LOG(x) \
std::cout << x << std::endl; \
/*
* @brief create_RSA function creates public key and private key file
*
*/
RSA* create_RSA(RSA* keypair, int pem_type, char* file_name);
/*
* @brief public_ecrypt function encrypts data.
* @return If It is fail, return -1
*/
int public_encrypt(int flen, unsigned char* from, unsigned char* to, RSA* key, int padding);
/*
* @brief private_decrypt function decrypt data.
* @return If It is fail, return -1
*/
int private_decrypt(int flen, unsigned char* from, unsigned char* to, RSA* key, int padding);
/*
* @brief create_ecrypted_file function creates .bin file. It contains encrypted data.
*/
void create_encrypted_file(char* encrypted, RSA* key_pair);
#endif //RSA_ALGORITHM_H
RSA.cpp :
#include "RSA.h"
#include <iostream>
#include <string.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <sstream>
#include <iomanip>
int public_encrypt(int flen, unsigned char* from, unsigned char* to, RSA* key, int padding) {
int result = RSA_public_encrypt(flen, from, to, key, padding);
return result;
}
void create_encrypted_file(char* encrypted, RSA* key_pair) {
FILE* encrypted_file = fopen("encrypted_file.bin", "w");
fwrite(encrypted, sizeof(*encrypted), RSA_size(key_pair), encrypted_file);
fclose(encrypted_file);
}
RSA* createRSA(int pem_type, char* file_name) {
RSA* rsa = NULL;
FILE* fp = NULL;
if (pem_type == PUBLIC_KEY_PEM) {
fp = fopen(file_name, "rb");
PEM_read_RSAPublicKey(fp, &rsa, NULL, NULL);
fclose(fp);
}
else if (pem_type == PRIVATE_KEY_PEM) {
fp = fopen(file_name, "rb");
PEM_read_RSAPrivateKey(fp, &rsa, NULL, NULL);
fclose(fp);
}
return rsa;
}
int main() {
LOG("RSA has been started.");
char public_key_pem[11] = "public_key";
RSA* public_key = createRSA(PUBLIC_KEY_PEM, public_key_pem);
LOG("Public key pem file has been created.");;
char message[KEY_LENGTH] = "\xc8\xcd\x21\x74\xb9\x84\x33\xb9\x30\x94\xb3\x60\x26\xde\x12\x5a\x7f\x5e\xd8\x5e\xc2\x7e\xe6\xbb\x9e\x99\x6c\xb3\xb9\x38\xe9\xc6\x23\x8c\xc6\x5d\x36\x15\xfb\x63\x5f\x6f\x08\x0f\x6d\xda\x06\x31\x59\x28\xbc\xae\x4c\xcf\x80\x2f\x96\x80\x54\x7d\xb5\x7b\x82\x83";
char* encrypt = NULL;
LOG(KEY_LENGTH);
LOG(PUBLIC_EXPONENT);
encrypt = (char*)malloc(RSA_size(public_key));
int encrypt_length = public_encrypt(RSA_size(public_key), (unsigned char*)message, (unsigned char*)encrypt, public_key, RSA_NO_PADDING);
if (encrypt_length == -1) {
LOG("An error occurred in public_encrypt() method");
}
LOG("Data has been encrypted.");
create_encrypted_file(encrypt, public_key);
LOG("Encrypted file has been created.");
free(public_key);
free(encrypt);
LOG("RSA has been finished.");
return 0;
}
我看过很多帖子,但没有找到任何解决方法,尽管这个与我的问题非常相似
。
错误实际上与数学有关。密钥和代码都没有引起问题。如果您更改要加密的密钥或数据,出于某种原因它会正常工作。所以我猜想在 RSA 计算期间发生了一些事情,但没有足够聪明来弄清楚是什么。
两个密钥都是 public RSA 密钥,大小为 512 位,指数为 17,以 PKCS1-PEM 格式指定。
消息m
、无效密钥的模数n_fail
和有效密钥的模数n_ok
为:
m = 0xc8cd2174b98433b93094b36026de125a7f5ed85ec27ee6bb9e996cb3b938e9c6238cc65d3615fb635f6f080f6dda06315928bcae4ccf802f9680547db57b8283
n_fail = 0xc4f75716ec835d2325689f91ff85ed9bfc3211db9c164f41852e264e569d2802008054a0ef459e7e3eabb87fae576e735434d1d124b30b11bd6de09814860155
n_ok = 0xec83fe109b5e77fcfafc251aee0b44a756f4eb5a0fe520f85e7b322993055e5a3373f653035cd52374af2f4207cd50244961b9f16087abb807704f34bf6c35db
比较表明
n_fail < m < n_ok
对于 RSA,条件 m < n
必须适用。 n_fail
违反了此条件,这就是问题的原因。这也意味着相应的密钥本身不是无效的。它可以用来加密不违反m < n
的消息。但是,对于发布的消息,它的模数太小了。
关于安全性:现在应该使用 2048 bits and one of the paddings specified in RFC8017 大小的密钥(RSAES-PKCS1-v1_5
或 RSAES-OAEP
)。
我最近一直在我的 C++ 项目中使用 openssl 库,但我遇到了一个我自己无法解决的问题。
我实际上是在尝试加载存储在文件中的 RSA public 密钥并加密 64 字节。 当我的代码使用使用函数 RSA_generate_key 生成的 public 键时,它可以工作,但是当我使用我自己的 public 键时,由于某种原因它将不再工作。
我怀疑密钥格式来自 pkcs1 pkcs8,尝试了 PEM_read_RSAPublicKey 和 PEM_read_RSA_PUBKEY,但由于某种原因仍然无法正常工作...
这是我的 public 密钥:
-----BEGIN RSA PUBLIC KEY-----
MEYCQQDE91cW7INdIyVon5H/he2b/DIR25wWT0GFLiZOVp0oAgCAVKDvRZ5+Pqu4
f65XbnNUNNHRJLMLEb1t4JgUhgFVAgER
-----END RSA PUBLIC KEY-----
来自 Openssl 库的 RSA_generate_key 函数的密钥,它正在工作:
-----BEGIN RSA PUBLIC KEY-----
MEYCQQDsg/4Qm153/Pr8JRruC0SnVvTrWg/lIPheezIpkwVeWjNz9lMDXNUjdK8v
QgfNUCRJYbnxYIeruAdwTzS/bDXbAgER
-----END RSA PUBLIC KEY-----
这是我的代码:
RSA.h :
#include <iostream>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <string>
#ifndef RSA_ALGORITHM_H
#define RSA_ALGORITHM_H
#define KEY_LENGTH 512
#define PUBLIC_EXPONENT 17
#define PUBLIC_KEY_PEM 1
#define PRIVATE_KEY_PEM 0
#define LOG(x) \
std::cout << x << std::endl; \
/*
* @brief create_RSA function creates public key and private key file
*
*/
RSA* create_RSA(RSA* keypair, int pem_type, char* file_name);
/*
* @brief public_ecrypt function encrypts data.
* @return If It is fail, return -1
*/
int public_encrypt(int flen, unsigned char* from, unsigned char* to, RSA* key, int padding);
/*
* @brief private_decrypt function decrypt data.
* @return If It is fail, return -1
*/
int private_decrypt(int flen, unsigned char* from, unsigned char* to, RSA* key, int padding);
/*
* @brief create_ecrypted_file function creates .bin file. It contains encrypted data.
*/
void create_encrypted_file(char* encrypted, RSA* key_pair);
#endif //RSA_ALGORITHM_H
RSA.cpp :
#include "RSA.h"
#include <iostream>
#include <string.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <sstream>
#include <iomanip>
int public_encrypt(int flen, unsigned char* from, unsigned char* to, RSA* key, int padding) {
int result = RSA_public_encrypt(flen, from, to, key, padding);
return result;
}
void create_encrypted_file(char* encrypted, RSA* key_pair) {
FILE* encrypted_file = fopen("encrypted_file.bin", "w");
fwrite(encrypted, sizeof(*encrypted), RSA_size(key_pair), encrypted_file);
fclose(encrypted_file);
}
RSA* createRSA(int pem_type, char* file_name) {
RSA* rsa = NULL;
FILE* fp = NULL;
if (pem_type == PUBLIC_KEY_PEM) {
fp = fopen(file_name, "rb");
PEM_read_RSAPublicKey(fp, &rsa, NULL, NULL);
fclose(fp);
}
else if (pem_type == PRIVATE_KEY_PEM) {
fp = fopen(file_name, "rb");
PEM_read_RSAPrivateKey(fp, &rsa, NULL, NULL);
fclose(fp);
}
return rsa;
}
int main() {
LOG("RSA has been started.");
char public_key_pem[11] = "public_key";
RSA* public_key = createRSA(PUBLIC_KEY_PEM, public_key_pem);
LOG("Public key pem file has been created.");;
char message[KEY_LENGTH] = "\xc8\xcd\x21\x74\xb9\x84\x33\xb9\x30\x94\xb3\x60\x26\xde\x12\x5a\x7f\x5e\xd8\x5e\xc2\x7e\xe6\xbb\x9e\x99\x6c\xb3\xb9\x38\xe9\xc6\x23\x8c\xc6\x5d\x36\x15\xfb\x63\x5f\x6f\x08\x0f\x6d\xda\x06\x31\x59\x28\xbc\xae\x4c\xcf\x80\x2f\x96\x80\x54\x7d\xb5\x7b\x82\x83";
char* encrypt = NULL;
LOG(KEY_LENGTH);
LOG(PUBLIC_EXPONENT);
encrypt = (char*)malloc(RSA_size(public_key));
int encrypt_length = public_encrypt(RSA_size(public_key), (unsigned char*)message, (unsigned char*)encrypt, public_key, RSA_NO_PADDING);
if (encrypt_length == -1) {
LOG("An error occurred in public_encrypt() method");
}
LOG("Data has been encrypted.");
create_encrypted_file(encrypt, public_key);
LOG("Encrypted file has been created.");
free(public_key);
free(encrypt);
LOG("RSA has been finished.");
return 0;
}
我看过很多帖子,但没有找到任何解决方法,尽管这个与我的问题非常相似
。
错误实际上与数学有关。密钥和代码都没有引起问题。如果您更改要加密的密钥或数据,出于某种原因它会正常工作。所以我猜想在 RSA 计算期间发生了一些事情,但没有足够聪明来弄清楚是什么。
两个密钥都是 public RSA 密钥,大小为 512 位,指数为 17,以 PKCS1-PEM 格式指定。
消息m
、无效密钥的模数n_fail
和有效密钥的模数n_ok
为:
m = 0xc8cd2174b98433b93094b36026de125a7f5ed85ec27ee6bb9e996cb3b938e9c6238cc65d3615fb635f6f080f6dda06315928bcae4ccf802f9680547db57b8283
n_fail = 0xc4f75716ec835d2325689f91ff85ed9bfc3211db9c164f41852e264e569d2802008054a0ef459e7e3eabb87fae576e735434d1d124b30b11bd6de09814860155
n_ok = 0xec83fe109b5e77fcfafc251aee0b44a756f4eb5a0fe520f85e7b322993055e5a3373f653035cd52374af2f4207cd50244961b9f16087abb807704f34bf6c35db
比较表明
n_fail < m < n_ok
对于 RSA,条件 m < n
必须适用。 n_fail
违反了此条件,这就是问题的原因。这也意味着相应的密钥本身不是无效的。它可以用来加密不违反m < n
的消息。但是,对于发布的消息,它的模数太小了。
关于安全性:现在应该使用 2048 bits and one of the paddings specified in RFC8017 大小的密钥(RSAES-PKCS1-v1_5
或 RSAES-OAEP
)。