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;
}
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With