While working on a major enhancement to my open-source Take Control module for Drupal (to be released soon), I needed to generate public/private keys for making secure asynchronous Ajax calls.

A quick Google search revealed that PHP’s Open SSL package should do the job. Some reading of Open SSL docs, and a quick overview of my development machine’s phpinfo() output revealed I already had Open SSL setup, and enabled on my local Apache web-server.

So, I sat down to do the actual coding. Remember, I just needed to generate public/private key pairs without any need of moving my development machine to use SSL/TLS. The entry point into PHP’s Open SSL package for my task was openssl_pkey_new() method. I was doing everything as mentioned by the docs, but still, everytime this method returned null.

After considerable head-butting, and hair pulling, which involved things like playing with the openssl’s ssleay32.dll and libeay32.dll libraries, PHP environment variables related to Open SSL, the location and contents of the all important openssl.cnf file, the command-line openssl.exe utility, generating & installing CSR certificates, playing with the configargs arguments, I got nothing going. Everytime, openssl_pkey_new() returned null.

What I was not sure was what exactly was going wrong? Are the required dll’s not available at appropriate position, is openssl.cnf file not being proprley found, or are its contents incorrect?

Just when I was going to give it up for the time-being, I hit some forum post somewhere, that told me how to specify openssl.cnf location in configargs. Sadly enough, PHP’s Open SSL documentation here, also mentions that you can do this, however neither this page, nor this one, tells you how to specify this in configargs. And it is as simple as passing the ‘config’ argument in configargs to openssl_pkey_new().

As soon as I did this, I hit the jackpot. I could generate the keys without any issue. So, here’s my code that I use to generate these keys:

 

{syntaxhighlighter brush: php;fontsize: 100; first-line: 1; }function take_control_new_keys($algo, $passphrase) {
$keys = array();

$configargs = array(
‘digest_alg’ => $algo,
‘config’ => drupal_get_path(‘module’, ‘take_control’) . ‘/openssl.cnf’);

// Create the keypair
$res = openssl_pkey_new($configargs);

// Get private key. A pass phrase is required for proper encryption/decryption.
openssl_pkey_export($res, $privkey, $passphrase, $configargs);

// Get public key
$pubkey = openssl_pkey_get_details($res);
$pubkey = $pubkey[‘key’];

$keys[‘priv’] = $privkey;
$keys[‘pub’] = $pubkey;

return ($keys);
}{/syntaxhighlighter}

As I said, because I am using Drupal, the path is specified using Drupal mechanisms. You can easily change this to what suits you.

Further, the encryption and decryption methods that use the above generated keys are as follows:

 

{syntaxhighlighter brush: as3;fontsize: 100; first-line: 1; }function take_control_encrypt_data($data) {
$pubkey = variable_get(‘take_control_public_key’);
$success = openssl_seal($data, $sealed, $envkey, array($pubkey));
return (array(‘encrypted’ => $sealed, ‘envkey’ => $envkey));
}

function take_control_decrypt_data($encrypted, $envkey) {
$prikey = variable_get(‘take_control_private_key’);
$passphrase = variable_get(‘take_control_pass_phrase’);

$prikey = openssl_pkey_get_private($prikey, $passphrase);

$success = openssl_open($encrypted, $decrypted, $envkey, $prikey);

return ($decrypted);
}{/syntaxhighlighter}

The above code would be publicly released soon with the upcoming enhancement to the Take Control module.

By the way, while researching for a solution to my problem, I found lots of links on how to get SSL/TLS going on Apache/IIS in Windows. Here are some of them, just in case you are looking for them:

http://tud.at/programm/apache-ssl-win32-howto.php3
http://raibledesigns.com/wiki/Wiki.jsp?page=ApacheSSL
http://www.neilstuff.com/apache/apache2-ssl-windows.htm

You can also find a sample openssl.cnf file attached below. Believe it or not, this is the same file that is available from many sources, and it worked perfectly for me without needing to make any changes to it. But also remember, I was just generating key pairs, not certificates. If you are generating certificates, you should probably modify this file appropriately.