Open source software security

Using Blowfish Encryption Between PHP and Perl

30 November -0001
Justin C. Klein Keane
Jan. 14, 2008

I recently wondered if I could use a common encryption algorithm across both PHP and Perl. In this particular case I wanted to know if PHP and Perl could both utilize the Blowfish encryption algorithm to share encrypted data (with data being encrypted in one language and decrypted in another). This effort was to be part of a distributed deployment of the Cornell Spider tool. The linux version of the Cornell Spider tool creates a log file encrypted with Blowfish. The linux version sends log messages to a server program after they are encrypted. This server program decrypts the messages and writes them to a log file. I wanted to modify the server program so that it wrote the encrypted log messages into a database, then create a PHP program that would display the log messages online over HTTPS after authenticated users supplied the password to decrypt the log message. So Perl would be encrypting a string with Blowfish using a key and PHP would decrypt the string using Blowfish and the same symmetric encryption key. However, before I started I needed to test and ensure that both PHP and Perl would handle Blowfish in identical ways to make the handling of data feasible across the two languages.

To start the test I simply encrypted a string using Perl. Perl uses the Crypt::CBC module to enable Blowfish encryption algorithm functionality. There were a couple of caveats. For instance, the encryption key had to be exactly 56 bytes in order for this to work. I also needed to arbitrarily set the input vector ($iv). Normally this is a randomly generated 8-bit string but since PHP and Perl will generate independent input vectors (or salts) this had to be standardized between the two. This simple Perl program should out put the results of Blowfish encryption/decryption:

#!/usr/bin/perl
use Crypt::CBC;

for ($i=0;$i<56;$i++) {$key .= '1';}
$cipher = Crypt::CBC->new( {'key' => $key,
        'cipher'=> 'Blowfish',
        'iv' => '12345678',
        'regenerate_key' => 0,
        'padding' => 'null',
        'prepend_iv' => 0
 });

$ciphertext = $cipher->encrypt("String to encrypt.");
$plaintext = $cipher->decrypt($ciphertext);

open (CFILE, '>/var/www/html/crypt.txt');
print CFILE $ciphertext;
close (CFILE);

When run it writes an encrypted string into the file at the web root directory. Now on to testing the PHP implementation to see if it can decrypt the test text.

We need to use the mcrypt libraries for PHP. The following script should take our test text and decipher it. Note that the rtrim() is necessary since we're using an 8-bit block cipher and there will be null bits appended to our decrypted string which will show up as question marks in HTML display. Using the following PHP code snippit we can open up the encrypted text file and decrypt the contents:

<?php
$key = '';
for ($i=0;$i<56;$i++) $key .= '1';

$fh = fopen('crypt.txt', 'r');
$ciphertext = fread($fh, 1024);
fclose($fh);

print "<h2>Ciphertext</h2>" . $ciphertext;

$output = rtrim(mcrypt_cbc(MCRYPT_BLOWFISH, $key, $ciphertext, MCRYPT_DECRYPT, '12345678'));

print "<h2>Plaintext:</h2>";
print $output;

?>

This produces the correct output:

Ciphertext
_f3?)??/1?o??[
Plaintext:
String to encrypt.

Note that I used code samples from http://us3.php.net/manual/en/function.mcrypt-cbc.php#62873 to help get this complete.