如何把以下 java AES-128-CBC 加密方法改为 php 的实现

2016-06-14 13:58:15 +08:00
 timsims

第三方 API 需要用到的加密,他们就一个 java demo ,需要自己改为 php 来实现,但我试了好久都没办法得到相同的结果

Java 的源码

public static String encrypt(String input, String key){
    byte[] crypted = null;

    SecretKeySpec skey = new SecretKeySpec(getHash("MD5", key), "AES");
    IvParameterSpec iv = new IvParameterSpec(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, skey, iv);
    crypted = cipher.doFinal(input.getBytes());
    return new String(Base64.encodeBase64(crypted));
}

 private static byte[] getHash(String algorithm, String text) {
    try {
        byte[] bytes = text.getBytes("UTF-8");
        final MessageDigest digest = MessageDigest.getInstance(algorithm);
        digest.update(bytes);
        return digest.digest();
    } catch (final Exception ex) {
        throw new RuntimeException(ex.getMessage());
    }
}

我自己做 PHP 的实现

public static function encrypt($input, $key) {

    $key = hash('md5', $key, true);
    $iv = '0000000000000000';
    return openssl_encrypt($input, 'aes-128-cbc', $key, 0, $iv);
}

结果

key:"790757e76c8942f995675b247aa57c2a"
input:"1234"

result in java:UfczMtIAm8ewSuIGRdPTDQ==
result in PHP:wd/OTHoIXwgHGDHcj8OTgg== 

如果换成把 cipher 方法换成 ECB 结果就相同了。。

我还试过 mcrypt_genericmcrypt_encrypt 这两种实现,但结果和 openssl_encrypt 一模一样

求大大指教

4761 次点击
所在节点    程序员
6 条回复
fcicq
2016-06-14 14:16:03 +08:00
php 版 iv 的 '0' 其实是 0x30 吧. 不会写字符串吗?
timsims
2016-06-14 14:24:17 +08:00
@fcicq 没看懂你的意思。。
Sunyanzi
2016-06-14 14:52:26 +08:00
$iv = str_repeat( chr( 0 ), 16 );

一楼已经说得很明白了 ... 我补一句 ... 这是个空白 IV ... 意思是使用 CBC 但不使用初始化向量 ...

这么做就把 CBC 的安全级降到和 ECB 一样了 ... 所以你在程序里直接使用 ECB 加密是正确的 ...
wzxjohn
2016-06-14 14:56:41 +08:00
@timsims 你需要理解全是 0 的字符串和全是 0 的 Byte 数组的区别。。。
timsims
2016-06-14 14:58:02 +08:00
@Sunyanzi 懂了。。。

$iv = '0000000000000000';

我是找网上的例子,他们还特意注释 ``` // iv same as java ````, 我一直以为 16 个 0 就相当于 Java 那段 new IvParameterSpec(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
liumw
2016-06-15 09:03:45 +08:00
给个参考

function AES_PKCS5_ENCRYPT($text, $key)
{
$alg = MCRYPT_RIJNDAEL_128;
$mode = MCRYPT_MODE_ECB;
$iv_size = mcrypt_get_iv_size($alg, $mode);
$block_size = mcrypt_get_block_size($alg, $mode);
$iv = mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM);
$this->iv = $iv;
$input = $this->pkcs5_pad($text, $block_size);
$crypttext = mcrypt_encrypt($alg, $key, $input, $mode, $iv);
return base64_encode($crypttext);
}

function AES_PKCS5_DECRYPT($text, $key)
{
$alg = MCRYPT_RIJNDAEL_128;
$mode = MCRYPT_MODE_ECB;
$text = base64_decode($text);
$decrypted = mcrypt_decrypt($alg, $key, $text, $mode, $this->iv);
$decrypted = $this->pkcs5_unpad($decrypted);
return $decrypted;
}


function pkcs5_pad($text, $blocksize)
{
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}

function pkcs5_unpad($text)
{
$pad = ord($text{strlen($text) - 1});
if ($pad > strlen($text)) return false;
if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false;
return substr($text, 0, -1 * $pad);
}

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/285620

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX