• 请不要在回答技术问题时复制粘贴 AI 生成的内容
timsims
V2EX  ›  程序员

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

  •  
  •   timsims · Jun 14, 2016 · 5233 views
    This topic created in 3667 days ago, the information mentioned may be changed or developed.

    第三方 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 一模一样

    求大大指教

    Supplement 1  ·  Jun 14, 2016

    补充一下 mcrypt_encryptmcrypt_generic 的实现,结果都是一样的。。

    public static function encrypt($input, $key) {
    
        $key = hash('md5', $key, true);
    
    
        $iv = '0000000000000000';
    
        $size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
        $input = Security::pkcs5_pad($input, $size);
    
    
        $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $input, MCRYPT_MODE_CBC, $iv);
    
        // output wd/OTHoIXwgHGDHcj8OTgg==
        echo base64_encode($encrypted);
    
        $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
    
        mcrypt_generic_init($td, $key, $iv);
        $data = mcrypt_generic($td, $input);
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
        $data = base64_encode($data);
    
        // output wd/OTHoIXwgHGDHcj8OTgg==
        echo $data;
    }
    
    private static function pkcs5_pad ($text, $blocksize) {
        $pad = $blocksize - (strlen($text) % $blocksize);
        return $text . str_repeat(chr($pad), $pad);
    }
    
    
    6 replies    2016-06-15 09:03:45 +08:00
    fcicq
        1
    fcicq  
       Jun 14, 2016   ❤️ 1
    php 版 iv 的 '0' 其实是 0x30 吧. 不会写字符串吗?
    timsims
        2
    timsims  
    OP
       Jun 14, 2016
    @fcicq 没看懂你的意思。。
    Sunyanzi
        3
    Sunyanzi  
       Jun 14, 2016   ❤️ 2
    $iv = str_repeat( chr( 0 ), 16 );

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

    这么做就把 CBC 的安全级降到和 ECB 一样了 ... 所以你在程序里直接使用 ECB 加密是正确的 ...
    wzxjohn
        4
    wzxjohn  
       Jun 14, 2016   ❤️ 1
    @timsims 你需要理解全是 0 的字符串和全是 0 的 Byte 数组的区别。。。
    timsims
        5
    timsims  
    OP
       Jun 14, 2016
    @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
        6
    liumw  
       Jun 15, 2016
    给个参考

    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);
    }
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   915 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 35ms · UTC 20:52 · PVG 04:52 · LAX 13:52 · JFK 16:52
    ♥ Do have faith in what you're doing.