I am trying to sign a message with a RSA private key. I read a private key to pkey and then sign a string as what says on openssl wiki, but failed in the final step. It always returns 0 on the line commented in program, which means sign failed. Could anyone helps me find out what’s wrong?
void main() {
EVP_MD_CTX * mdctx ;
EVP_PKEY * pkey ;
char dmessage[20] = "The messages";
int ret = 0;
FILE * fp;
unsigned char * sig = NULL;
size_t * slen = malloc(sizeof(size_t));
fp = fopen ("privkey.pem", "r");
if (fp == NULL) exit (1);
pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
fclose (fp);
if (pkey == NULL) {
ERR_print_errors_fp (stderr);
exit (1);
}
if(!(mdctx = EVP_MD_CTX_create())) goto err;
if(1 != EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, pkey)) goto err;
if(1 != EVP_DigestSignUpdate(mdctx, dmessage, 12)) goto err;
if(1 != EVP_DigestSignFinal(mdctx, NULL, slen)) goto err;
if(!(sig = OPENSSL_malloc(sizeof(unsigned char) * (int)(*slen)))) goto err;
if(1 != (ret = EVP_DigestSignFinal(mdctx, sig, slen))) goto err;//*****it return 0 here,which means sign failed
ret = 1;
err:
if(ret != 1)
{
printf("%d somthing wrong\n",ret);
}
/* Clean up */
if(sig && !ret) OPENSSL_free(sig);
if(mdctx) EVP_MD_CTX_destroy(mdctx);
return;
}
Thanks a lot!
I’m using openssl 1.0.1j on linux mint 17, and the private key is generated by
openssl genrsa -out privkey.pem 256
Your key is way too small, that's bits not bytes. Try again with a good secure key size that can hold the hash and PKCS#1 padding. I would recommend at least 2048 bits instead of the 256 bits that you generated using the OpenSSL command line.
See keylength.com for more information about key sizes. Note that RSA requires a key size a lot larger than those required for symmetric algorithms such as AES.
Related
I am creating an RSA key pair with the following code (C and OpenSSL library):
void rsa_gen_keys_ca() {
RSA *keypair = NULL;
unsigned char *pub_key = NULL;
BIGNUM *bne = NULL;
unsigned long e = RSA_F4;
int success = 0;
bne = BN_new();
success = BN_set_word(bne, e);
if (!success) {
errx(1, "\nrsa_gen_keys_ca failed at BN_set_word result.");
goto free_all;
}
keypair = RSA_new();
success = RSA_generate_key_ex(keypair, RSA_KEY_SIZE, bne, NULL);
if (!success) {
errx(1, "\nrsa_gen_keys_ca failed at RSA_generate_key_ex result.");
goto free_all;
}
success = i2d_RSAPublicKey(keypair, &pub_key);
if (success < 0) {
errx(1, "\nrsa_gen_keys_ca failed at i2d_RSAPublicKey result.");
goto free_all;
}
printf("==========RSA Public Key successfully extracted: %s", pub_key);
free_all:
RSA_free(keypair);
BN_free(bne);
}
When I run it, I am receiving the following warning:
random: uninitialized urandom read (32 bytes read)
I think leaving the code with this warning would be a security concern, since in the past I read something regarding the urandom generator.
Can anyone explain this warning and how to avoid it?
For industrial purposes, I want to decrypt an AES-encrypted message with an RSA-encrypted key in C. At first, I thought doing it step-by-step by first, using OpenSSL libcrypto library, by first RSA decoding the key then AES decoding the data.
I have found out that EVP tools were commonly seen as a better way to do this since it actually does what the low-levels functions do but correctly.
Here is what I see the flow of the program :
Initialize OpenSSL;
Read and store the RSA private key;
Initialize the decryption by specifying the decryption algorithm (AES) and the private key;
Update the decryption by giving the key, the data, the key and their length
Finally decrypt the data and return it.
I have been a lot confused by the fact that so far we do not intend to use any IV or ADD (although IV might come up later in the project). I have followed this guide it is not very clear and does not fit the way I use EVP.
So here is my actual code :
#include <openssl/evp.h>
#include <openssl/conf.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/aes.h>
#include <openssl/err.h>
#include "openssl\applink.c"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
const char PRIVATE_KEY_PATH[] = "C:/Users/Local_user/privateKey.pem";
EVP_PKEY* initializePrivateKey(void)
{
FILE* privateKeyfile;
if ((privateKeyfile = fopen(PRIVATE_KEY_PATH, "r")) == NULL) // Check PEM file opening
{
perror("Error while trying to access to private key.\n");
return NULL;
}
RSA *rsaPrivateKey = RSA_new();
EVP_PKEY *privateKey = EVP_PKEY_new();
if ((rsaPrivateKey = PEM_read_RSAPrivateKey(privateKeyfile, &rsaPrivateKey, NULL, NULL)) == NULL) // Check PEM file reading
{
fprintf(stderr, "Error loading RSA Private Key File.\n");
ERR_print_errors_fp(stderr);
return NULL;
}
if (!EVP_PKEY_assign_RSA(privateKey, rsaPrivateKey))
{
fprintf(stderr, "Error when initializing EVP private key.\n");
ERR_print_errors_fp(stderr);
return NULL;
}
return privateKey;
}
const uint8_t* decodeWrappingKey(uint8_t const* data, const size_t data_len, uint8_t const* wrappingKey, const size_t wrappingKey_len)
{
// Start Decryption
EVP_CIPHER_CTX *ctx;
if (!(ctx = EVP_CIPHER_CTX_new())) // Initialize context
{
fprintf(stderr, "Error when initializing context.\n");
ERR_print_errors_fp(stderr);
return NULL;
}
EVP_PKEY *privateKey = initializePrivateKey();
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, privateKey, NULL)) // Initialize decryption
{
fprintf(stderr, "Error when initializing decryption.\n");
ERR_print_errors_fp(stderr);
return NULL;
}
uint8_t* res;
if ((res = calloc(data_len, sizeof(uint8_t))) == NULL) // Check memory allocating
{
perror("Memory allocating error ");
return NULL;
}
puts("Initialization done. Decoding..\n");
size_t res_len = 0;
if (1 != EVP_DecryptUpdate(ctx, res, &res_len, data, data_len))
{
fprintf(stderr, "Error when preparing decryption.\n");
ERR_print_errors_fp(stderr);
}
if (1 != EVP_DecryptFinal_ex(ctx, res, &res_len))
{
fprintf(stderr, "Error when decrypting.\n");
ERR_print_errors_fp(stderr);
}
return res;
}
void hexToBytes(uint8_t *des, char const *source, const size_t size) {
for (int i = 0; i < size - 1; i += 2)
sscanf(source + i, "%02x", des + (i / 2));
}
int main(void) {
char const *strWrap = "5f82c48f85054ef6a3b2621819dd0e969030c79cc00deb89........";
char const *strData = "ca1518d44716e3a4588af741982f29ad0a3e7a8d67.....";
uint8_t *wrap = calloc(strlen(strWrap), sizeof(uint8_t));
hexToBytes(wrap, strWrap, strlen(strWrap)); // Converts string to raw data
uint8_t *data = calloc(strlen(strData), sizeof(uint8_t));
hexToBytes(data, strData, strlen(strData));
/* Load the human readable error strings for libcrypto */
ERR_load_crypto_strings();
/* Load all digest and cipher algorithms */
OpenSSL_add_all_algorithms();
/* Load config file, and other important initialisation */
OPENSSL_config(NULL);
const uint8_t *res = decodeWrappingKey(data, strlen(strData) / 2, wrap, strlen(strWrap) / 2);
if (res == NULL)
return 1;
return 0;
}
My output is the following one :
Initialization done. Decoding..
Error when preparing decryption.
Error when decrypting.
Obviously it fails when updating and finalising the decryption but I can't figure out why and the ERR_print_errors_fp(stderr); which had always worked for me so far seems to be mute.
Here is a complete working example of how you can encrypt a key using RSA, and encrypt a message using that key using AES, followed by the subsequent decryption of those things. It assumes AES-256-CBC is being used. If you want to use AES-256-GCM instead then you will need to make some changes to get and set the tag (ask me if you need some pointers on how to do this). It also assumes that the RSA encryption is done with PKCS#1 padding (which is all that the EVP_Seal* APIs support). If you need some other kind of padding then you will need to use a different method. Finally it assumes you are using OpenSSL 1.1.0. If you are using 1.0.2 then some changes will probably be necessary (at least you will need to explicitly init and de-init the library - that isn't required in 1.1.0).
The code reads the RSA private and public keys from files called privkey.pem and pubkey.pem which are in the current working directory. I generated these files like this:
openssl genrsa -out privkey.pem 2048
openssl rsa -in privkey.pem -pubout -out pubkey.pem
I've tested this on Linux only. The code is as follows:
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int envelope_seal(EVP_PKEY *pub_key, unsigned char *plaintext,
int plaintext_len, unsigned char **encrypted_key,
int *encrypted_key_len, unsigned char **iv,
int *iv_len, unsigned char **ciphertext,
int *ciphertext_len)
{
EVP_CIPHER_CTX *ctx;
int len, ret = 0;
const EVP_CIPHER *type = EVP_aes_256_cbc();
unsigned char *tmpiv = NULL, *tmpenc_key = NULL, *tmpctxt = NULL;
if((ctx = EVP_CIPHER_CTX_new()) == NULL)
return 0;
*iv_len = EVP_CIPHER_iv_length(type);
if ((tmpiv = malloc(*iv_len)) == NULL)
goto err;
if ((tmpenc_key = malloc(EVP_PKEY_size(pub_key))) == NULL)
goto err;
if ((tmpctxt = malloc(plaintext_len + EVP_CIPHER_block_size(type)))
== NULL)
goto err;
if(EVP_SealInit(ctx, type, &tmpenc_key, encrypted_key_len, tmpiv, &pub_key,
1) != 1)
goto err;
if(EVP_SealUpdate(ctx, tmpctxt, &len, plaintext, plaintext_len) != 1)
goto err;
*ciphertext_len = len;
if(EVP_SealFinal(ctx, tmpctxt + len, &len) != 1)
goto err;
*ciphertext_len += len;
*iv = tmpiv;
*encrypted_key = tmpenc_key;
*ciphertext = tmpctxt;
tmpiv = NULL;
tmpenc_key = NULL;
tmpctxt = NULL;
ret = 1;
err:
EVP_CIPHER_CTX_free(ctx);
free(tmpiv);
free(tmpenc_key);
free(tmpctxt);
return ret;
}
int envelope_open(EVP_PKEY *priv_key, unsigned char *ciphertext,
int ciphertext_len, unsigned char *encrypted_key,
int encrypted_key_len, unsigned char *iv,
unsigned char **plaintext, int *plaintext_len)
{
EVP_CIPHER_CTX *ctx;
int len, ret = 0;
unsigned char *tmpptxt = NULL;
if((ctx = EVP_CIPHER_CTX_new()) == NULL)
return 0;
if ((tmpptxt = malloc(ciphertext_len)) == NULL)
goto err;
if(EVP_OpenInit(ctx, EVP_aes_256_cbc(), encrypted_key, encrypted_key_len,
iv, priv_key) != 1)
return 0;
if(EVP_OpenUpdate(ctx, tmpptxt, &len, ciphertext, ciphertext_len) != 1)
return 0;
*plaintext_len = len;
if(EVP_OpenFinal(ctx, tmpptxt + len, &len) != 1)
return 0;
*plaintext_len += len;
*plaintext = tmpptxt;
tmpptxt = NULL;
ret = 1;
err:
EVP_CIPHER_CTX_free(ctx);
free(tmpptxt);
return ret;
}
int main(void)
{
EVP_PKEY *pubkey = NULL, *privkey = NULL;
FILE *pubkeyfile, *privkeyfile;
int ret = 1;
unsigned char *iv = NULL, *message = "Hello World!\n";
unsigned char *enc_key = NULL, *ciphertext = NULL, *plaintext = NULL;
int iv_len = 0, enc_key_len = 0, ciphertext_len = 0, plaintext_len = 0, i;
if ((pubkeyfile = fopen("pubkey.pem", "r")) == NULL) {
printf("Failed to open public key for reading\n");
goto err;
}
if ((pubkey = PEM_read_PUBKEY(pubkeyfile, &pubkey, NULL, NULL)) == NULL) {
fclose(pubkeyfile);
goto err;
}
fclose(pubkeyfile);
if ((privkeyfile = fopen("privkey.pem", "r")) == NULL) {
printf("Failed to open private key for reading\n");
goto err;
}
if ((privkey = PEM_read_PrivateKey(privkeyfile, &privkey, NULL, NULL))
== NULL) {
fclose(privkeyfile);
goto err;
}
fclose(privkeyfile);
if (!envelope_seal(pubkey, message, strlen(message), &enc_key, &enc_key_len,
&iv, &iv_len, &ciphertext, &ciphertext_len))
goto err;
printf("Ciphertext:\n");
for (i = 0; i < ciphertext_len; i++)
printf("%02x", ciphertext[i]);
printf("\n");
printf("Encrypted Key:\n");
for (i = 0; i < enc_key_len; i++)
printf("%02x", enc_key[i]);
printf("\n");
printf("IV:\n");
for (i = 0; i < iv_len; i++)
printf("%02x", iv[i]);
printf("\n");
if (!envelope_open(privkey, ciphertext, ciphertext_len, enc_key,
enc_key_len, iv, &plaintext, &plaintext_len))
goto err;
plaintext[plaintext_len] = '\0';
printf("Plaintext: %s\n", plaintext);
ret = 0;
err:
if (ret != 0) {
printf("Error\n");
ERR_print_errors_fp(stdout);
}
EVP_PKEY_free(pubkey);
EVP_PKEY_free(privkey);
free(iv);
free(enc_key);
free(ciphertext);
free(plaintext);
return ret;
}
Your key is encrypted with RSA, so you will decrypt it with RSA APIs like RSA_private_decrypt first, not with EVP* APIs.
Once you get key decrypted you need to use it with (EVP*) APIs to decrypt the data with AES.
This is a c function I wrote to generate openssl rsa 4096 bit keys.
bool rsa_gen_keys()
{
int ret = 0;
RSA *rsa = NULL;
BIGNUM *bignum = NULL;
BIO *bio_private = NULL;
BIO *bio_public = NULL;
int bits = 4096;
unsigned long k = RSA_F4;
bignum = BN_new();
ret = BN_set_word(bignum,k);
if(ret != 1){
goto cleanup;
}
rsa = RSA_new();
ret = RSA_generate_key_ex(rsa, bits, bignum, NULL);
if(ret != 1){
goto cleanup;
}
// write rsa private key to file
bio_private = BIO_new_file("private_new.pem", "w+");
ret = PEM_write_bio_RSAPrivateKey(bio_private, rsa, NULL, NULL, 0, NULL, NULL);
BIO_flush(bio_private);
// write rsa public key to file
bio_public = BIO_new_file("public_new.pem", "w+");
ret = PEM_write_bio_RSAPublicKey(bio_public, rsa);
if(ret != 1){
goto cleanup;
}
BIO_flush(bio_public);
cleanup:
BIO_free_all(bio_private);
BIO_free_all(bio_public);
RSA_free(rsa);
BN_free(bignum);
return ret;
}
The keys generated by the above function seem to be missing something. When I try to use the public_new.pem file in another program, I get the following error:
140286309791384:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:701:Expecting: PUBLIC KEY
However, if I use the openssl command to generate the key files, the files work fine.
$openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:4096
I noticed the key sizes generated from the function and from the command line don't match. This is a clue, but what do I need to change in my function to fix this?
-rw-rw-r-- 1 3272 Feb 6 09:19 private_key.pem
-rw-rw-r-- 1 800 Feb 6 09:20 public_key.pem
-rw-rw-r-- 1 3243 Feb 6 10:43 private_new.pem
-rw-rw-r-- 1 775 Feb 6 10:43 public_new.pem
BTW, I tried the above with 2048 bits keys and I get the same result and same size mismatch
openssl genpkey is using PEM_write_bio_PrivateKey (PKCS#8) instead of PEM_write_bio_RSAPrivateKey (PKCS#1): https://github.com/openssl/openssl/blob/master/apps/genpkey.c#L161-L164.
You don't show how you generated public_key.pem, but it was probably written with PEM_write_bio_PUBKEY (X.509 SubjectPublicKeyInfo) vs PEM_write_bio_RSAPublicKey (PKCS#1).
From a PEM armor perspective:
PKCS#1 Public: BEGIN RSA PUBLIC KEY
X.509 SubjectPublicKeyInfo: BEGIN PUBLIC KEY
PKCS#1 Private: BEGIN RSA PRIVATE KEY
PKCS#8: BEGIN PRIVATE KEY
I realized I needed to use the format of the keys for PKCS#8 and X.509. So I switched to EVP functions to generate them. Here is a very simplified version of the code I ended up using (no error checking):
bool rsa_gen_keys() {
int ret = 0;
BIO *bio_private = NULL;
BIO *bio_public = NULL;
int bits = 4096;
EVP_PKEY_CTX *ctx;
EVP_PKEY *pkey = NULL;
// Get the context
ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
if (!ctx)
goto cleanup;
// init keygen
if (EVP_PKEY_keygen_init(ctx) <= 0)
goto cleanup;
// set the bit size
if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) <= 0)
goto cleanup;
/* Generate key */
if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
goto cleanup;
// write rsa private key to file
bio_private = BIO_new_file("private_new.pem", "w+");
ret = PEM_write_bio_PrivateKey(bio_private, pkey, NULL, NULL, 0, NULL, NULL);
if (ret != 1) {
goto cleanup;
}
BIO_flush(bio_private);
// write rsa public key to file
bio_public = BIO_new_file("public_new.pem", "w+");
//ret = PEM_write_bio_RSAPublicKey(bio_public, rsa);
ret = PEM_write_bio_PUBKEY(bio_public, pkey);
if (ret != 1) {
goto cleanup;
}
BIO_flush(bio_public);
cleanup:
if(bio_private) BIO_free_all(bio_private);
if(bio_public) BIO_free_all(bio_public);
if(pkey) EVP_PKEY_free(pkey);
return ret;
}
I am trying out a small example program to decrypt a message that has been signed and then encrypted using openSSL. It works well in the command line. However upon trying out the code after modifying the code in the 'demos' folder of OpenSSL, the decryption fails
Here is the decryption code:
int decrypt_smime(){
BIO *in = NULL, *out = NULL, *tbio = NULL;
X509 *rcert = NULL;
EVP_PKEY *rkey = NULL;
//PKCS7 *cms = NULL;
CMS_ContentInfo *cms = NULL;
int ret = 1;
int flags = CMS_STREAM;
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
printf("decrypt...\n");
/* Read in recipient certificate and private key */
tbio = BIO_new_file("signer.pem", "r");
if (!tbio)
goto err;
rcert = PEM_read_bio_X509(tbio, NULL, 0, NULL);
BIO_reset(tbio);
rkey = PEM_read_bio_PrivateKey(tbio, NULL, 0, NULL);
if (!rcert || !rkey)
goto err;
printf("decrypt...\n");
/* Open S/MIME message to decrypt */
in = BIO_new_file("smencsign.txt", "r");
if (!in)
goto err;
printf("keys read...\n");
/* Parse message */
cms = SMIME_read_CMS(in, NULL); //here is the problem I think
if (!cms)
goto err;
printf("keys read...\n");
out = BIO_new_file("decout.txt", "w");
if (!out)
goto err;
/* Decrypt S/MIME message */
if (!CMS_decrypt(cms, rkey, rcert, NULL, out, flags))
goto err;
ret = 0;
err:
if (ret)
{
fprintf(stderr, "Error Decrypting Data\n");
ERR_print_errors_fp(stderr);
}
if (cms)
//PKCS7_free(cms);
CMS_ContentInfo_free(cms);
if (rcert)
X509_free(rcert);
if (rkey)
EVP_PKEY_free(rkey);
if (in)
BIO_free(in);
if (out)
BIO_free(out);
if (tbio)
BIO_free(tbio);
return ret;
}
The error I get is:
Error Verifying Data
*3074258568:error:0D0D40D1:asn1 encoding routines:SMIME_read_ASN1:no content type:asn_mime.c:451:*
The commands on openssl that worked:
openssl cms -sign -in encr.txt -signer signer.pem -text | openssl cms -encrypt -out smencsign.txt signer.pem
openssl smime -decrypt -in smencsign.txt -recip signer.pem -inkey signer.pem
So clearly openssl uses 'cms' utility to sign and encrypt but seems to use 'smime' utility for decryption. What is then the code equivalent?
Try to add the following line:
OpenSSL_add_all_ciphers();
I am facing a problem in RSA decryption using OpenSSL Library (EVP api).
Here is my code for key generation
#include <stdio.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#define SECFILE "sec.pem"
#define PUBFILE "pub.pem"
int main()
{
EVP_PKEY_CTX *ctx;
EVP_PKEY *pkey = NULL;
ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
FILE *fp;
if (!ctx)
{
/* Error occurred */
perror("Error in CTX \n");
}
if (EVP_PKEY_keygen_init(ctx) <= 0)
{
/* Error */
perror("Error in EVP_PKEY_keygen_init \n");
}
if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048) <= 0)
{
/* Error */
perror("Error in EVP_PKEY_CTX_set_rsa_keygen_bits \n");
}
/* Generate key */
if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
{
/* Error */
perror("Error in EVP_PKEY_keygen \n");
}
fp = fopen(SECFILE, "w");
PEM_write_PrivateKey(fp, pkey, NULL,NULL, 0,0, NULL);
fclose(fp);
fp = fopen(PUBFILE, "w");
PEM_write_PUBKEY(fp,pkey);
fclose(fp);
return 0;
}
For encryption :
I used this link
For decryption :
int do_evp_open(FILE *rsa_pkey_file, FILE *in_file, FILE *out_file)
{
int retval = 0;
RSA *rsa_pkey = NULL;
EVP_PKEY *pkey = EVP_PKEY_new();
EVP_CIPHER_CTX ctx;
unsigned char buffer[4096];
unsigned char buffer_out[4096 + EVP_MAX_IV_LENGTH];
size_t len;
int len_out;
unsigned char *ek;
int eklen ;
uint32_t eklen_n;
unsigned char iv[EVP_MAX_IV_LENGTH] = {122,205,106,192,4,183,69,176,84,28,214,226,220,140,86,174};
/// Read RSA Private Key
if (PEM_read_RSAPrivateKey(rsa_pkey_file, &rsa_pkey, NULL, NULL) == NULL)
{
fprintf(stderr, "Error loading RSA Private Key File.\n");
ERR_print_errors_fp(stderr);
retval = -2;
goto out;
}
/// Assign RSA key to EVP key
if (!EVP_PKEY_assign_RSA(pkey, rsa_pkey))
{
fprintf(stderr, "EVP_PKEY_assign_RSA: failed.\n");
retval = -3;
goto out;
}
EVP_CIPHER_CTX_init(&ctx);
ek = malloc( EVP_PKEY_size(pkey));
if (!EVP_OpenInit(&ctx, EVP_aes_128_cbc(), ek, eklen, iv,pkey))
{
fprintf(stderr, "EVP_OpenInit: failed.\n");
ERR_print_errors_fp(stderr); /// Prints error of occured in Openssl
retval = -3;
goto out_free;
}
while ((len = fread(buffer, 1, sizeof buffer, in_file)) > 0)
{
if (!EVP_OpenUpdate(&ctx, buffer_out, &len_out, buffer, len))
{
fprintf(stderr, "EVP_OpenUpdate: failed.\n");
retval = 3;
goto out_free;
}
if (fwrite(buffer_out, len_out, 1, out_file) != 1)
{
perror("output file");
retval = -5;
goto out_free;
}
}
if (ferror(in_file))
{
perror("input file");
retval = -4;
goto out_free;
}
if (!EVP_OpenFinal(&ctx, buffer_out, &len_out))
{
fprintf(stderr, "EVP_OpenFinal: failed.\n");
retval = - 3;
goto out_free;
}
if (fwrite(buffer_out, len_out, 1, out_file) != 1)
{
perror("output file");
retval = -5;
goto out_free;
}
out_free:
EVP_PKEY_free(pkey);
free(ek);
out:
return retval;
}
My Private and public keys are :
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDj+g6m7KY5zK8z
FZ/MKFySr1ZB+n0b3GjhMUcUDn5S9N7oyoCzkOVVa7gl0jTI8dwCFVAy8693Rq+i
AT7dUTLViT9V8GkX9r0yFcppt5uc2YgI5aOOTvmQKQe08FSZ7QbviEL25MNnBfB1
wpd+mJN3nb0hkeo7x2IZD/ZVfs+TmOG9mHbQR8b1XcxEDoLx3aX1J8Eix1pN7YK6
nDAFm984Ho+PCz1aGl/TnDl3b90X5HXGHiD6uNDHokZ+th8B6AeFFRlkWlQd0w2R
e/EEZ36p4TQOHSc3sSUw6pen0N8YmBNZksBEr1vsZvYkKtRKCfy0fXtL4iqKzcgJ
ocos+Z6nAgMBAAECggEBALlWDdlYpF5y76/JEaso2PGLR8XFvTYMPttsc0tz6PDK
D/oSvwS8dCS4uPFObgk6ztCGwTda8rg2KAy9lHzaSUheFrZoBxgrSG5SVscRNJoU
IsqQ3iGQRMUVBiXsB+tHTg8nqMENA2pa4rzpoL2Tjrd87kg/VryYgEC9wFaLDHgB
FaXJJlaeuTBQXV7Ga9pg+KF1Kv91/q3T62Um0ggSajFpX15x6sLIo5EWm0DGksn0
chQeiEs33e8fHil95g0nXK+hXOMnMvbAln/eOCGktO4JnPTjicAA7iKliCsLiaeZ
t5Czscv/8AVlBAISGJcE8ASM+AbalXtnoOK6W+dv0gkCgYEA/cPi7U8bJ0tlvxF3
3vc8V7uzuAgKtOKQet1spQtAoi343ZoSyFHQEwO5PMmtB56/mk3+/mDpoKTQo0oK
f5COIlzW+PIMQCroalpJe+ZcY/PS8SPoOY39yiX4WQchgac01R0Qf6XDAOfyfZ9d
MZTtDgpkx/oyfRTzxI7D9SZUqZ0CgYEA5fwH5uwmc0fsIw3tl3pHHOK9g78Rs6XE
0feXplBCzx+qaEtAK1Jp1nMX/PmN575i3UN3dii9YV8v9geTf+hytpQd/TbrvsSY
Py9j95XYN75Z5TAsWnZbZr/gTdZSz0yObb/9GzxBipp+EHCEOSS0RF8u9XHlM9bC
0agB4VZKqBMCgYByIjxaR44K6lpkyVKEseYt/3ohd1x5Zr1cxWIsCReU2eBoqvdv
qXxQUQhrUrnEB55dpF7fwm7Rlc9Q4eg+36FNyzvU0+i2o5XM37bVRxKe0fc6BdBY
sohG9zTvtclYKwAUKfJVtxQxwCDMZ3Te7ACCpCIX32v93gKVkTCJfift8QKBgHZ9
PAEAZ+r7AjEpSuDBMgQy2ZsYBOG+pUHcQzh/n3wg/2XOZ1gqlLbVA2XlmPPtxffj
e5fX84JITWh/jMHYm8lvVGgSNLFLjnj3TJTRkd1eZ+hJwoA0/HBaqRDRPEbrVXI7
+QZgLBBh+lMz9RuPyoRzWblBHepwWl00JwvWro4bAoGBAKFAXVzbx74JM6wzr9H5
TusTwOM5mf/I1TkCq1Dd5n1vDVfrkNokZ2LfJWqiQHLZj2rGxSQSVjIsVaBmEDTZ
ob8duUsbkYQe4dToHFHcBO+akBtULC4HWv/D4pPVoyAE7WJBJBw0vl1sA15kiXBu
HBXffOzN/Erqvp90HLtefpMp
-----END PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4/oOpuymOcyvMxWfzChc
kq9WQfp9G9xo4TFHFA5+UvTe6MqAs5DlVWu4JdI0yPHcAhVQMvOvd0avogE+3VEy
1Yk/VfBpF/a9MhXKabebnNmICOWjjk75kCkHtPBUme0G74hC9uTDZwXwdcKXfpiT
d529IZHqO8diGQ/2VX7Pk5jhvZh20EfG9V3MRA6C8d2l9SfBIsdaTe2CupwwBZvf
OB6Pjws9Whpf05w5d2/dF+R1xh4g+rjQx6JGfrYfAegHhRUZZFpUHdMNkXvxBGd+
qeE0Dh0nN7ElMOqXp9DfGJgTWZLARK9b7Gb2JCrUSgn8tH17S+Iqis3ICaHKLPme
pwIDAQAB
-----END PUBLIC KEY-----
The error I am getting While EVP_OpenInit is :
140004942804648:error:0407106B:lib(4):func(113):reason(107):rsa_pk1.c:190: 140004942804648:error:04065072:lib(4):func(101):reason(114):rsa_eay.c:594
Any help would be appreciated.
Thanks,
Pawan
Are you absolutely sure, that you have initialized variable eklen?
I see you have used EVP_OpenInit(), EVP_OpenUpdate() and EVP_OpenFinal() for decryption. So I'm going to assume that you've used EVP_SealInit(), EVP_SealUpdate() and EVP_SealFinal() functions for encryption.
So if you have used EVP_SealInit(), you must have passed the address (pointer) to eklen (please check man EVP_SealInit) where the variable gets a value assigned. In analogous to that the eklen variable that you are passing to EVP_OpenInit() must contain a valid key length.
The following is the description from man EVP_OpenInit.
EVP_OpenInit() initializes a cipher context ctx for decryption with cipher type. It decrypts the encrypted symmetric key of length ekl bytes passed in the ek parameter using the private key priv. The IV is supplied in the iv parameter.
I'm not sure here, but I guess you need to use EVP_PKEY_size() function in this case to get the length of the key.
For example (in your decryption code):
....
..
.
EVP_CIPHER_CTX_init(&ctx);
ek = malloc( EVP_PKEY_size(pkey));
/* Add the following line */
eklen = EVP_PKEY_size(pkey);
if (!EVP_OpenInit(&ctx, EVP_aes_128_cbc(), ek, eklen, iv,pkey))
{
fprintf(stderr, "EVP_OpenInit: failed.\n");
...
..
.