Replacing JAVA with PHP for PKCS5 encryption

烈酒焚心 提交于 2021-02-06 11:24:24

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!