Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get the RSA* object from a char array that contains the public key in OpenSSL?

Im trying to encrypt and decrypt messages while storing the private and public keys on char vectors. I have tried d2i_PublicKey(...) and using EVP_PKEY objects in EVP_set1_RSA(...). I also do not know what are all the parameters in EVP_set1_RSA(...). Please help. Here is my code:

#include <stdio.h>

//RSA
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <arpa/inet.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/x509.h>

#define RSA_KEY_LENGTH 2048
#define PUB_EXP     3
#define PRINT_KEYS

//RSA


int main()
{
    printf("\ngenerating keys...\n");
    RSA *keypair = RSA_generate_key(RSA_KEY_LENGTH, PUB_EXP, NULL, NULL);


    // ---------

    printf("Converting Keys to char array..\n");

    char   *pri_key = NULL;           // Private key
    char   *pub_key = NULL;           // Public key
    size_t pri_len;            // Length of private key
    size_t pub_len;            // Length of public key

    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';

    // ---------



    char msg[RSA_KEY_LENGTH/8] = "HOLA, ESPERO QUE ME ENCRIPTES";
    char   *encrypt = NULL;    // Encrypted message
    char   *decrypt = NULL;    // Decrypted message

    printf("encrypting: %s\n", msg);



/*
* Here I want to obtain an RSA *PublicKey to use it for the encryption 
*/


    int encrypt_len;
    err = (char*)malloc(130);
    printf("++++\n");
    if((encrypt_len = RSA_public_encrypt(strlen(msg), (unsigned char*)msg, (unsigned char*)encrypt, PublicKey, RSA_PKCS1_OAEP_PADDING)) == -1) {
        printf("err++++\n");
        ERR_load_crypto_strings();
        ERR_error_string(ERR_get_error(), err);
        fprintf(stderr, "Error encrypting message: %s\n", err);

    }

    return 0;
}
like image 351
ghyur7 Avatar asked Oct 20 '22 20:10

ghyur7


1 Answers

I've found a solution to this issue among other Stack-Overflow posts and namely here :Reading Public/Private Key from Memory with OpenSSL

The answer you waere looking for is answered by @SquareRootOfTwentyThree is his last line of code,

After extracting the Public key into a BIO variable called pub:

PEM_write_bio_RSAPublicKey(pub, keypair);

create a RSA variable and put pub inside it:

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

After you've done this you can successfully encrypt the message as usual, using 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);
}

you can then decrypt it as usual, using the original keypair, without having to use it at your first encryption

Decryption:

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

This might help if you want to transfer the "pub" variable over a network, use it to encrypt a message, then send the encrypted data back to the original machine to get it decrypted.

If you really want to use char variables, as you said in your question, you can of course copy the memory as raw to a char variable (from the BIO one) using memcpy, but don't forget to add the "\0" at the end, here, this post should help: Separating public and private keys from RSA keypair variable

like image 86
Dani Marian Morar Avatar answered Oct 31 '22 18:10

Dani Marian Morar