Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Blowfish in Delphi/PHP

1,392 views
Skip to first unread message

Lawrence

unread,
Nov 30, 2004, 2:52:12 PM11/30/04
to

I'm using Dave Barton's DCPcrypt Cryptographic Component Library
( http://www.cityinthesky.co.uk/delphi.html ) to encrypt a string of information in Delphi, then I use Indy to post it to a PHP script using the mcrypt library.

The first step, I wanted to verify that I get the same encrypted string from both implementations given the same input params. The outputs of both never match, regardless of how simple my inputs are.

How can I get the 2 to play nice?

Thanks,
Lawrence

danny heijl

unread,
Dec 1, 2004, 2:42:43 AM12/1/04
to
Lawrence wrote:

> The first step, I wanted to verify that I get the same encrypted string from both implementations given the same input params. The outputs of both never match, regardless of how simple my inputs are.

Do they use the same IV (Intialization Vector) ?

Danny
---

"Henrick Hellström [StreamSec]"

unread,
Dec 1, 2004, 8:50:51 AM12/1/04
to
Lawrence wrote:

> The first step, I wanted to verify that I get the same encrypted
> string from both implementations given the same input params. The
> outputs of both never match, regardless of how simple my inputs are.

There are three things to consider:

1. You must use the same algorithm. Even the slightest bug in either
will render the two implementations incompatible.

2. You must use the same key. This means three things:
2.1. If you use password, make sure you use the same encoding (ANSI?
UTF-8? Unicode-16? Unicode-16 Big Endian? Null terminated?)
2.2. If you use raw keys, make sure they are encoded and decoded
properly (ASCII? Hexadecimal? Base64?)
2.3. If you use a KDF (and IIRC DCPCrypt does), make sure you use
exactly the same.

3. Use the same Block Cipher Mode. If you use one that takes an IV, make
sure you use the same IV. If you use one with a Mode Ratio (for example
CFB-8 which IIRC is CFB in DCPCrypt), make sure you use the same ratio.

4. Use the same Block Padding.


--
Henrick Hellström
www.streamsec.com

Jhon

unread,
Dec 1, 2004, 9:36:46 PM12/1/04
to
You could try to use mcrypt for windows.

Jhon
----


Lawrence

unread,
Dec 2, 2004, 5:00:33 PM12/2/04
to

Below is my test php script and Delphi code. DCP_blowfish1.EncryptString seems to always default to cmCFB8bit, but I don't know what the mcrypt equivalent is, so I modified EncryptsString to use whatever mode that was selected. EncryptString also does a Base64Encode on the results before returning. The php script is based on an example I saw on php.net. The Delphi code is based on the FileEncrypt demo app for DCPCrypt.

Results of Delphi test app: h0QwjnZsEpugR7Ap
Results of php test script: lTQ2KnxNpvll9x9qTRd+zA==

My mistake must be something obvious, but I can't see it.

Lawrence

procedure TfrmMain.btnEncryptClick(Sender: TObject);
var
CipherIV: array[0..7] of byte; // the initialisation vector (for chaining modes)
HashDigest: array of byte; // the result of hashing the passphrase
i: integer;
const IV = ')Tw?ÓG{&';
begin
try
SetLength(HashDigest,DCP_md51.HashSize div 8);
DCP_md51.Init;
DCP_md51.UpdateStr('1234'); // hash the passphrase
DCP_md51.Final(HashDigest[0]); // store the output in HashDigest

for i := 0 to (Length(CipherIV) - 1) do
CipherIV[i] := Ord(IV[i]); // again just random values for the IV
DCP_blowfish1.Init(HashDigest[0],DCP_md51.HashSize,@CipherIV); // initialise the cipher with the hash as key
DCP_blowfish1.CipherMode := cmCBC; // use CBC chaining when encrypting

Encrypted.Text := DCP_blowfish1.EncryptString('Hello world!');

DCP_blowfish1.Burn; // important! get rid of keying information
except
end;
end;

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

<?php

$str = "Hello world!";

/* Open the cipher */
$td = mcrypt_module_open('blowfish', '', 'cbc', '');

/* Create the IV
$iv = ")Tw?ÓG{&";

/* Create key */
$str_key = "1234";
$key = md5($str_key);

/* Intialize encryption */
mcrypt_generic_init($td, $key, $iv);

/* Encrypt data */
$encrypted = base64_encode(mcrypt_generic($td, $str));

echo $encrypted."<br>\n";//

/* Terminate encryption handler and close module */
mcrypt_generic_deinit($td);
mcrypt_module_close($td);

?>

"Henrick Hellström [StreamSec]"

unread,
Dec 3, 2004, 2:54:09 AM12/3/04
to
Lawrence wrote:

> procedure TfrmMain.btnEncryptClick(Sender: TObject);
> var
> CipherIV: array[0..7] of byte; // the initialisation vector (for chaining modes)
> HashDigest: array of byte; // the result of hashing the passphrase
> i: integer;
> const IV = ')Tw?ÓG{&';

A constant is NOT random. If your production code looks like this you
might be in serious trouble.


> begin
> try
> SetLength(HashDigest,DCP_md51.HashSize div 8);
> DCP_md51.Init;
> DCP_md51.UpdateStr('1234'); // hash the passphrase
> DCP_md51.Final(HashDigest[0]); // store the output in HashDigest
>
> for i := 0 to (Length(CipherIV) - 1) do
> CipherIV[i] := Ord(IV[i]); // again just random values for the IV

First problem: IV is a string and the ')' is at index 1; not 0.

> DCP_blowfish1.Init(HashDigest[0],DCP_md51.HashSize,@CipherIV); // initialise the cipher with the hash as key
> DCP_blowfish1.CipherMode := cmCBC; // use CBC chaining when encrypting
>
> Encrypted.Text := DCP_blowfish1.EncryptString('Hello world!');

Second problem: DCP will not perform padding for CBC mode encryption,
but PHP will.

> DCP_blowfish1.Burn; // important! get rid of keying information
> except
> end;
> end;
>
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> <?php
>
> $str = "Hello world!";
>
> /* Open the cipher */
> $td = mcrypt_module_open('blowfish', '', 'cbc', '');
>
> /* Create the IV
> $iv = ")Tw?ÓG{&";
>
> /* Create key */
> $str_key = "1234";
> $key = md5($str_key);
>
> /* Intialize encryption */
> mcrypt_generic_init($td, $key, $iv);
>
> /* Encrypt data */
> $encrypted = base64_encode(mcrypt_generic($td, $str));
>
> echo $encrypted."<br>\n";//
>
> /* Terminate encryption handler and close module */
> mcrypt_generic_deinit($td);
> mcrypt_module_close($td);
>
> ?>


--
Henrick Hellström
www.streamsec.com

"Henrick Hellström [StreamSec]"

unread,
Dec 3, 2004, 4:13:57 AM12/3/04
to
Lawrence wrote:
> /* Open the cipher */
> $td = mcrypt_module_open('blowfish', '', 'cbc', '');

MCRYPT had a bug in its blowfish implementation for a very long time.
Make sure your mcrypt module is up to date and *not* compiled in
"compatibility" mode (i.e. compatible with the old bug) or with byteswap
turned off.

--
Henrick Hellström
www.streamsec.com

0 new messages