天天看點

php7 加密模式AES AES-128-CBC 填充PKCS7Padding 加密hex 字元集utf8

AES,進階加密标準(英語:Advanced Encryption Standard,縮寫:AES),在密碼學中又稱Rijndael加密法,是美國聯邦政府采用的一種區塊加密标準。這個标準用來替代原先的DES,已經被多方分析且廣為全世界所使用。嚴格地說,AES和Rijndael加密法并不完全一樣(雖然在實際應用中二者可以互換),因為Rijndael加密法可以支援更大範圍的區塊和密鑰長度:AES的區塊長度固定為128 比特,密鑰長度則可以是128,192或256比特;而Rijndael使用的密鑰和區塊長度可以是32位的整數倍,以128位為下限,256比特為上限。包括AES-ECB,AES-CBC,AES-CTR,AES-OFB,AES-CFB

注:在搞這個進階加密的時候發現很多問題,一群複制粘貼黨浪費我這麼多時間,多看文檔

參考手冊 ​​http://www.php.net/manual/en/function.openssl-decrypt.php​​

Parameters may seem obvius to some but not for everyone so: 

- $data can be as the description says raw or base64. If no $option is set (this is, if value of 0 is passed in this parameter), data will be assumed to be base64 encoded. If parameter OPENSSL_RAW_DATA is set, it will be understood as row data. 

- $password (key) is a String of [pseudo] bytes as those generated by the function openssl_random_pseudo_bytes(). 

- $options as (as for 2016) two possible values OPENSSL_RAW_DATA and OPENSSL_ZERO_PADDING. Setting both can be done by OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING. If no OPENSSL_ZERO_PADDING is specify, default pading of PKCS#7 will be done as it's been observe by [openssl at mailismagic dot com]'s coment in openssl_encrypt() 

- $iv is as in the case of $password, a String of bytes. Its length depends on the algorithm used. May be the best way to generate an $iv is by: 

我也看不懂翻譯一下:

有些人可能覺得參數很明顯,但并非每個人都如此:



-$data可以如描述中所說的raw或base64。如果沒有設定$option(如果此參數中傳遞的值為0),則假定資料是base64編碼的。如果設定參數openssl_raw_data,它将被了解為行資料。



-$password(key)是由函數openssl_random_pseudo_bytes()生成的[pseudo]位元組字元串。



-$options as(截至2016年)兩個可能的值openssl_raw_data和openssl_zero_padding。兩種設定都可以通過openssl_raw_data_openssl_zero_padding完成。如果沒有指定openssl_zero_padding,pkcs 7的預設padding将按照openssl_encrypt()中[openssl at mailismagic dot com]的coment所觀察的方式進行。



-$IV和$password一樣,是一個位元組字元串。它的長度取決于使用的算法。産生IV美元的最好方法是:      

再注一下 : 參數 options 打開源碼這裡定義了一下,是以直接填1即可

define('OPENSSL_RAW_DATA', 1);
define('OPENSSL_ZERO_PADDING', 2);
define('OPENSSL_DONT_ZERO_PAD_KEY', 4);      

這下就很清楚了 自己玩吧,需要幫我的聯系我,

這裡在講解一下填充的問題:比如線上網站上做測試:​​http://tool.chacuo.net/cryptaes​​

php7 加密模式AES AES-128-CBC 填充PKCS7Padding 加密hex 字元集utf8

這裡解釋一下參數,如上圖中的加密出來的參數 

39a2706b82b2c13e8442305d6a926b9518ad9bb658b01a11b95ce18c6b085347

39 是一個位元組 a2 是一個位元組 

加解密已經封裝了自動填充,不需要自己在去填充補位和解密時截取去處位置

這裡我被坑了,我在給它加l一次hex加解密其實是在加密的将他認定為字元串(十進制)轉十六進制,解密時用十六進制轉為ASCII,是錯誤的.大家注意了

還一個标注一下:iv預設就是16位,相信大家會遇到如下報錯,openssl_encrypt 加密會把iv預設截成16位,所有就是你的iv如果是17位.你的iv會在末尾減一位,好了廢話有點多,相信能幫助到大家,

Warning: openssl_encrypt(): IV passed is 17 bytes long which is longer than the 16 expected by selected cipher, truncating in      
<?php

class AES
{
    /**
     * var string $method 加解密方法,可通過openssl_get_cipher_methods()獲得
     */
    protected $method;

    /**
     * var string $secret_key 加解密的密鑰
     */
    protected $secret_key;

    /**
     * var string $iv 加解密的向量,有些方法需要設定比如CBC
     */
    protected $iv;

    /**
     * var string $options (不知道怎麼解釋,目前設定為0沒什麼問題)
     */
    protected $options;

    /**
     * 構造函數
     *
     * @param string $key 密鑰
     * @param string $method 加密方式
     * @param string $iv iv向量
     * @param mixed $options 還不是很清楚
     *
     */
    public function __construct($key, $method = 'AES-128-CBC', $iv = '', $options = 0)
    {
        // key是必須要設定的
        $this->secret_key = isset($key) ? $key : exit('key為必須項');

        $this->method = $method;

        $this->iv = $iv;

        $this->options = $options;
    }

    /**
     * 加密方法,對資料進行加密,傳回加密後的資料
     *
     * @param string $data 要加密的資料
     *
     * @return string
     *
     */
    public function encrypt($data)
    {
        $en = openssl_encrypt($data, $this->method, $this->secret_key, $this->options, $this->iv);
        //$en = $this->String2Hex($en);
        return $en;
    }

    /**
     * 解密方法,對資料進行解密,傳回解密後的資料
     *
     * @param string $data 要解密的資料
     *
     * @return string
     *
     */
    public function decrypt($data)
    {
        //$data = $this->Hex2String($data);
        $de = openssl_decrypt($data, $this->method, $this->secret_key, $this->options, $this->iv);
        return $de;
    }


    public function String2Hex($string){


        $hex='';
//        for ($i=0; $i < strlen($string); $i++){
//            $hex .= dechex(ord($string[$i]));
//        }
        $hex = bin2hex($string);
        return $hex;
    }

    public function Hex2String($hex){
        $string='';
        for ($i=0; $i < strlen($hex)-1; $i+=2){
            $string .= chr(hexdec($hex[$i].$hex[$i+1]));
        }
        return $string;
    }
}


$data = '{"messageid":15645624658187,"timestamp":1564562465,"deviceid":"AD13L1907310001","cmd":"CMD-01","desired":{"allget":1}}';
$key = 'FW2VN#N8DAL147L*';
//$aes = new Aes($key, 'AES-128-CBC', '2398DHY433UGFKL1',  1);
$aes = new Aes($key, 'AES-128-CBC', '2398DHY433UGFKL1',  1);
$encode = $aes->encrypt($data);
echo "#####encode#####" . $encode . PHP_EOL;
$decode = $aes->decrypt($encode);
echo "#####decode#####" . $decode . PHP_EOL;