Thursday, January 24, 2008

RSA OpenSSL with Microsoft Visual C++

Hi, buddies, how long time? JE JE JE

Here I am newly with another solution.

I have been working with RSA for some time with Java, but now I wanted to work with RSA in pure C.

Well, there are several libraries to work with RSA in C, but I choose OpenSSL.

Another time I only have a Windows System to try, I’m in a customer and here there aren’t UNIX machines.

Well, I downloaded this OpenSSL version

http://www.openssl.org/source/openssl-0.9.8g.tar.gz

This package is a source code package, and you need to compile to work with it.

To compile OpenSSL on Windows with Microsoft Visual C++, you have to read the install instructions (INSTALL.W32), located in the root. You’ll need Perl, and you’ll have to configure Perl correctly to work with Visual C++, in the file INSTALL.W32 you’ll find everything what you need. But, basically you’ll have to run these instructions from the root OpenSSL path:

To configure Perl, don’t forget add the Perl bin path to your PATH environment variable:
>perl Configure VC-WIN32 --prefix=‘c:/some/openssl/dir ‘

If you don't want to use the assembly language files at all then run
> ms\do_ms

And finally, run the compilation:

For get OpenSSL libs, run:
> nmake -f ms\nt.mak

Or run this command to get OpenSSL dlls:
> nmake -f ms\ntdll.mak

If you want to generate the libs or dlls with debugger information, you’ll need to edit do_nt.bat or do_ntdll.bat, to add debug option to the command line in these lines:

perl util\mk1mf.pl no-asm debug VC-NT>ms\nt.mak
perl util\mk1mf.pl dll no-asm debug VC-NT>ms\ntdll.mak

These bats build the makes with DEBUG option; you’ll have to execute the nmake -f ms\nt.mak newly to get the new libraries.

Maybe you’ll need unicows.lib for this last compilation.
If you don’t have it into your PC, it’s here.
http://surfnet.dl.sourceforge.net/sourceforge/libunicows/libunicows-1.1.1-msvc6.zip

Well, after the compilation you’ll get some exes and two dlls or libs, it depends if you compile nt.mak (libs) or ntdlls.mak (dlls), the output directory name begins with out32.

Well, here is a sample source code that shows how to read private and public keys from files (private key file is encrypted), retrieving the keys, encrypting and decrypting.

The bold lines are important, they showed the problems that I found


#include <stdio.h>
#include <string.h>
#include "e_os.h"
#include <openssl\crypto.h>
#include <openssl\err.h>
#include <openssl\rand.h>
#include <openssl\bn.h>
#include "applink.c"
#include "pem.h"
#include <openssl\rsa.h>

// Callback for login information
int pass_cb(char *buf, int size, int rwflag, void *password)
{
strncpy(buf, "carlos", size);
buf[size - 1] = '\0';
return(strlen(buf));
}


int main(int argc, char *argv[])
{

RSA *rsaPrivKey = RSA_new();
RSA *rsaPubKey = RSA_new();
unsigned char inText[256];
FILE *pubKey = NULL;
FILE *privKey = NULL;
unsigned char sigBuffer[256];
int size;
unsigned char plainText[256];
int encSize;
char pass[7]="carlos\n";

// OpenSSL Init
_fmode=_O_BINARY;
CRYPTO_malloc_init();
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
ENGINE_load_builtin_engines();

// End OpenSSL Init

// Opening Files generated with openSSL
pubKey=fopen("J:\\public.key", "r");
// Private Key file, encrypted with 3DESC
privKey=fopen("J:\\priv.key", "r");

// Reading Keys
if(privKey){
    rsaPrivKey = PEM_read_RSAPrivateKey(privKey, &rsaPrivKey,
        (pem_password_cb *)pass_cb, pass);
}
ERR_print_errors_fp(stdout);
if(pubKey)
{
    rsaPubKey = PEM_read_RSA_PUBKEY(pubKey, &rsaPubKey,
        NULL, NULL);
}

// Encrypting
strcpy(inText,"Carlos");
printf("String to encrypting: %s\n", inText );
size = strlen((char*)inText);
encSize=RSA_public_encrypt(size, inText,
sigBuffer, rsaPubKey, RSA_PKCS1_OAEP_PADDING);

// Decrypting
printf("encrypted string size: %d\n" ,encSize );
encSize=RSA_private_decrypt(encSize, sigBuffer, plainText,
rsaPrivKey, RSA_PKCS1_OAEP_PADDING);
memset(plainText+encSize,0,sizeof(plainText)-encSize);
printf("ret %s\n",plainText);
ERR_print_errors_fp(stdout);
printf("Decrypting result: %s\n", plainText );

// Free keys
RSA_free(rsaPubKey);
RSA_free(rsaPrivKey);

// unload OpenSSL
CRYPTO_cleanup_all_ex_data();
ERR_remove_state(0);

CRYPTO_mem_leaks_fp(stderr);

return 0;
}

Here is the Visual C++ Project
Source Files