Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Separating public and private keys from RSA keypair variable

Tags:

c++

openssl

rsa

As the title says, I have some code that generates a pair of RSA keys. I want to split them apart and use them individually to encrypt/decrypt, rather than use the variable "keypair" to encrypt, and decrypt.

I am working to transfer data across a network, and want to encrypt it using simple RSA encryption. Therefore i want to send the public key over to a different user, so he can use it to encrypt some data, and then send it back to me.

Here is the code that generates the keys:

//Generate key pair
    RSA *keypair = RSA_generate_key(KEY_LENGTH, PUB_EXP, NULL, NULL);

I now want to separate the public from the private key, so i can use them independently to encrypt and decrypt data. How can i do that?

I've got some code that takes the "keypair" and extracts some information into some "BIO" variables, although i am not sure how that would help me:

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

This code works, since i've tested it in visual studio 2012. Any ideas on how to separate the keys, then maybe put them back together in a "keypair" or maybe how to use them separately to encrypt/decrypt some string variables?

Thank you

(FULL CODE)

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

Found this code here : https://shanetully.com/2012/04/simple-public-key-encryption-with-rsa-and-openssl/

like image 903
Dani Marian Morar Avatar asked Dec 25 '22 11:12

Dani Marian Morar


1 Answers

I want to split [the keypair] apart and use them individually to encrypt/decrypt

... Any ideas on how to separate the keys, then maybe put them back together in a "keypair" or maybe how to use them separately to encrypt/decrypt some string variables?

You can use RSAPublicKey_dup and RSAPrivateKey_dup, without the need to round trip them by ASN.1/DER or PEM encoding them. Here, round tripping consist of using a functions like PEM_write_bio_RSAPublicKey and PEM_read_bio_RSAPublicKey.

Below is a sample program that uses them. Its written in C++ (thanks for adding that tag).

While you can separate them, they both use the RSA structure. The public key has some members set to NULL, like the private exponent.


You can also print the keys with RSA_print, RSA_print_fp and friends. See RSA_print (3) or its use below.


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

Here is the output:

$ ./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

Related, you never ask how to encrypt or decrypt with a RSA key, yet you claim the answer to the encryption and decryption problems is shown in the code in your answer.

You seem to have made the question a moving target :) You should probably avoid that on Stack Overflow (I think its OK to do in those user thread forums). On Stack Overflow, you should ask a separate question.

like image 87
jww Avatar answered Jan 04 '23 23:01

jww