我的任务是用运行PHP的东西替换遗留的java系统。
我有点拘泥于用PHP代码替换java密码。
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"));
似乎是Java 的核心
在PHP中,我正在做
$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来自这里。
所以<GUESS 1>
是密钥大小,<GUESS 2>
是IV。有人对这样的价值观有建议吗?据我所知,加密本身应该是可移植的,但我不确定一些Java方法中发生了什么。
看起来java在某个地方创建了一个IV,但我不知道如何创建,也不知道在哪里创建。
相关
解密(使用PHP)Java加密(PBEWithMD5AndDES)
您可能需要查看http://us3.php.net/manual/en/ref.mcrypt.php#69782,但基本上他实现了一个DIY填充解决方案:
function pkcs5_pad ($text, $blocksize)
{
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
这可能是你最好的选择,但如果你看看这条评论,他关于如何验证每一步都是正确的建议可能对你有用。
https://stackoverflow.com/a/10201034/67566
理想情况下,你应该远离DES,既然这种填充在PHP中会成为一个问题,为什么不看看你是否可以将加密算法更改为不那么麻烦、更安全的算法呢?
要帮助您显示此页面,请执行以下操作:http://www.ietf.org/rfc/rfc4772.txt,其中简洁地表示DES易受暴力攻击,因此已被弃用,并被AES取代。
现有的两个答案都有帮助,但我将在这里发布完整的解决方案。
我在任何地方都没有看到它的文档,但在查看了这个加密方案的实现后,我发现密钥是加密哈希的前8个字节,IV是最后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);
}
似乎奏效了。它取代了我问题中的pbkdf2,否定了对<GUESS 1>
的需求,并给出了<GUESS 2>
的值
然后我遇到了詹姆斯·布莱克提到的填充问题,并设法解决了这个问题。所以最后的代码是
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);
您也可以使用hash_pbkdf2 PHP(5.5)函数,而不是使用pbkdf2 PHP库。
根据PHP文档,GUESS 1是创建的派生密钥的长度
长度
输出字符串的长度。如果raw_output为TRUE,则对应于派生密钥的字节长度,如果raw_output为FALSE这相当于派生密钥字节长度的两倍(如密钥的每个字节都作为两个十六进制返回)。
如果传递了0,则使用所提供算法的全部输出。
也许这篇文章(以字节为单位的最佳哈希大小是多少?)的结果对你来说很有趣。
GUESS 2或IV是用于创建唯一salt以生成散列的随机初始化向量。
您可以使用mycript_create_IV函数创建IV。
查看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;
?>