基于openssl的AES加解密

对于加解密,企业常用的有AES和RSA,它们分别是对称加解密算法和非对称加解密算法的代表,这里主要封装了php的一套基于openssl的AES加解密实现类

<?php
/**
 * Created by PhpStorm.
 * User: 小小徐
 * Date: 2019/4/21
 * Time: 18:11
 */
class BaseAES{
    /**
     * 初始化向量长度|随机向量长度
     */
    const INIT_VECTOR_LENGTH = 16;
    /**
     * 常见的的两种AES加密128|256
     */
    const CIPHER128 = 'AES-128-CBC';
    const CIPHER256 = 'AES-256-CBC';
    /**
     * @var string 加解密方式
     */
    protected static $method ;
    /**
     * 加密|解密字符
     * @var null|string
     */
    protected $data;
    /**
     * 随机偏移量
     * @var string
     */
    protected $initVector;
    /**
     * 错误信息
     * @var null|string
     */
    protected $errorMessage;

    /**
     * 构造函数
     * @param string $initVector 偏移量
     * @param string|null $data 加解密数据
     * @param string|null $errorMessage 错误信息
     */
    public function __construct($initVector, $data = null, $errorMessage = null)
    {
        $this->initVector = $initVector;
        $this->data = $data;
        $this->errorMessage = $errorMessage;
    }

    /**
     * 校验密钥长度
     * @param string $secretKey 16/24/32 -characters secret password
     * @return bool
     */
    protected static function isKeyLengthValid($secretKey)
    {
        $length = strlen($secretKey);
        return $length == 16 || $length == 24 || $length == 32;
    }

    /**
     * 获取加解密的字符串
     * @return string|null
     */
    public function getData()
    {
        return $this->data;
    }

    /**
     * 获取随机偏移量
     * @return string|null
     */
    public function getInitVector()
    {
        return $this->initVector;
    }

    /**
     * 获取错误信息
     * @return string|null
     */
    public function getErrorMessage()
    {
        return $this->errorMessage;
    }

    /**
     * 判断是否有错误
     * @return bool
     */
    public function hasError()
    {
        return $this->errorMessage !== null;
    }

    /**
     * @return null|string
     */
    public function __toString()
    {
        return $this->getData();
    }

    /**
     * 基于openssl的解密方法
     * @param string  $plainText  需要解密的字符串
     * @param string  $secretKey  密钥长度16|24|32
     * @param string  $initVector 偏移量
     * @param string  $method  解密方式
     * @return static
     */
    public static function decrypt($cipherText, $secretKey,$initVector=null, $method= null)
    {
        try {
            // 校验密钥长度
            if (!static::isKeyLengthValid($secretKey)) {
                throw new \InvalidArgumentException("Secret key's length must be 128, 192 or 256 bits");
            }
            // 获取原加密后的字符串
            $encoded = base64_decode($cipherText);
            //获取解密方式
            if(null === $method){
                $method = self::CIPHER128;
            }
            
            // 获取真正加密后的原始串
            $data = static ::decryptCallBack($initVector,$encoded);
            //  解密
            $decoded = openssl_decrypt(
                $data,
                $method,
                $secretKey,
                OPENSSL_RAW_DATA,
                $initVector
            );
            if ($decoded === false) {
                // Operation failed
                return new static(isset($initVector), null, openssl_error_string());
            }
            // 返回一个自己的对象 可以再进行进一步操作
            return new static($initVector, $decoded);
        } catch (\Exception $e) {
            // Operation failed
            return new static(isset($initVector), null, $e->getMessage());
        }
    }

    /**
     * 基于openssl的加密方法
     * @param string  $plainText  需要加密的字符串
     * @param string  $secretKey  密钥长度16|24|32
     * @param string  $initVector 偏移量
     * @param string  $method  加密方式
     * @return static
     */
    protected static function encrypt($plainText, $secretKey,$initVector=null, $method= null)
    {
        try {
            //校验密钥长度
            if (!static::isKeyLengthValid($secretKey)) {
                throw new \InvalidArgumentException("Secret key's length must be 128, 192 or 256 bits");
            }
            //设置加密方式
            if(null === $method){
                $method = self::CIPHER128;
            }
            // 生成随机向量 即偏移量
            if(null === $initVector){
                $initVector = bin2hex(openssl_random_pseudo_bytes(static::INIT_VECTOR_LENGTH / 2));
            }
            //加密
            $raw = openssl_encrypt(
                $plainText,
                $method,
                $secretKey,
                OPENSSL_RAW_DATA,
                $initVector
            );
            //对加密后的原始数据和偏移量进行操作
            $callBackResult = static ::encryptCallBack($initVector,$raw);
            // Return base64-encoded string:  $callBackResult result |将数据进行base64_encode
            $result = base64_encode($callBackResult);
            if ($result === false) {
                // Operation failed
                return new static($initVector, null, openssl_error_string());
            }
            // 返回自己的对象方便进一步操作
            return new static($initVector, $result);
        } catch (\Exception $e) {
            // Operation failed
            return new static(isset($initVector), null, $e->getMessage());
        }
    }

    /**
     * 与decryptCallBack相对应
     * 在加密后和base64_encode之前 对 加密后的原始数据与偏移量进行操作
     * @param $initVector string 偏移量
     * @param $raw  string 加密后的原始串[非utf8]
     * @return string
     */
    protected static function encryptCallBack($initVector,$raw){
        return $initVector.$raw;
    }

    /**
     * 与encryptCallBack相对应
     * 在base64_decode之后和解密之前 对 需要解密的字符串进行base64_decode之后的原始数据与偏移量进行操作
     * @param $initVector  string 偏移量
     * @param $encoded  string 解密后的原始串[非utf8]
     * @return bool|string
     */
    protected static function decryptCallBack(&$initVector,$encoded){
        // 获取偏移量
        if( null === $initVector){
            $initVector = substr($encoded, 0, static::INIT_VECTOR_LENGTH);
        }
        return substr($encoded, static::INIT_VECTOR_LENGTH);
    }


    /**
     * AES128加密
     * @param $plainText string 需要加密的字符串
     * @param $secretKey string 密钥
     * @param $initVector string 偏移量
     * @return BaseAES
     */
    public static function encryptWith128CBC($plainText, $secretKey,$initVector=null)
    {
           return self::encrypt($plainText,$secretKey,$initVector);
    }

    /**
     * AES128解密
     * @param $cipherText string  需要解密的字符串
     * @param $secretKey  string  密钥
     * @param $initVector string 偏移量
     */
    public static function decryptWith128CBC($cipherText, $secretKey,$initVector=null)
    {
        return self::decrypt($cipherText, $secretKey,$initVector);
    }

    /**
     * AES256加密
     * @param $plainText string 需要加密的字符串
     * @param $secretKey string 密钥
     * @param $initVector string 偏移量
     * @return BaseAES
     */
    public static function encryptWith256CBC($plainText, $secretKey,$initVector=null)
    {
        return self::encrypt($plainText,$secretKey,$initVector,self::CIPHER256);
    }

    /**
     * AES256解密
     * @param $cipherText string  需要解密的字符串
     * @param $secretKey  string  密钥
     * @param $initVector string 偏移量
     */
    public static function decryptWith256CBC($cipherText, $secretKey,$initVector=null)
    {
        return self::decrypt($cipherText, $secretKey,$initVector,self::CIPHER256);
    }

}

使用方式

$key = 'zxcvbnmasdfghjkl';
$data = "who are you!";
$res1 = BaseAES::encryptWith256CBC($data,$key);
$res2 = BaseAES::decryptWith256CBC($res1,$key);
var_dump($res1);
var_dump($res2);

为了满足更特殊的需求,返回的是一个对象,包含加密|解密的数据及随机生成的偏移量以满足特殊的使用场景

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenSSL提供了AES加密算法,可以使用AES_cbc_encrypt函数进行加密操作。这个函数需要传入明文数据、密钥、初始向量(ivec)等参数进行加密。其中,初始向量(ivec)的内容可以任意指定,但加密和解密操作必须使用相同的数据。在AES_cbc_encrypt的底层实现中,每16个字节进行一次处理,先与初始向量进行异或运算,然后调用AES_encrypt函数进行加密。在加密过程中,AES_cbc_encrypt会修改初始向量的内容,因此初始向量参数不能是一个常量,也不能在传递给加密函数后立即传递给解密函数,必须重新赋值后再传递给解密函数。 需要注意的是,对称加密算法的优势是算法公开、计算量小、加密速度快、加密效率高,而安全性主要取决于密钥的保护。对称加密的缺点主要体现在多用户通信场景中,密钥分发和管理比较困难。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [基于openssl库实现AES加密(C语言)](https://blog.csdn.net/ylgcgbd/article/details/117931518)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [OpenSSLAES加密的用法](https://blog.csdn.net/m0_46577050/article/details/121302115)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值