RSA+AES 实现客户端和服务端交互数据加密

经验 301 浏览

现在接口大多是http请求,数据在请求过程中容易被抓包造成信息泄露或者数据被篡改。所以,数据传输过程中我们需要对敏感数据加密处理。

在实现加密方法之前,我们需要先了解下加密算法,我们的加密方法都需要加密算法去支持。常用接口加密常用的就是 DES/AES/RSA/SHA1/MD5 等加密算法了。

加密算法一般也就3种:对称加密算法、非对称加密算法、散列算法

| DES

DES对称加密算法,全称为 Data Encryption Standard,是一种使用密钥加密的块算法。加密串的长度是64位(bit),超过位加密串被忽略。所谓对称性加密即加密和解密密钥相同,对称性加密一般会按照固定长度,把待加密字符串分成块,不足一整块或者刚好最后有特殊填充字符。

DES 现在已经不被视为一种安全的加密算法而废弃,主要原因是它使用的56位密钥过短。

| AES

AES(Advanced Encryption Standard)高级加密标准,在密码学中又称Rijndael加密法这个标准用来替代原先的 DES(Data Encryption Standard),已经被多方分析且广为全世界所使用。AES 的分组长度是128bit,三种可选密钥长度128bit,192bit和256bit,轮数分别为10、12和14。

优点:AES 加密解密速度快,兼容设备,安全级别高。

场景:绝大部分场景都可使用,尤其大量数据需要加密时。

| RSA

RSA加密算法是一种非对称加密算法。使用公钥加密数据,利用私钥进行解密,加密或签名后的结果是不可读的二进制,使用时我们转为 BASE64 码再传输。

优点:RSA 目前为止,只要秘钥长度够长,基本不可能破解。而且既可以用来加密数据,也可以用来做数字签名。

场景:由于安全性可靠,但是大量数据时解密慢,我们用于对数据少且保密性高的数据加密。比如 AES 的秘钥串,就可以由 RSA 加密传输。

| SHA1/MD5

SHA1/MD5 是一种密码散列算法,将任意大小的数据映射到一个较小的、固定长度的唯一值。加密性强的散列一定是不可逆的,这就意味着通过散列结果,无法推出任何部分的原始信息。SHA1 和 MD5 目前可以被破解,建议使用 SHA2 或其他散列算法。

优点:抗修改性:任何修改后的值都不一样;压缩性:任意长度的数据算出的值都是固定的;强抗碰撞:已知原数据与其散列值,想找到一个具有相同散列值的数据(即伪造数据)是非常困难的。

场景:SHA1/MD5 都不可逆,用于完整性(数据摘要),可确保信息在传输过程保持一致性,所以可以用来校验数据真伪,防止篡改数据;还可以用于密码加密,数据库中不存储密码明文,而是存储其散列值,校验时比较散列值是否相同,即使获取到数据库权限也不知道密码。

| 加密流程

单一算法都是有局限性的,我们可以采用 AES+RSA 和 MD5 算法组合,实现加密流程:非对称加密算法(RSA)管理对称算法的密钥,使用散列函数(MD5)进行数据摘要,然后用对称加密算法(AES)加密数据。

/====================客户端====================/

step1. 客户端向服务端请求公钥,服务器端生成 RSA 秘钥对,保存私钥,返回公钥

step2. 客户端生成随机 AES 明文密钥(16位),并通过 RSA 公钥加密获取密文secretKey

key = 'e9c8e878ee8e2658';  // 随机生成AES明文/iv向量,用来预防内部人员的。

secretKey = Rsa.encryptToBase64(key, 公钥);  // encryptToBase64 将明文RSA加密后转成base64码。

step3. 客户端对data源数据 MD5 摘要(或者其他约定的方式,确保数据传输前后一致性),得到sign签名。

sign = md5('{"username":"bzing","password":"123456"}');

step4. 客户端将sign和data通过 AES 加密。

data = '{"data":{"username":"bzing","password":"123456"},"sign":"7e6e72203e520dcbd5e0c190ee5df99e"}';

encryptString = Aes.encryptToBase64(data, key);  // data:明文数据,key:明文key,encryptString:加密串 

step5. 客户端将 encryptString 和 secretKey 发送到服务端。

'{"encryptString":"xxxxxxxxx","secretKey":"xxxxxxxxxx"}'

/====================服务端====================/

step1. 服务端通过私钥对secretKey密文进行解密,获取到 AES 密钥明文 key。

key = Rsa.decryptFromBase64(secretKey, 私钥);

step2. 服务端通过 AES 明文 key 对 encryptString  解密。

dataArr = Aes.decryptFromBase64(encryptString, key);

step3. 服务端将解密得到的数据按照与客户端一致的方法签名sign1,并对比sign签名。

data = dataArr['data'];

sign = dataArr['sign'];

sign1 = md5(data);

step4. 服务端签名验证通过,解析json串,处理逻辑。

|  版权声明:本文为博主原创文章,转载请注明出处。