With this blog post I release an object-oriented PHP implementation of the RSA public key algorithm. The implementation is based on Edsko de Vries’ non-object-oriented implementation. Additionally to the object-orientation I reimplemented the signature methods which are now based on encrypted hashes instead of encrypting the whole message. This post shows you how to use this cryptographic PHP module, called rsa4php, and where to download it. Feel free to use it in your own programs under the terms of the GNU General Public Licence (GPL).

### Get rsa4php

You can download the RSA distribution, called rsa4php, from files.oliver-mueller.com/pub/rsa4php as ZIP file and as tarball.

The licensing information you find inside the ZIP file and the tarball respectively as file `gpl-2.0.txt`

or alternatively at these sites:

http://www.gnu.org/licenses/gpl-2.0.txt

http://oliver-mueller.com/files/gpl-2.0.txt

### Generating Keys

The RSA module does not contain any key generating functions yet (and maybe never will). To generate a key pair you can use OpenSSL. It is very easy with the Unix shell script `genkey.sh`

which is part of my rsa4php distribution.

This script expects the key length in bits as argument. To generate a RSA key pair with a key length of 2048 bits simply execute this command on your shell:

`./genkey.sh 2048`

This will create a file `keyconf.php`

which contains the key parameters. The content of such a file looks like this:

```
$ cat keyconf.php
<?php
$nx = "009d47d39934b6e1fc2e0e0e8b99c45f3e1736b817372df842f96f11c643e47e7065e7886b2399edfd04f74e71bdcc1dcc26a3bc96355b2ec510c19d4810e006d2460d7a2d33d0ef7e619b93d169d786fa0f26a0c22a46febbb944e6a5ce85810e468790dd576811cc7da02f572c7b499c457b863d49272057106d8b3afa3fcd71679c06619b97c666f01096a317de08c0cbb7330195b1a5276a8e317ce6d7c45ab12cd45b295f1e97c8603bbea91d21df516b3a8dd0d15a59a9adbf9e025879f5059a93950c8dd9926323e42c4a35fb1e6a48efc6ca3d8158184cfe60b56edc281abc37e975b0659ee71a7f8a3bb4211fc218257103d6e448dfd6bd178cdea999";
$ex = "010001";
$dx = "6dc7077324ef0d36c6327b8686d220a426f1c37638c67644d0f2ec56156733b561fb44257bd8e1dabb8f9e0a17ae9391bdda8533d6940945f5171e9f815fcc8311f03039c2b3efa5a79d3e84693accf45684e0aa05763e306af52383d16d2f91f63a832b6ae9b19aa88898e260a2c0d339502977374afef0a5ffbfb16f9ffed5335f5f400ca38576a171d01f5ce04a1896d3d66db7adf9561533bacfa74fa74c1982646b0aaccd4e21db19c451a826e8f00ad81728e10c5ac30d72593baba598e41d1c0bf2c57cb1172aaf9f7cd23f88344ddf686f17d4f725d8565cefa481af28a94c51215b73534942978c8fe0fc13f5f8c29540ba33d47d86904abcfd7a";
$lx = 2048;
?>
```

These four variables define a valid RSA public key pair. Variable `nx`

contains the modulus, `ex`

the public exponent, and `dx`

the private exponent. Last but not least variable `lx`

tells the key’s length in bits.

### Creating an RSA Object

Based on the variables created by `genkey.sh`

you can create an RSA object. On a system providing 5.4 or later you can directly create the RSA object as follows:

`$mykey = new RSA(hex2bin($ex), hex2bin($dx), hex2bin($nx), $lx);`

If you are using an earlier PHP 5.x release you will have to use the following function to convert the hexadecimal strings to binary data:

```
function hex2bin($hex_str) {
$bin = '';
for($i = 0; $i < strlen($hex_str); $i+=2)
$bin .= chr(hexdec($hex_str[$i] . $hex_str[$i+1]));
return $bin;
}
```

With this function you can use exactly the same syntax as on PHP 5.4 and later where `hex2bin()`

is available by default.

If you want to create an RSA object representing a public key only, you will have to set the private exponent to `"00"`

:

`$mypubkey = new RSA(hex2bin($ex), "00", hex2bin($nx), $lx);`

*Note: This is a simple workaround. Do not try to decrypt or sign messages with such a public-key-only object! It won’t work, of course, and the module will simply calculate rubbish without throwing some error indicating this special situation!*

### Encrypting and Decrypting Messages

Encrypting a message is very simple. You call the method `encrypt()`

of your RSA object with the message to be encrypted as parameter:

`$cipher = $mykey->encrypt("Hello, world!");`

To decrypt a cipher text to retrieve the plaintext again:

`$plaintext = $mykey->decrypt($cipher);`

### Signing Messages and Verification of Signatures

Signing a message is an expensive operation if you use the whole message as input for signing. Therefore it is common to calculate a hash of the message and encrypt this hash with the private key. The resulting cryptogram is used as digital signature.

All these operations – calculating the hash and encrypting it – is done by method `sign()`

. This is a major change to the original implementation by Edsko de Vries. rsa4php’s method `sign()`

expects two parameters – the message to sign and a hashing algorithm.

The name of the hash algorithm is a string like `"sha1"`

, `"sha256"`

or `"`

`snefru256`

`"`

. A complete list of supported hash algorithm returns the PHP function `hash_algos()`

.

To sign a message use a call like this:

`$signature = $mykey->sign($message, "sha256");`

The following statement verifies a signature:

`$match = $key->verify($message, $signature, "sha256");`

`$match`

is a Boolean value indicating whether the signature matches (value `true`

) the message or not (`false`

).

How does this compare to phpseclib’s Crypt_RSA?:

http://phpseclib.sourceforge.net/rsa/intro.html

The RSA implementation of phpseclib is a full-featured cryptographic library. It supports several key formats such as PuTTY ssh keys, OpenSSH keys, and PKCS certificates. It also integrates well into different application scenarios.

The PHP module, which I released, is a simple small and lightweight implementation. I had demand for it in the context of a proof of concept and an essay about it. Caused by the fact that this module bases upon a free software implementation I gave my modifications back to the community–following the open-source idea.

If you ask about comparisons of the two implementations regarding performance or security issues I will have to confess I did not compare the two implementations (yet).

Thanks for all your efforts that you have put in this. Very interesting info. “Knowledge of what is possible is the beginning of happiness.” by George Santayana.

Nice work, but (there is always a ‘but’) why don’t you use base_convert($key, 16, 10) instead of first using hex2bin($key) and then using binary_to_number($key)?

Forgett my last comment…. I tried it and it does’nt work for big numbers… sorry 🙂

Yes, indeed. base_convert() works for “normal” integers only. Big integers make life always a bit harder… 🙂