问题
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.
cipherAlgorythm = "PBEWithMD5AndDES";
cipherTransformation = "PBEWithMD5AndDES/CBC/PKCS5Padding";
PBEParameterSpec ps = new javax.crypto.spec.PBEParameterSpec(salt, iterations);
SecretKeyFactory kf = SecretKeyFactory.getInstance(cipherAlgorythm);
SecretKey key = kf.generateSecret(new javax.crypto.spec.PBEKeySpec(password.toCharArray()));
Cipher encryptCipher = Cipher.getInstance(cipherTransformation);
encryptCipher.init(Cipher.ENCRYPT_MODE, key, ps);
byte[] output = encryptCipher.doFinal("This is a test string".getBytes("UTF-8"));
Seems to be the guts of the Java
In PHP I am doing
$hashed_key = pbkdf2('md5', $this->key, $this->salt, $this->reps , <GUESS 1>, TRUE);
$output = mcrypt_encrypt(MCRYPT_DES, $hashed_key, "This is a test string", MCRYPT_MODE_CBC, <GUESS 2>);
pbkdf2 is from here.
So <GUESS 1>
is the key size and <GUESS 2>
is the IV. I have played around with these to no avail. Does anyone have suggestion for such values? As far as I can see the encryption itself should be portable but I am unsure about what is going on in some of the Java methods.
It looks like java is creating an IV somewhere, but I don't understand how or where.
RELATED
Decrypt ( with PHP ) a Java encryption ( PBEWithMD5AndDES )
回答1:
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.
回答2:
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);
回答3:
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;
?>
来源:https://stackoverflow.com/questions/20639575/replacing-java-with-php-for-pkcs5-encryption