欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

php中AES加解密的正确姿势

程序员文章站 2024-03-14 17:27:52
...

在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;
	    }
	}
}