I have been tasked with replacing a legacy java system with something which runs PHP.
I am getting a little stuck on replacing the java cryptography with PHP code.
You can use hash_pbkdf2 PHP (5.5) function too instead of using PBKDF2 PHP libraries.
According to PHP docs the GUESS 1 is the length of the created derived key
length
The length of the output string. If raw_output is TRUE this corresponds to the byte-length of the derived key, if raw_output is FALSE this corresponds to twice the byte-length of the derived key (as every byte of the key is returned as two hexits).
If 0 is passed, the entire output of the supplied algorithm is used.
Maybe this post (what is an optimal Hash size in bytes?) result interesting for you.
GUESS 2 or IV is a random initialization vector used to create an unique salt to generate the hash.
You can create the IV with mycript_create_iv function.
Take a look at the complete sample in PHP.net
<?php
$password = "password";
$iterations = 1000;
// Generate a random IV using mcrypt_create_iv(),
// openssl_random_pseudo_bytes() or another suitable source of randomness
$salt = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM);
$hash = hash_pbkdf2("sha256", $password, $salt, $iterations, 20);
echo $hash;
?>
Both existing answers helped, but I'll post the complete solution here.
I have not seen it documented anywhere but after looking at implementations for this encryption scheme I found the key is the first 8 bytes of the encrypted hash and the IV is the last 8.
public function get_key_and_iv($key, $salt, $reps) {
$hash = $key . $salt;
for ($i = 0; $i< $reps; $i++) {
$hash = md5($hash, TRUE);
}
return str_split($hash,8);
}
seems to do the trick. Which replaces pbkdf2 in my question, negates the need for <GUESS 1>
and gives a value for <GUESS 2>
Then I got caught with the padding problem which James Black mentioned and managed to fix. So final code is
list($hashed_key, $iv) = get_key_and_iv($key, $salt, $reps);
// 8 is DES block size.
$pad = 8 - (strlen($plaintext) % 8);
$padded_string = $plaintext . str_repeat(chr($pad), $pad);
return mcrypt_encrypt(MCRYPT_DES, $hashed_key, $padded_string, MCRYPT_MODE_CBC, $iv);
You may want to look at http://us3.php.net/manual/en/ref.mcrypt.php#69782, but basically he implemented a DIY padding solution:
function pkcs5_pad ($text, $blocksize)
{
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
That may be your best bet, but if you look at this comment, his suggestions on how to verify that each step is correct may be useful for you.
https://stackoverflow.com/a/10201034/67566
Ideally you should move away from DES and since this padding is going to be a problem in PHP, why not see if you can change the encryption algorithm to something less troublesome and more secure?
To help you can show this page: http://www.ietf.org/rfc/rfc4772.txt, where it is succinctly expressed that DES is susceptible to brute force attacks, so has been deprecated and replaced with AES.