Hello everybody.
My goal is to crypt/decrypt simple strings
in a programmatic way, using OpenSSL crypt library.
Please consider the C program attached below.
Could someone explain to me why on a Linux/Intel
platform this program works fine and why it doesn't
work at all on a Solaris/Sparc and even MacOS X/PowerPC
platform ?
The RSA_public_encrypt routine sends -1 as result.. why ?
Best regards
Josef
/* Test of RSA encryption */
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#define NUM_ITERATIONS 1000
/***
* Extracts public key from X.509 certificate
*/
EVP_PKEY * ReadPublicKeyInCert(const char * certfile)
{
FILE * fp = fopen(certfile, "r");
EVP_PKEY * pkey = NULL;
X509 * x509;
char ** buff = NULL;
if (!fp) return NULL;
x509 = (X509 *)PEM_ASN1_read((char *(*)())d2i_X509, PEM_STRING_X509,
fp, buff, NULL, NULL);
if (x509 == NULL) {
ERR_print_errors_fp (stderr);
return NULL;
}
fclose (fp);
pkey = X509_extract_key(x509);
X509_free(x509);
if (pkey == NULL) ERR_print_errors_fp (stderr);
return pkey;
}
/***
* Reads private key from file
*/
EVP_PKEY * ReadPrivateKey(const char * keyfile)
{
FILE * fp = fopen(keyfile, "r");
EVP_PKEY * pkey = NULL;
char ** buff = NULL;
if (!fp) return NULL;
pkey = (EVP_PKEY *)PEM_ASN1_read((char *(*)())d2i_PrivateKey, PEM_STRING_EVP_PKEY,
fp, buff, NULL, NULL);
fclose (fp);
if (pkey == NULL) ERR_print_errors_fp(stderr);
return pkey;
}
/***
* Main program entry
*/
int main(int argc, char * argv[]) {
unsigned char receipt1[512], receipt2[512];
const char * buffer = "Ceci est un message a encrypter.";
const char * privKeyFile = "private.key";
const char * pubKeyFile = "public.crt";
EVP_PKEY * pubKey = NULL, * privKey = NULL;
int enc_len = 0, dec_len = 0, i, check = 0;
clock_t start, end, start_enc, end_enc, start_dec, end_dec;
double elapsed = 0.0, elaps_enc = 0.0, elaps_dec = 0.0;
unsigned long cumul_enc = 0L, cumul_dec = 0L;
/* Start memory check */
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
/* Init of error messages */
ERR_load_crypto_strings();
/* Reads private key from file */
privKey = ReadPrivateKey(privKeyFile);
if (!privKey) {
fprintf(stderr, "Cannot load private key in %s\n", privKeyFile);
exit(-1);
}
/* Reads public key */
pubKey = ReadPublicKeyInCert(pubKeyFile);
if (!pubKey) {
EVP_PKEY_free(privKey);
fprintf(stderr, "Cannot load public key in %s\n", pubKeyFile);
exit(-1);
}
memset(receipt1, '\0', sizeof(receipt1));
memset(receipt2, '\0', sizeof(receipt2));
printf("Original message length: %d\n", strlen(buffer));
printf("Original message: %s\n", buffer);
/* CPU test */
start = clock();
for (i = 0; i < NUM_ITERATIONS; i++) {
/* Encryption of original text */
start_enc = clock();
enc_len = RSA_public_encrypt(strlen(buffer), (unsigned char *)buffer, receipt1,
pubKey->pkey.rsa, RSA_PKCS1_PADDING);
if (enc_len != EVP_PKEY_size(pubKey)) {
fprintf(stderr, "Error: ciphertext should match length of key\n");
exit(-1);
}
end_enc = clock();
cumul_enc += end_enc - start_enc;
/* Decryption of a crypted message */
start_dec = clock();
dec_len = RSA_private_decrypt(strlen(receipt1), receipt1, receipt2,
privKey->pkey.rsa, RSA_PKCS1_PADDING);
end_dec = clock();
cumul_dec += end_dec - start_dec;
}
end = clock();
/* Performance Stats */
elapsed = ((double) (end - start)) / CLOCKS_PER_SEC;
elaps_enc = (double)cumul_enc / CLOCKS_PER_SEC;
elaps_dec = (double)cumul_dec / CLOCKS_PER_SEC;
printf("Re-decrypted message length: %d\n", strlen(receipt2));
printf("Decrypted message: %s\n", receipt2);
printf("CPU time for 10000 crypt/decrypt iterations: %f seconds.\n", elapsed);
printf("Crypt method: %.2f seconds, %.2f%% of CPU time.\n", elaps_enc, elaps_enc / elapsed * 100.0);
printf("Decrypt method: %.2f seconds, %.2f%% of CPU time.\n", elaps_dec, elaps_dec / elapsed * 100.0);
printf("---------------------\n");
printf("Total: %.2f crypt/decrypt per second.\n", 10000.0 / elapsed);
/* End of memory survey */
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF);
/* Free of allocated resources */
EVP_PKEY_free(privKey);
EVP_PKEY_free(pubKey);
return 0;
}