我正在尝试使用 OpenSSL 库在 C++ 中实现 ssl 握手(在上下文中,因为节点通过网关进行通信,所以我不能使用已经实现的 ssl 套接字)
让我们有发送者和接收者
- 发件人将他的证书发送给收件人
- 接收方从发送方 pub_key(包含在证书中)创建 AES 密钥
- 接收方使用发送方 pub_key 加密 AES 密钥,然后使用其私钥加密并将其发送给发送方(连同其证书)
- 发送者使用接收者 pub_key 解密它,然后使用它的私钥
使用 RSA_PKCS1_PADDING 进行公共加密 使用 RSA_NO_PADDING 进行私有加密
现在私人解密部分失败了大约 50% 的时间
error:0407106B:rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02
我不知道如何解决这个问题。
整个代码:
#include <iostream>
#include "openssl/bio.h"
#include "openssl/evp.h"
#include "openssl/aes.h"
#include "openssl/err.h"
#include <openssl/pem.h>
using namespace std;
int main(int argc, char *argv[]) {
int ret = 0;
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
srand(time(NULL));
X509 *sender_x, *receiver_x;
RSA *sender_priv_key, *sender_pub_key, *receiver_priv_key, *receiver_pub_key;
EVP_PKEY *sender_evp_key, *receiver_evp_key;
string sender_ssl_cert = "unit_test/ini/00000000000Wcert.pem";
string sender_ssl_key = "unit_test/ini/00000000000Wkey.pem";
string receiver_ssl_cert = "unit_test/ini/00000000000Rcert.pem";
string receiver_ssl_key = "unit_test/ini/00000000000Rkey.pem";
string ssl_ca="unit_test/ini/sitsroot.pem";
BIO *bio = BIO_new(BIO_s_mem());
unsigned char tmp_buf[2000 + 1];
unsigned char key[32], iv[32];
/** **************************************************************** */
/** ************************ READ FILES **************************** */
FILE *f;
if ((f = fopen(sender_ssl_cert.c_str(), "r")) == NULL) {
cout << "failed to open file " << sender_ssl_cert << endl;
return -1;
}
if ((sender_x = PEM_read_X509(f, NULL, NULL, NULL)) == NULL) {
cout << "failed to read cert file " << sender_ssl_cert << endl;
fclose(f);
return -1;
}
fclose(f);
if ((f = fopen(sender_ssl_key.c_str(), "r")) == NULL) {
cout << "failed to open file " << sender_ssl_key << endl;
return -1;
}
if ((sender_priv_key = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL)) == NULL) {
cout << "failed to read cert file " << sender_ssl_key << endl;
fclose(f);
return -1;
}
fclose(f);
if ((f = fopen(receiver_ssl_cert.c_str(), "r")) == NULL) {
cout << "failed to open file " << receiver_ssl_cert << endl;
return -1;
}
if ((receiver_x = PEM_read_X509(f, NULL, NULL, NULL)) == NULL) {
cout << "failed to read cert file " << receiver_ssl_cert << endl;
fclose(f);
return -1;
}
fclose(f);
if ((f = fopen(receiver_ssl_key.c_str(), "r")) == NULL) {
cout << "failed to open file " << receiver_ssl_key << endl;
return -1;
}
if ((receiver_priv_key = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL)) == NULL) {
cout << "failed to read cert file " << receiver_ssl_key << endl;
fclose(f);
return -1;
}
fclose(f);
/** ************************ READ FILES **************************** */
/** **************************************************************** */
/** **************************************************************** */
/** *********************** GENERATE KEY *************************** */
sender_evp_key = X509_get_pubkey(sender_x);
PEM_write_bio_PUBKEY(bio, sender_evp_key);
ret = BIO_read(bio, tmp_buf, 2000);
ret = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), NULL, tmp_buf, ret, 5, key, iv);
if (ret != 32) {
cout << "Key size is " << ret << " bytes, should be 256 bits" << endl;
return -1;
}
/** *********************** GENERATE KEY *************************** */
/** **************************************************************** */
/** **************************************************************** */
/** *********************** ENCRYPT KEY **************************** */
sender_pub_key = EVP_PKEY_get1_RSA(sender_evp_key);
unsigned char *encrypted_key = (unsigned char*)malloc(RSA_size(sender_pub_key) * sizeof(unsigned char));
if ((ret = RSA_public_encrypt(32, key, encrypted_key, sender_pub_key, RSA_PKCS1_PADDING)) < 0) {
cout << "RSA_public_encrypt failed: " << ERR_error_string(ERR_get_error(), NULL) << endl;
return -1;
}
if ((ret = RSA_private_encrypt(ret, encrypted_key, encrypted_key, receiver_priv_key, RSA_NO_PADDING)) < 0) {
cout << "RSA_private_encrypt failed, " << ERR_error_string(ERR_get_error(), NULL) << endl;
return -1;
}
cout << "RSA_private_encrypt ret: " << ret << endl;
/** *********************** ENCRYPT KEY **************************** */
/** **************************************************************** */
/** **************************************************************** */
/** *********************** DECRYPT KEY **************************** */
if ((receiver_evp_key = X509_get_pubkey(receiver_x)) == NULL) cout << "receiver_evp_key NULL" << endl;
if ((receiver_pub_key = EVP_PKEY_get1_RSA(receiver_evp_key)) == NULL) cout << "receiver_pub_key NULL" << endl;
unsigned char *decrypted_key = (unsigned char*)malloc(RSA_size(receiver_pub_key) * sizeof(unsigned char) + 1);
if ((ret = RSA_public_decrypt(ret, encrypted_key, decrypted_key, receiver_pub_key, RSA_NO_PADDING)) < 0) {
cout << "RSA_public_decrypt failed, " << ERR_error_string(ERR_get_error(), NULL) << endl;
return -1;
}
cout << "RSA_public_decrypt ret: " << ret << endl;
if ((ret = RSA_private_decrypt(ret, decrypted_key, decrypted_key, sender_priv_key, RSA_PKCS1_PADDING)) < 0) {
cout << "RSA_private_decrypt failed, " << ERR_error_string(ERR_get_error(), NULL) << endl;
return -1;
}
cout << "RSA_private_decrypt ret: " << ret << endl;
/** *********************** DECRYPT KEY **************************** */
/** **************************************************************** */
return 0;
}
编辑:在将 strlen 更改为加密函数返回的 ret 值后,这变得没问题 但是让我们转到第 3 步。将此代码添加到末尾(就在 return 0; 语句之前)
/** **************************************************************** */
/** ******************* ANOTHER ENCRYPT KEY ************************ */
unsigned char *another_encrypted_key = (unsigned char*)malloc(RSA_size(receiver_pub_key) * sizeof(unsigned char));
if ((ret = RSA_public_encrypt(32, decrypted_key, another_encrypted_key, receiver_pub_key, RSA_PKCS1_PADDING)) < 0) {
cout << "RSA_public_encrypt failed: " << ERR_error_string(ERR_get_error(), NULL) << endl;
return -1;
}
if ((ret = RSA_private_encrypt(ret, another_encrypted_key, another_encrypted_key, sender_priv_key, RSA_NO_PADDING)) < 0) {
cout << "RSA_private_encrypt failed, " << ERR_error_string(ERR_get_error(), NULL) << endl;
return -1;
}
/** ******************* ANOTHER ENCRYPT KEY ************************ */
/** **************************************************************** */
这导致大约 15% 的机会获得:
error:04066084:rsa routines:RSA_EAY_PRIVATE_ENCRYPT:data too large for modulus
在 RSA_private_encrypt 上,这是我努力解决的主要问题(之前的问题只是我的错误)
编辑2:
RSA_public_encrypt ret: 128
RSA_size(sender_priv_key): 128
RSA_private_encrypt failed, error:04066084:rsa routines:RSA_EAY_PRIVATE_ENCRYPT:data too large for modulus