php与OpenResty使用AES加密传输方法

php与OpenResty使用AES加密传输方法

Openresty中的可以直接使用resty.aes(lua代码)模块来进行数据的AES加解密,本文主要介绍PHP程序使用AES加密后如何向Lua代码传输并解密。

我们在做一个安全项目时,后端程序是PHP,在向前端传输数据时需要使用aes加密,前端环境是Openresty,使用lua代码开发的接口。

后端程序是php,也有现成AES加解密类可以使用,本文直接上代码:

class aes{
    const KEY="加密密钥KEY 16位 和前端对应";
    const IV ="初始化向量IV 16位 和前端对应";
    private function addPkcs7Padding($string, $blocksize = 32) {
        $len = strlen($string); 
        $pad = $blocksize - ($len % $blocksize); 
        $string .= str_repeat(chr($pad), $pad); 
        return $string;
    }
    function aes256cbcEncrypt($str, $iv, $key ) {   
        return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $this->addPkcs7Padding($str) , MCRYPT_MODE_CBC, $iv));
    }
    private function stripPkcs7Padding($string){
        $slast = ord(substr($string, -1));
        $slastc = chr($slast);
        $pcheck = substr($string, -$slast);

        if(preg_match("/$slastc{".$slast."}/", $string)){
            $string = substr($string, 0, strlen($string)-$slast);
            return $string;
        } else {
            return false;
        }
    }
    function aes256cbcDecrypt($encryptedText, $iv, $key) {
        $encryptedText =base64_decode($encryptedText);
        return $this->stripPkcs7Padding(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encryptedText, MCRYPT_MODE_CBC, $iv));
    }
    function aes128cbcDecrypt($encryptedText, $iv=self::IV, $key=self::KEY) {
        $encryptedText =base64_decode($encryptedText);
        return $this->stripPkcs7Padding(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encryptedText, MCRYPT_MODE_CBC, $iv));
    }
    function hexToStr($hex)
    {   
        $string=""; 
        for($i=0;$i<strlen($hex)-1;$i+=2)
        $string.=chr(hexdec($hex[$i].$hex[$i+1]));
        return  $string;
    }
    function strToHex($string)
    { 
        $hex="";
        $tmp="";
        for($i=0;$i<strlen($string);$i++)
        {
            $tmp = dechex(ord($string[$i]));
            $hex.= strlen($tmp) == 1 ? "0".$tmp : $tmp;
        }
        $hex=strtoupper($hex);
        return $hex;
    }
    function aes128cbcHexDecrypt($encryptedText, $iv=self::IV, $key=self::KEY) {
        $str = $this->hexToStr($encryptedText);
        return $this->stripPkcs7Padding(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_CBC, $iv));
    }

    function aes128cbcEncrypt($str, $iv=self::IV, $key=self::KEY ) {    
        $base = (mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key,$this->addPkcs7Padding($str,16) , MCRYPT_MODE_CBC, $iv));
        return $this->strToHex($base);
    }
}

程序代码引入类,进行加密:

$aes = new aes;
$Sourcedata = 待加密的原始数;
$encrypted = $aes->aes128cbcEncrypt($Sourcedata);
$encrypted 即为使用aes 128 cbc加密后的数据(16进制模式,便于传输)

前端lua可以直接使用现成模块解密,连接:https://github.com/openresty/lua-resty-string

    local aes = require "resty.aes"
    local str = require "resty.string"
    local encrypted = 后端传输过来的aes 128 cbc加密数据 二进制字符串
    local aes_128_cbc_with_iv = assert(aes:new("1234567890123456",
        nil, aes.cipher(128,"cbc"), {iv="1234567890abcdef"}))
   ---1234567890123456 为加密密钥,和后端对应
   ---1234567890abcdef 初始化向量,和后端对应
    local aes_decrypt = aes_128_cbc_with_iv:decrypt(encrypted))
   --aes_decrypt  即为解密后的原始数据

由上面事例代码可以看出,在Openresty处理AES,使用lua-resty-string模块中aes.lua的解密函数decrypt(str)必须保证原数据是二进制字符串,这就需要在解密前需要将后端传输过来的16进制数据转换为二进制字符串。

lua代码:十六进制字符串转换为二进制字符串

function hex2bin(hexstr)
	local str = ""
    for i = 1, string.len(hexstr) - 1, 2 do  
    	local doublebytestr = string.sub(hexstr, i, i+1);  
    	local n = tonumber(doublebytestr, 16);  
    	if 0 == n then  
        	str = str .. '\00'
    	else  
        	str = str .. string.format("%c", n)
    	end
    end 
    return str
end

结合上面后端传输,前端的完成代码为:

local aes = require "resty.aes"
local str = require "resty.string"
local encrypted = hex2bin(encrypted)
local aes_128_cbc_with_iv = assert(aes:new("1234567890123456", nil, aes.cipher(128,"cbc"), {iv="1234567890abcdef"})) ---1234567890123456 为加密密钥,和后端对应
---1234567890abcdef 初始化向量,和后端对应
local aes_decrypt = aes_128_cbc_with_iv:decrypt(encrypted))

关于作者

cdnya administrator

安全防御技术员

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据