php中AES加解密的正確姿勢

在php中以往加解密(AES等)都是用mcrypt_encrypt,然而在PHP新版本中mcrypt_encrypt被棄用(mcrypt的好些函數自PHP 7.1.0起已棄用,強烈建議不要使用。),所以加解密就不能再用這個方法了,這時候就得用其他方法代替了,比如openssl中的加解密方法就是官方推薦的,這裏提供openssl中AES加解密的示例:

<?php
/**
 *  +----------------------------------------------------------------------
 *  | HlinfoCMS
 *  +----------------------------------------------------------------------
 *  | Copyright (c) 2020 hlinfo.net All rights reserved.
 *  +----------------------------------------------------------------------
 *  | Author: 吶喊 <[email protected]>
 *  +----------------------------------------------------------------------
 */
namespace app\common;
/**
 * AES加解密
 * <ul>
 * <li>$text="hello word,您好^_^";</li>
 * <li>echo "原文:".$text."";</li>
 * <li>$key = "123456";</li>
 * <li>$aes = new AES($key);</li>
 * <li>$mw = $aes->encrypt($text);</li>
 * <li>echo "密文:".$mw;</li>
 * <li>$verifyKey = $aes->getVerifyKey();</li>
 * <li>echo "校驗祕鑰:".$verifyKey;</li>
 * <li>$aes2 = new AES($key,$verifyKey);</li>
 * <li>$min = $aes2->decrypt($mw);</li>
 * <li>echo "解密後的數據:".$min;</li>
 * </ul>
 * @package app\common
 */
class AES{
	/**
	*加密祕鑰
	*/
	private $key;
	/**
	*校驗祕鑰
	*/
	private $verifyKey;
	/**
	*加密算法
	*/
	const method = "aes-256-cbc";

    /**
     * 構造函數
     * AES constructor.
     * @param $key
     * @param null $checkkey
     */
	public function __construct($key,$verifyKey=null) {
		$this->key = md5($key);
                if(!empty($verifyKey)){
                        $this->verifyKey = $verifyKey;
                }
	}

    /**
     * @return mixed
     */
    public function getKey()
    {
        return $this->key;
    }

    /**
     * @param mixed $key
     */
    public function setKey($key)
    {
        $this->key = $key;
    }

    /**
     * @return mixed
     */
    public function getVerifyKey()
    {
        return $this->verifyKey;
    }

    /**
     * @param mixed $verifyKey
     */
    public function setVerifyKey($verifyKey)
    {
        $this->verifyKey = $verifyKey;
    }

    /**
    *生成校驗祕鑰
    */
    public function createChkKey(){
        if(empty($this->verifyKey)) {
            $chkkey = base64_encode(openssl_random_pseudo_bytes(64));
            $this->verifyKey = $chkkey;
        }
    }
    /**
     * 加密
     * @param $data
     * @return string
     */
	public function encrypt($data)
	{
	    #生成校驗祕鑰
	    $this->createChkKey();
            #base64解密校驗密鑰
	    $verify_key = base64_decode($this->verifyKey);
            #獲取加密算法對應的iv向量長度
	    $iv_length = openssl_cipher_iv_length(self::method);
            #獲取iv向量
	    $iv = openssl_random_pseudo_bytes($iv_length);
	    #加密
	    $ciphertext = openssl_encrypt($data,self::method,$this->key, OPENSSL_RAW_DATA ,$iv);
        #計算校驗Hash
	    $hashkey = hash_hmac('sha3-512', $ciphertext, $verify_key, TRUE);
	    #結果base64處理
	    $output = base64_encode($iv.$hashkey.$ciphertext);   
	    return $output;
	}

    /**
     * 解密
     * @param $input
     * @return bool|string
     */
	public function decrypt($input)
	{
            #base64解密校驗密鑰
            $verify_key = base64_decode($this->verifyKey);
            #base64解密密文
	    $cipherData = base64_decode($input);
	    #獲取加密算法對應的iv向量長度
	    $iv_length = openssl_cipher_iv_length(self::method);
	    #獲取iv向量
	    $iv = substr($cipherData,0,$iv_length);
	    #獲取校驗的hash值
	    $hashkey = substr($cipherData,$iv_length,64);
	    #獲取真正的密文
	    $ciphertext = substr($cipherData,$iv_length+64);
	    #解密
	    $plaintext = openssl_decrypt($ciphertext,self::method,$this->key,OPENSSL_RAW_DATA,$iv);
            #計算校驗Hash
	    $hashkey_new = hash_hmac('sha3-512', $ciphertext, $verify_key, TRUE);
	    #校驗
	    if (hash_equals($hashkey,$hashkey_new)){
		return $plaintext;
	    }else{
		return false;
	    }
	}
}

 

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