java/php對應的AES/CBC/PKCS5Padding模式 加密解密

目前一個系統(java開發的)上將加密的用戶名和密碼傳遞到另一個系統(PHP開發的),約定了java使用AES加密,php在獲得加密的用戶名和密碼後,進行解密。
java代碼:

package com.wondersgroup.common.decrypt.utils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * Created by smart on 2015/8/17.
 */
public class Encrypt {
    // 密匙
    private static String DEFAULTKEY = "你的16位祕鑰";
    // 偏移量
    private static String IVPARAMETER = "0102030405060708";

    // 加密
    public static String execute(String sSrc) throws Exception {
        if (sSrc == null) {
            return null;
        }
        return encrypt(sSrc, DEFAULTKEY);
    }

    private static String encrypt(byte[] sSrc, String sKey) throws Exception {
        if (sKey == null || sSrc == null) {
            return null;
        }
        return byte2hex(encryptByte(sSrc, sKey)).toLowerCase();
    }

    private static String encrypt(String sSrc, String sKey) throws Exception {
        if (sKey == null || sSrc == null) {
            return null;
        }
        return encrypt(sSrc.getBytes(), sKey);
    }

    private static byte[] encryptByte(byte[] sSrc, String sKey) throws Exception {
        if (sKey == null || sSrc == null) {
            return null;
        }
        // 判斷Key是否爲16位
        if (sKey.length() != 16) {
            return null;
        }
        byte[] raw = sKey.getBytes();
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        IvParameterSpec iv = new IvParameterSpec(IVPARAMETER.getBytes());
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
        return cipher.doFinal(sSrc);
    }

    private static byte[] hex2byte(String strhex) {
        if (strhex == null) {
            return null;
        }
        int l = strhex.length();
        if (l % 2 == 1) {
            return null;
        }
        byte[] b = new byte[l / 2];
        for (int i = 0; i != l / 2; i++) {
            b[i] = (byte) Integer.parseInt(strhex.substring(i * 2, i * 2 + 2), 16);
        }
        return b;
    }

    private static String byte2hex(byte[] b) {
        String hs = "";
        String stmp = "";
        for (int n = 0; n < b.length; n++) {
            stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
            if (stmp.length() == 1) {
                hs = hs + "0" + stmp;
            } else {
                hs = hs + stmp;
            }
        }
        return hs.toUpperCase();
    }

    public static void main(String[] arg) {
        try {
            System.out.println(execute("hujunyu"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

package com.wondersgroup.common.decrypt.utils;


import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * Created by smart on 2015/8/17.
 */
public class Decrypt {
    //密匙
    private static String DEFAULTKEY = "你的16位祕鑰";
    //偏移量
    private static String IVPARAMETER = "0102030405060708";

    public static String execute(String sSrc) throws Exception {
        if ( sSrc==null) {
            return null;
        }
        return decrypt(sSrc, DEFAULTKEY);
    }

    // 解密
    private static String decrypt(byte[] sSrc, String sKey) throws Exception {
        if (sKey == null || sSrc==null) {
            return null;
        }
        return new String( decryptByte( sSrc, sKey));
    }

    private static byte[] decryptByte(byte[] sSrc, String sKey) throws Exception {
        try {
            // 判斷Key是否正確
            if (sKey == null || sSrc==null) {
                return null;
            }
            // 判斷Key是否爲16位
            if (sKey.length() != 16) {
                return null;
            }
            byte[] raw = sKey.getBytes();// "ASCII"
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec iv = new IvParameterSpec(IVPARAMETER.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            try {
                return cipher.doFinal(sSrc);
            } catch (Exception e) {
                return null;
            }
        } catch (Exception ex) {
            return null;
        }
    }
    private static String decrypt(String sSrc, String sKey) throws Exception {
        if (sKey == null || sSrc==null) {
            return null;
        }
        return decrypt( hex2byte(sSrc), sKey);
    }

    private static byte[] hex2byte(String strhex) {
        if (strhex == null) {
            return null;
        }
        int l = strhex.length();
        if (l % 2 == 1) {
            return null;
        }
        byte[] b = new byte[l / 2];
        for (int i = 0; i != l / 2; i++) {
            b[i] = (byte) Integer.parseInt(strhex.substring(i * 2, i * 2 + 2), 16);
        }
        return b;
    }

    private static String byte2hex(byte[] b) {
        String hs = "";
        String stmp = "";
        for (int n = 0; n < b.length; n++) {
            stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
            if (stmp.length() == 1) {
                hs = hs + "0" + stmp;
            } else {
                hs = hs + stmp;
            }
        }
        return hs.toUpperCase();
    }

    public static void main(String[] arg) {
        try {
            System.out.println(execute("55a280077e82db68806ce77fe9602a7c"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

php代碼:

<?php

/**
 * java/php對應的AES/CBC/PKCS5Padding模式 加密解密
 */
class Crypt {

    /**
     * [$cipher 加密模式]
     * @var [type]
     */
    private $cipher = MCRYPT_RIJNDAEL_128;
    private $mode = MCRYPT_MODE_CBC;

    /**
     * [$key 密匙]
     * @var string
     */
    private $secret_key = '你的16位祕鑰';
    /**
     * [$iv 偏移量]
     * @var string
     */
    private $iv = '0102030405060708';

    function setCipher($cipher=''){
        $cipher && $this->cipher = $cipher;
    }

    function setMode($mode=''){
        $mode && $this->mode = $mode;
    }

    function setSecretKey($secret_key=''){
        $secret_key && $this->secret_key = $secret_key;
    }

    function setIv($iv=''){
        $iv && $this->iv = $iv;
    }

    //加密
    function encrypt($str)
    {       
        $size = mcrypt_get_block_size ( MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC );
        $str = $this->pkcs5Pad ( $str, $size );

        $data=mcrypt_cbc(MCRYPT_RIJNDAEL_128, $this->secret_key, $str, MCRYPT_ENCRYPT, $this->iv);

        //bin2hex() 函數把 ASCII 字符的字符串轉換爲十六進制值
        $data=strtolower(bin2hex($data));
        return $data;
    }

    //解密
    function decrypt($str)
    {
        $str = $this->hex2bin( strtolower($str));
        $str = mcrypt_cbc(MCRYPT_RIJNDAEL_128, $this->secret_key, $str, MCRYPT_DECRYPT, $this->iv );
        $str = $this->pkcs5Unpad( $str );
        return $str;
    }

    //bin2hex還原
    private function hex2bin($hexData)
    {
        $binData = "";
        for($i = 0; $i < strlen ( $hexData ); $i += 2)
        {
            $binData .= chr(hexdec(substr($hexData, $i, 2)));
        }
        return $binData;
    }

    //PKCS5Padding
    private function pkcs5Pad($text, $blocksize)
    {
        $pad = $blocksize - (strlen ( $text ) % $blocksize);
        return $text . str_repeat ( chr ( $pad ), $pad );
    }

    private function pkcs5Unpad($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 );
    }

}
?>

例如明文:admin,加密後就是4327f7a3c4ad5e1121f12eca79d958ac(注:加密的結果與你的祕鑰有關)

無論java和php的AES加密出來的結果都一致。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章