C++ 从RSA密钥对变量中分离公钥和私钥

C++ 从RSA密钥对变量中分离公钥和私钥,c++,openssl,rsa,C++,Openssl,Rsa,正如标题所说,我有一些生成一对RSA密钥的代码。我想将它们分开并分别使用它们来加密/解密,而不是使用变量“keypair”来加密和解密 我正在努力通过网络传输数据,并希望使用简单的RSA加密对其进行加密。因此,我想将公钥发送给另一个用户,这样他就可以使用它来加密一些数据,然后将其发送回我 以下是生成密钥的代码: //Generate key pair RSA *keypair = RSA_generate_key(KEY_LENGTH, PUB_EXP, NULL, NULL); 我现

正如标题所说,我有一些生成一对RSA密钥的代码。我想将它们分开并分别使用它们来加密/解密,而不是使用变量“keypair”来加密和解密

我正在努力通过网络传输数据,并希望使用简单的RSA加密对其进行加密。因此,我想将公钥发送给另一个用户,这样他就可以使用它来加密一些数据,然后将其发送回我

以下是生成密钥的代码:

//Generate key pair
    RSA *keypair = RSA_generate_key(KEY_LENGTH, PUB_EXP, NULL, NULL);
我现在想把公钥和私钥分开,这样我就可以独立地使用它们来加密和解密数据。我该怎么做

我有一些代码,可以获取“密钥对”,并将一些信息提取到一些“BIO”变量中,尽管我不确定这对我有什么帮助:

// To get the C-string PEM form:
BIO *pri = BIO_new(BIO_s_mem());
BIO *pub = BIO_new(BIO_s_mem());

PEM_write_bio_RSAPrivateKey(pri, keypair, NULL, NULL, 0, NULL, NULL);
PEM_write_bio_RSAPublicKey(pub, keypair);

pri_len = BIO_pending(pri);
pub_len = BIO_pending(pub);

pri_key = (char*)malloc(pri_len + 1);
pub_key = (char*)malloc(pub_len + 1);

BIO_read(pri, pri_key, pri_len);
BIO_read(pub, pub_key, pub_len);

pri_key[pri_len] = '\0';
pub_key[pub_len] = '\0';

#ifdef PRINT_KEYS
    printf("\n%s\n%s\n", pri_key, pub_key);
#endif
printf("done.\n");
这段代码很有效,因为我已经在VisualStudio2012中对其进行了测试。 关于如何分离密钥,然后将它们放回“密钥对”中,或者如何单独使用它们来加密/解密某些字符串变量,有什么想法吗

多谢各位

(完整代码)

#包括
#包括
#包括
#包括
#包括
#定义键长度2048
#定义PUB_EXP 3
#定义打印密钥
#定义写入文件
int main(){
size\u t pri\u len;//私钥的长度
size\u t pub\u len;//公钥的长度
char*pri_key;//私钥
char*pub_key;//公钥
char msg[KEY_LENGTH/8];//要加密的消息
char*encrypt=NULL;//加密消息
char*decrypt=NULL;//解密的消息
char*err;//任何错误消息的缓冲区
//生成密钥对
RSA*keypair=RSA\u generate\u key(key\u LENGTH,PUB\u EXP,NULL,NULL);
//要获取C字符串PEM表单,请执行以下操作:
BIO*pri=BIO_new(BIO_s_mem());
BIO*pub=BIO_new(BIO_s_mem());
PEM_write_bio_RSAPrivateKey(pri,keypair,NULL,NULL,0,NULL,NULL);
PEM_write_bio_rs公钥(pub,密钥对);
pri_len=BIO_未决(pri);
pub_len=BIO_pending(pub);
pri_key=(char*)malloc(pri_len+1);
pub_key=(char*)malloc(pub_len+1);
生物阅读(优先级、优先级、优先级);
BIO_read(pub、pub_key、pub_len);
pri_key[pri_len]='\0';
发布键[pub_len]='\0';
#ifdef打印密钥
printf(“\n%s\n%s\n”,pri\u key,pub\u key);
#恩迪夫
printf(“完成。\n”);
//获取要加密的消息
printf(“要加密的消息:”);
fgets(msg,图例长度-1,标准尺寸);
msg[strlen(msg)-1]='\0';
//加密消息
加密=(char*)malloc(RSA_大小(密钥对));
int-encrypt_-len;
err=(char*)malloc(130);
如果((encrypt_len=RSA_public_encrypt(strlen(msg)+1,(unsigned char*)msg,(unsigned char*)encrypt,keypair,RSA_PKCS1_OAEP_PADDING))=-1){
错误加载加密字符串();
ERR\u error\u字符串(ERR\u get\u error(),ERR);
fprintf(stderr,“加密消息时出错:%s\n”,err);
转到免费的东西;
}
//解密
解密=(字符*)malloc(加密);
if(RSA_private_decrypt(encrypt_len,(unsigned char*)encrypt,(unsigned char*)decrypt,keypair,RSA_PKCS1_OAEP_PADDING)=-1){
错误加载加密字符串();
ERR\u error\u字符串(ERR\u get\u error(),ERR);
fprintf(stderr,“解密消息时出错:%s\n”,err);
转到免费的东西;
}
printf(“解密的消息:%s\n”,解密);
getchar();
//printf(“%s”,发布键);
免费的东西:
无RSA_(密钥对);
BIO_free_all(酒吧);
BIO_free_all(pri);
免费(优先键);
免费(公开密钥);
免费(加密);
免费(解密);
自由(错误);
}

在此处找到此代码:

您可以使用
d2i\u RSAPublicKey
i2d\u RSAPublicKey
从RSA密钥对中提取RSA公钥。使用
i2d\u RSAPublicKey
将密钥对编码为PKCS\1 RSAPublicKey结构,将其存储在bytestring中,然后使用
d2i\u RSAPublicKey
将其解码回RSA密钥结构。

我在其他堆栈溢出帖子中找到了解决问题的方法,即

我想要的答案是@SquareRootOfTwentyThree是他的最后一行代码

将公钥提取到名为pub的BIO变量后:

PEM_write_bio_RSAPublicKey(pub, keypair);
我可以通过网络发送变量pub,在它到达另一端后,创建一个RSA变量并将pub放入其中:

解决方案:

RSA *keypair2 = NULL; 
PEM_read_bio_RSAPublicKey( pub, &keypair2, NULL, NULL);
完成此操作后,我可以像往常一样使用keypair2成功加密消息:

加密:

encrypt = (char*)malloc(RSA_size(keypair));
int encrypt_len;
err = (char*)malloc(130);
if((encrypt_len = RSA_public_encrypt(strlen(msg)+1, (unsigned char*)msg,
        (unsigned char*)encrypt, keypair2 ,RSA_PKCS1_OAEP_PADDING)) == -1) {
    ERR_load_crypto_strings();
    ERR_error_string(ERR_get_error(), err);
    fprintf(stderr, "Error encrypting message: %s\n", err);
}
然后,我可以将此加密变量发送回第一台机器,并像往常一样使用原始的
密钥对
对其进行解密,而无需通过网络发送

解密:

decrypt = (char*)malloc(encrypt_len);
if(RSA_private_decrypt(encrypt_len, (unsigned char*)encrypt, (unsigned char*)decrypt,
        keypair, RSA_PKCS1_OAEP_PADDING) == -1) {
    ERR_load_crypto_strings();
    ERR_error_string(ERR_get_error(), err);
    fprintf(stderr, "Error decrypting message: %s\n", err);
}

谢谢大家对本帖的贡献

查看代码时,您似乎成功地将
public
private
键分离为字符串pub_键和pri_键,但随后使用
printf
将它们输出,并将它们粘贴在一起。要仅打印
public
键,请将printf语句更改为:

printf("\n%s\n", pub_key); 
我想将[密钥对]分开,分别使用它们进行加密/解密

。。。关于如何分离密钥,然后将它们放回“密钥对”中,或者如何单独使用它们来加密/解密某些字符串变量,有什么想法吗

您可以使用
RSAPublicKey_dup
RSAPrivateKey_dup
,而无需通过ASN.1/DER或PEM编码对其进行往返。在这里,往返包括使用诸如
PEM\u write\u bio\r公钥
PEM\u read\u bio\r公钥
之类的功能

下面是使用它们的示例程序。它用C++编写(感谢添加了标签)。 虽然可以将它们分开,但它们都使用
RSA
结构。公钥的某些成员设置为
NULL
,如私有指数


您还可以使用
RSA\u print
RSA\u print\u fp
和friends打印密钥。请参阅下面的或其用法



雷尔
printf("\n%s\n", pub_key); 
// g++ -Wall -Wextra -std=c++11 -stdlib=libc++ -I/usr/local/ssl/macosx-x64/include \
//     t.cpp -o t.exe /usr/local/ssl/macosx-x64/lib/libcrypto.a

#include <memory>
using std::unique_ptr;

#include <openssl/bn.h>
#include <openssl/rsa.h>

#include <cassert>
#define ASSERT assert

using BN_ptr = std::unique_ptr<BIGNUM, decltype(&::BN_free)>;
using RSA_ptr = std::unique_ptr<RSA, decltype(&::RSA_free)>;

int main(int argc, char* argv[])
{
    int rc;

    RSA_ptr rsa(RSA_new(), ::RSA_free);
    BN_ptr bn(BN_new(), ::BN_free);

    rc = BN_set_word(bn.get(), RSA_F4);
    ASSERT(rc == 1);

    rc = RSA_generate_key_ex(rsa.get(), 2048, bn.get(), NULL);
    ASSERT(rc == 1);

    RSA_ptr rsa_pub(RSAPublicKey_dup(rsa.get()), ::RSA_free);
    RSA_ptr rsa_priv(RSAPrivateKey_dup(rsa.get()), ::RSA_free);

    fprintf(stdout, "\n");
    RSA_print_fp(stdout, rsa_pub.get(), 0);

    fprintf(stdout, "\n");
    RSA_print_fp(stdout, rsa_priv.get(), 0);

    return 0;
}