js前端加密,php后端解密(crypto-js,openssl_decrypt)

最近在做react native项目,需要对用户登录数据进行加密传输,前端加密采用开源js库crypto-js,后端解密用php(我的是php7版本)自带的openssl_decrypt方法,踩了许多坑,记录一下。

一、安装/配置依赖库

1. crypto-js安装

npm install crypto-js

GitHub项目地址:

官方文档中有介绍具体使用的方法,很清晰。

2. php openssl 配置

参考文章:

openssl_encrypt的基本使用形式:openssl_decrypt(data, method, key, options, iv)

data:待解密的数据

method:可以选aes-128-cbc、aes-256-cbc等,官网上的method列表如下:

[0] => AES-128-CBC

[1] => AES-128-CFB

[2] => AES-128-CFB1

[3] => AES-128-CFB8

[5] => AES-128-OFB

[6] => AES-192-CBC

[7] => AES-192-CFB

[8] => AES-192-CFB1

[9] => AES-192-CFB8

[11] => AES-192-OFB

[12] => AES-256-CBC

[13] => AES-256-CFB

[14] => AES-256-CFB1

[15] => AES-256-CFB8

[17] => AES-256-OFB

[18] => BF-CBC

[19] => BF-CFB

[21] => BF-OFB

[22] => CAST5-CBC

[23] => CAST5-CFB

[25] => CAST5-OFB

[41] => IDEA-CBC

[42] => IDEA-CFB

[44] => IDEA-OFB

[53] => aes-128-cbc

[54] => aes-128-cfb

[55] => aes-128-cfb1

[56] => aes-128-cfb8

[58] => aes-128-ofb

[59] => aes-192-cbc

[60] => aes-192-cfb

[61] => aes-192-cfb1

[62] => aes-192-cfb8

[64] => aes-192-ofb

[65] => aes-256-cbc

[66] => aes-256-cfb

[67] => aes-256-cfb1

[68] => aes-256-cfb8

[70] => aes-256-ofb

[71] => bf-cbc

[72] => bf-cfb

[74] => bf-ofb

[75] => cast5-cbc

[76] => cast5-cfb

[78] => cast5-ofb

[94] => idea-cbc

[95] => idea-cfb

[97] => idea-ofb

options:有OPENSSL_RAW_DATA和OPENSSL_ZERO_PADDING两种,前者会默认采用PKCS#7进行补位,输出结果是加密后的原始结果,没有用base64编码;后者要求被加密的数据必须是“加密块”的整数倍,也就需要自己对加密数据进行补位处理。

iv:一个初始非零向量(必须是16位)

二、采坑记录

我采用的是aes加密的方式,

注意坑1:openssl_encrypt中aes-128-cbc、aes-256-cbc中的128、256是与秘钥位数有关的,16位秘钥需要使用aes-128-cbc模式。参考文章:

注意坑2:加密后的字符串如果直接用post form形式提交给php后端,会出现无法解密的情况,经过多次测试,终于找到原因。

这是我form表单里提交的密文:

图片[1]-js前端加密,php后端解密(crypto-js,openssl_decrypt)-JieYingAI捷鹰AI

php后端获取'data'数据后得到的密文:

图片[2]-js前端加密,php后端解密(crypto-js,openssl_decrypt)-JieYingAI捷鹰AI

详细看!字符'+'还有'/'解析方式不同,得到的是完全不同的密文!!

所以,我最后前端是用json格式传输的数据,php后端用

file_get_contents("php://input");

获取前端传送过来的json数据。php获取json数据可参考文章: 三、代码实现

//前端js,使用crypto-js对数据进行AES加密
  function encrypt(text){
	var key = CryptoJS.enc.Latin1.parse('1234567890654321'); //为了避免补位,直接用16位的秘钥
	var iv = CryptoJS.enc.Latin1.parse('1234567890123456'); //16位初始向量
	var encrypted = CryptoJS.AES.encrypt(text, key, {
			iv: iv,
			mode:CryptoJS.mode.CBC,
			padding:CryptoJS.pad.ZeroPadding
		});
	return encrypted;
  }

//后端php,类函数appLogin()
public function appLogin(){
        $post = $this->request->post();
	$encrypted = $post['data'];
	$key = "1234567890654321";
	$iv = "1234567890123456";
	$decrypted = openssl_decrypt($encrypted, 'aes-128-cbc', $key, OPENSSL_ZERO_PADDING , $iv);		
	…… //其他处理,解密后的字符串是带有'u0000'补位的原始结果,需要自行去掉
}

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享