将公钥和私钥与RSA密钥对变量分开

时间:2014-03-20 00:51:52

标签: c++ openssl rsa

正如标题所说,我有一些代码可以生成一对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");

此代码有效,因为我已在visual studio 2012中测试过它。 关于如何分离键的任何想法,然后可能将它们重新组合在一起"密钥对"或者可能如何单独使用它们来加密/解密一些字符串变量?

谢谢

(完整代码)

#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <stdio.h>
#include <string.h>

#define KEY_LENGTH  2048
#define PUB_EXP     3
#define PRINT_KEYS
#define WRITE_TO_FILE

int main() {
    size_t pri_len;            // Length of private key
    size_t pub_len;            // Length of public key
    char   *pri_key;           // Private key
    char   *pub_key;           // Public key
    char   msg[KEY_LENGTH/8];  // Message to encrypt
    char   *encrypt = NULL;    // Encrypted message
    char   *decrypt = NULL;    // Decrypted message
    char   *err;               // Buffer for any error messages
//Generate key pair
    RSA *keypair = RSA_generate_key(KEY_LENGTH, PUB_EXP, NULL, NULL);

// 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");

// Get the message to encrypt
    printf("Message to encrypt: ");
    fgets(msg, KEY_LENGTH-1, stdin);
    msg[strlen(msg)-1] = '\0';

// Encrypt the message
    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, keypair, RSA_PKCS1_OAEP_PADDING)) == -1) {
        ERR_load_crypto_strings();
        ERR_error_string(ERR_get_error(), err);
        fprintf(stderr, "Error encrypting message: %s\n", err);
        goto free_stuff;
    }

// Decrypt it
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);
    goto free_stuff;
}
printf("Decrypted message: %s\n", decrypt);

getchar();

//printf("%s", pub_key);

free_stuff:
RSA_free(keypair);
BIO_free_all(pub);
BIO_free_all(pri);
free(pri_key);
free(pub_key);
free(encrypt);
free(decrypt);
free(err);
}

在此处找到此代码:https://shanetully.com/2012/04/simple-public-key-encryption-with-rsa-and-openssl/

4 个答案:

答案 0 :(得分:4)

  

我想将[密钥对]分开并单独使用它们来加密/解密

     

...关于如何分离密钥的任何想法,然后可能将它们放回到“密钥对”中,或者可能如何单独使用它们来加密/解密某些字符串变量?

您可以使用RSAPublicKey_dupRSAPrivateKey_dup,而无需通过ASN.1 / DER或PEM对它们进行往返。此处,往返行程包括使用PEM_write_bio_RSAPublicKeyPEM_read_bio_RSAPublicKey等函数。

以下是使用它们的示例程序。它用C ++编写(感谢您添加该标记)。

虽然您可以将它们分开,但它们都使用RSA结构。公钥的一些成员设置为NULL,就像私有指数一样。

您还可以使用RSA_printRSA_print_fp和朋友打印密钥。请参阅下面的RSA_print (3)或其用法。

// 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;
}

这是输出:

$ ./t.exe 

Public-Key: (2048 bit)
Modulus:
    00:aa:5a:cc:30:52:f1:e9:49:3d:a6:25:00:33:29:
    a6:fa:f7:53:e0:3c:73:4c:91:41:66:20:ec:62:1f:
    27:2a:2a:6c:0f:90:f8:d9:7e:d5:ec:72:7b:38:8c:
    ca:12:60:f8:d1:fb:f2:65:7c:b1:3a:b6:4e:26:ba:
    5b:86:cc:30:f2:fc:be:c3:a2:00:b9:ea:81:fa:1c:
    22:4e:f7:be:a1:1a:66:90:13:b6:12:66:26:23:6d:
    22:15:7d:3b:a4:99:44:38:fa:1c:70:63:4e:50:6f:
    66:38:6c:f6:1a:13:e1:c7:dc:a6:a1:eb:6f:f9:c9:
    59:c8:30:dc:c2:1b:dc:6c:9d:ea:0c:3d:52:5a:00:
    ea:c9:c9:85:51:21:9f:ec:95:b3:dc:c2:50:21:29:
    c2:64:6c:1e:34:36:d8:61:59:ab:3c:a2:cc:e8:ef:
    57:c3:7f:49:86:be:e3:42:88:1b:39:10:b8:2f:fa:
    81:ef:a0:94:99:0c:71:ae:1e:82:7f:e3:6e:00:6e:
    02:13:66:bb:a9:31:58:ec:90:39:9c:bc:9c:8c:90:
    e9:20:f7:20:8e:d6:a3:a3:df:a2:4a:0f:0f:39:b5:
    57:b9:ef:6a:27:e0:1a:ed:f6:ce:0d:87:cd:43:03:
    bf:67:ef:ff:fd:da:98:cc:22:ab:5e:8d:7b:43:d3:
    90:4d
Exponent: 65537 (0x10001)

Private-Key: (2048 bit)
modulus:
    00:aa:5a:cc:30:52:f1:e9:49:3d:a6:25:00:33:29:
    a6:fa:f7:53:e0:3c:73:4c:91:41:66:20:ec:62:1f:
    27:2a:2a:6c:0f:90:f8:d9:7e:d5:ec:72:7b:38:8c:
    ca:12:60:f8:d1:fb:f2:65:7c:b1:3a:b6:4e:26:ba:
    5b:86:cc:30:f2:fc:be:c3:a2:00:b9:ea:81:fa:1c:
    22:4e:f7:be:a1:1a:66:90:13:b6:12:66:26:23:6d:
    22:15:7d:3b:a4:99:44:38:fa:1c:70:63:4e:50:6f:
    66:38:6c:f6:1a:13:e1:c7:dc:a6:a1:eb:6f:f9:c9:
    59:c8:30:dc:c2:1b:dc:6c:9d:ea:0c:3d:52:5a:00:
    ea:c9:c9:85:51:21:9f:ec:95:b3:dc:c2:50:21:29:
    c2:64:6c:1e:34:36:d8:61:59:ab:3c:a2:cc:e8:ef:
    57:c3:7f:49:86:be:e3:42:88:1b:39:10:b8:2f:fa:
    81:ef:a0:94:99:0c:71:ae:1e:82:7f:e3:6e:00:6e:
    02:13:66:bb:a9:31:58:ec:90:39:9c:bc:9c:8c:90:
    e9:20:f7:20:8e:d6:a3:a3:df:a2:4a:0f:0f:39:b5:
    57:b9:ef:6a:27:e0:1a:ed:f6:ce:0d:87:cd:43:03:
    bf:67:ef:ff:fd:da:98:cc:22:ab:5e:8d:7b:43:d3:
    90:4d
publicExponent: 65537 (0x10001)
privateExponent:
    66:a4:ce:e3:4f:16:f3:b9:6d:ab:ee:1f:70:b4:68:
    28:4f:5d:fa:7e:71:fa:70:8b:37:3e:1f:30:00:15:
    59:12:b6:89:aa:90:46:7c:65:e9:52:11:6c:c1:68:
    00:2a:ed:c1:98:4d:35:59:2c:70:73:e8:22:ed:a6:
    b8:51:d0:2c:98:9d:58:c3:04:2d:01:5f:cf:93:a4:
    18:70:ae:2b:e3:fc:68:53:78:21:1d:eb:5c:ed:24:
    dc:4d:d8:e2:14:77:46:dd:6c:c5:4b:10:a4:e6:7a:
    71:05:36:44:00:36:ca:75:e8:f1:27:2b:11:16:81:
    42:5e:2e:a5:c6:a3:c9:cd:60:59:ce:72:71:76:c8:
    ca:ba:f0:45:c3:86:07:7b:22:20:c4:74:c6:a8:ab:
    7c:2c:f8:de:ea:25:95:81:79:33:54:67:7b:61:91:
    80:a8:1f:4c:38:32:d4:4d:2e:a8:7d:9b:d4:1a:3e:
    6b:ca:50:3c:a0:61:0e:00:ad:f4:5c:0f:26:1a:59:
    00:3c:bd:ee:c3:e8:d0:b8:9b:0e:44:89:49:d1:24:
    a4:39:15:dc:0e:c5:d5:41:a2:4a:f4:e5:e3:23:c7:
    98:8a:87:f7:18:a6:e2:7b:27:83:f6:fb:62:42:46:
    ae:de:ba:48:ad:07:39:40:da:65:17:d1:d2:ed:df:
    01
prime1:
    00:dd:dc:70:b5:70:ea:10:20:28:40:a0:c3:b8:70:
    6d:3d:84:c0:57:2d:69:fc:e9:d4:55:ed:4f:ac:3d:
    c2:e9:19:49:f0:ab:c6:bd:99:9e:0f:e5:a4:61:d4:
    b3:c5:c2:b1:e4:3a:10:ff:e6:cd:ce:6e:2d:93:bc:
    87:12:92:87:7c:d3:dd:bc:32:54:9e:fa:67:b1:9d:
    e2:27:53:e6:03:a7:22:17:45:63:0d:42:f3:96:5d:
    a3:e0:9c:93:f0:42:8b:bb:95:34:e6:f6:0b:f7:b6:
    c5:59:a0:b5:2a:71:59:c0:f2:7e:bf:95:2d:dd:6d:
    94:23:2a:95:4a:4f:f1:d0:93
prime2:
    00:c4:91:6a:33:1b:db:24:eb:fd:d3:69:e9:3c:e2:
    a2:2d:23:7a:92:65:a8:a0:50:1d:0a:2b:b4:f0:64:
    e4:40:57:f3:dc:f7:65:18:7d:51:75:73:b9:d6:67:
    9b:0e:94:5f:37:02:6c:7f:eb:b9:13:4b:bf:8e:65:
    22:0b:2c:c6:8d:2a:a2:88:ec:21:e3:f9:0b:78:b4:
    1d:d0:44:e6:36:0d:ec:3c:8f:0a:c7:3b:0d:91:65:
    b7:de:a3:c9:a3:2a:8c:7f:1f:a1:d2:6e:9b:ee:23:
    78:c1:30:76:87:af:a8:11:a4:15:b4:54:16:d8:94:
    71:5c:64:30:43:58:b5:07:9f
exponent1:
    2f:91:e8:88:be:e1:30:fb:f4:25:87:52:ef:e5:0b:
    47:39:83:94:2d:a4:a0:19:f2:f1:49:a4:df:a5:8e:
    79:34:76:ea:27:aa:c1:54:82:d3:9d:c5:95:44:6a:
    17:69:1b:83:77:ff:d5:1e:c3:da:13:3d:aa:83:ad:
    e2:89:90:8b:6f:52:07:dc:32:d0:b3:98:30:39:4e:
    18:68:a0:d4:ff:ad:0b:98:51:18:b2:d6:4f:d3:5c:
    23:f8:ee:af:81:55:3c:af:4d:5c:88:3d:20:ac:0b:
    bc:9f:fc:b8:50:fd:91:a5:6d:0f:df:08:aa:85:a8:
    51:b1:fb:b8:a7:53:8e:09
exponent2:
    7d:46:0b:7f:ad:06:19:de:c8:b2:7e:f2:25:5a:6e:
    6f:04:08:6e:da:99:00:2a:6e:87:77:d9:65:c7:76:
    ec:46:e1:64:f6:ca:18:34:6d:c0:c3:d3:31:00:70:
    82:77:2e:c3:59:29:1a:d1:78:ef:02:3c:7f:9c:96:
    78:b6:bd:87:64:1f:97:d1:9d:bb:b3:91:8b:08:87:
    63:9f:35:74:47:a5:41:e7:0b:c0:73:33:2f:71:bb:
    20:0a:14:4c:87:a6:68:b2:19:28:8a:53:98:0e:45:
    3c:22:0d:b8:65:cb:60:0a:c9:c6:56:3d:05:24:7d:
    a6:9b:37:63:04:5a:c3:13
coefficient:
    00:cc:d7:5c:e6:0e:7b:79:d4:cb:4f:6d:82:a7:45:
    90:67:90:dc:d3:83:62:f1:4b:17:43:5c:4a:ea:bf:
    38:25:c3:6f:34:e2:05:91:5e:60:d6:de:6d:07:1a:
    73:71:b3:1d:73:f2:3c:60:ed:ec:42:d4:39:f8:a4:
    ae:d5:aa:40:1e:90:b1:eb:b1:05:a3:2f:03:5f:c6:
    b7:07:4c:df:0f:c4:a9:80:8c:31:f5:e2:01:00:73:
    8a:25:03:84:4e:48:7a:31:8e:e6:b8:04:4c:44:61:
    7d:e4:87:1c:57:4f:45:44:33:bb:f3:ae:1c:d2:e1:
    99:ed:78:29:76:4d:8c:6d:91

相关的,你永远不会问如何用RSA密钥加密或解密,但你声称加密和解密问题的答案显示在答案的代码中。

你似乎已经把问题变成了一个移动目标:)你应该在Stack Overflow上避免这种情况(我认为在那些用户线程论坛中可以做到这一点)。在Stack Overflow上,你应该问一个单独的问题。

答案 1 :(得分:3)

您可以使用d2i_RSAPublicKeyi2d_RSAPublicKey (link)从RSA密钥对中提取RSA公钥。使用i2d_RSAPublicKey将密钥对编码为PKCS#1 RSAPublicKey结构,将其存储在字节字符串中,然后使用d2i_RSAPublicKey将其解码回RSA密钥结构。

答案 2 :(得分:3)

我在其他Stack-Overflow帖子中找到了我的问题的解决方案,即Reading Public/Private Key from Memory with OpenSSL

我正在寻找的答案由@SquareRootOfTwenty回答三,这是他的最后一行代码,

将Public密钥解压缩到名为pub:

的BIO变量中
PEM_write_bio_RSAPublicKey(pub, keypair);

我可以通过网络发送变量pub,在它到达另一侧之后创建一个RSA变量并将pub放入其中:

解决方案:

RSA *keypair2 = NULL; 
PEM_read_bio_RSAPublicKey( pub, &keypair2, NULL, NULL);

完成此操作后,我可以像往常一样使用keypair2成功加密邮件:

ENCRYPTION:

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);
}

然后,我可以将此加密变量发送回第一台计算机,并使用原始keypair照常解密,而无需通过网络发送。

解密:

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);
}

谢谢大家为这篇文章做出贡献!!!

答案 3 :(得分:0)

检查代码时,您似乎已成功将publicprivate键分隔为字符串pub_key和pri_key,但随后使用printf输出它们将它们粘贴在一起。要打印public键,请将printf语句更改为:

printf("\n%s\n", pub_key); 
相关问题