對於加解密,企業常用的有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);
爲了滿足更特殊的需求,返回的是一個對象,包含加密|解密的數據及隨機生成的偏移量以滿足特殊的使用場景