Sunday, June 7, 2015

Public Key Cryptography in PHP

When we are dealing with Java, when it comes to cryptography the most basic thing that we come across is the 'keystore'. It's a kind of key database that save and manage SecretKey, Public/Private Key Pair, and certificates. It's simply a password protected file.
When it comes to PHP, I couldn't find such 'keystore' concept used for Key Management. Instead what I found was the OpenSSL PHP extension [1] that supports the standard OpenSSL cryptography toolkit [2] and some other libraries that tries to reinvent the wheel.

However, referring the OpenSSL PHP extension manual and surfing the web confirmed that it's fairly easy to use this extension to secure a system. Let's take one example and explore the extension for a bit.

Lets' look at an Asymmetric Encryption scenario. So we will need a private key and a public key, where the private key is a secret and the public key can be given to anyone who want to communicate with us. A person who want to send us some data securely will encrypt with our public key, so only we will be able to decrypt it with our private key.

So first we need to generate the public and private key. This can be done either by using the openssl command line tool or the extension. Make sure to password protect the file or the string you generate giving the passphrase in the extension or via commandline tool. Otherwise the private key is not encrypted and it is completely unprotected.
In the tool you can specify the passphrase with argument -passout

Using command line tool:


openssl genrsa -des3 -passout pass:password -out private.pem  1024

This will generate a 1024 bit rsa private key, which is password protected by password 'password'.

However, here the passphrase could be grabbed by any other malicious process, since command line arguments are generally visible to all processes.
A better option would be to write passphrase to a file with protected permissions and use that,


openssl genrsa -des3 -passout file:passphrase.txt -out private.pem  1024

or provide it in standard input.


openssl genrsa -des3 -passout stdin -out private.pem  1024

Using PHP OpenSSL extension:


$passphrase = "password";
$privateKey = openssl_pkey_new(array(
 'private_key_bits' => 1024,
 'private_key_type' => OPENSSL_KEYTYPE_RSA,
));
openssl_pkey_export_to_file($privateKey, '/path/to/privatekey', $passphrase);
 
// get the public key $keyDetails['key'] from the private key;
$keyDetails = openssl_pkey_get_details($privateKey);
file_put_contents('/path/to/publickey', $keyDetails['key']);
 

Then we can load the public key and encrypt data as below.


$pubKey = openssl_pkey_get_public('file:///path/to/publickey');
openssl_public_encrypt($plainText, $encryptedText, $pubKey);

From the private key we can decrypt the encrypted data and get the plain text again.


$privateKey = openssl_pkey_get_private('file:///path/to/privatekey', $passphrase);
openssl_private_decrypt($encryptedText, $plainText, $privateKey);

Likewise we can use PHP OpenSSL extension to sign or seal as well. Please refer the documentation [1] for more details and you can also find a bunch of examples contributed by users also.

[1] http://php.net/manual/en/book.openssl.php
[2] https://www.openssl.org/docs/apps/openssl.html

No comments:

Post a Comment