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
> 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
---
> 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
----
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);
?>
> 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
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