RSA非对称加密RSA是一种常用的非对称加密算法,加密和加密使用不同的密钥,常用于要求安全性较高的加密场景,比如接口的验签和接口数据的加密与解密 。与非对称加密算法对比,其安全性较高,但是加密性能却比较低,不适合高并发场景,一般只加密少量的数据 。
AES对称加密AES是一种最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的),加密和解密使用的是相同的密钥 。其加密性能好,加密解密速度非常快,内存需求低,适用于经常发送数据的场合 。
RSA+AES实现接口验签和请求参数的加密与解密背景:作为程序猿,我们经常需要在我们自己开发的系统上,开发一些接口供第三方调用,那么这个时候,对我们接口的安全性要求就比较高了,尤其是那种需要传输比较私密的信息的时候,其对安全性的要求就更高了 。
实现思路调用方:
- 使用AES对称加密算法对业务请求参数进行加密后传输
- 使用RSA非对称加密算法对AES的密钥进行公钥加密后传输
- 使用RSA的私钥对请求参数进行签名
- 获取到请求参数后,对参数进行验签和业务参数的解密
AES是对称加密算法,加密和解密的密钥都是同一个,为了防止被别人恶意获取到该密钥,然后对我们的业务请求参数进行解密,我们需要将AES密钥进行非对称加密后再进行传输 。
代码实现
<!--RSA依赖--><dependency><groupId>org.bouncycastle</groupId><artifactId>bcpkix-jdk15on</artifactId><version>1.56</version></dependency><!--Jackson依赖--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.8</version></dependency><!--Jackson依赖--><dependency><groupId>org.codehaus.jackson</groupId><artifactId>jackson-core-asl</artifactId><version>1.8.3</version></dependency>请求和接收的实体对象@Datapublic class JsonRequest {//接口id 可空private String serviceId;//请求唯一id 非空private String requestId;//商户id 非空private String AppId;//参数签名 非空private String sign;//对称加密key 非空private String aseKey;//时间戳,精确到毫秒 非空private long timestamp;//请求的业务参数(AES加密后传入) 可空private String body;}- serviceId:服务id(接口id) 。接口设计分为两种,一种是所有的调用方针对类似的业务,都调用的是同一接口地址,然后内部系统根据serviceId去判断具体是要调用哪个业务方法;另一种是针对不同的调用方,开发不同的接口,接口地址也是不一样,那么这个时候就可以不要serviceId这个字段 。本章是使用第二种方式,所以serviceId可以不要(可空) 。
- requestId:请求唯一id 。方便查询定位某个请求和防止同个请求多次调用 。
- appId:商户id,即我们会给调用方分配一个这样的id,并且将这个id与调用方的信息进行关联,比如“通过appId查询出调用方的加密密钥等”
- aseKey:是AES对称加密的密钥 。用于解密业务请求参数 。这里要先用RSA公钥对aseKey进行加密后传输 。
- timestamp:请求时间戳 。可以用该字段,对请求的时间合法性进行校验 。(如:过滤掉请求时间不在当前时间的正负10分钟范围内的请求)
- body:请求的业务参数 。对请求的业务参数AES加密后再赋值 。
/** * @author: Longer * @date: 2020/8/23 * @description: AES工具类 */public class AESUtil {/*** 加密* @param content 加密文本* @param key 加密密钥,appSecret的前16位* @param iv 初始化向量,appSecret的后16位* @return* @throws Exception*/public static String encrypt(String content, String key, String iv) throws Exception {byte[] raw = key.getBytes();SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); //"算法/模式/补码方式"IvParameterSpec ivParam = new IvParameterSpec(iv.getBytes()); //使用CBC模式,需要一个向量iv,可增加加密算法的强度cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParam);byte[] encrypted = cipher.doFinal(content.getBytes());return new BASE64Encoder().encode(encrypted);}public static String decrypt(String content, String key, String iv) throws Exception {byte[] raw = key.getBytes();SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding "); //"算法/模式/补码方式"IvParameterSpec ivParam = new IvParameterSpec(iv.getBytes()); //使用CBC模式,需要一个向量iv,可增加加密算法的强度cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivParam);byte[] encrypted = new BASE64Decoder().decodeBuffer(content); //先用base64解密byte[] original = cipher.doFinal(encrypted);return new String(original);}public static void main(String[] args) throws Exception {String encrypt = AESUtil.encrypt("你好啊!!!", "1234567890123456", "1234567890123456");String decrypt = AESUtil.decrypt(encrypt, "1234567890123456", "1234567890123456");System.out.println(decrypt);}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 电脑微信如何实现多开?
- 高校|1076万“打工人”即将进职场,如何实现就业?这个方向值得考虑
- 华为S5700设置acl,实现vlan三层隔离,让你小白变大神,转发收藏
- 百度C++工程师如何实现极致并发优化
- 教程 在浏览器中实现IPFS连接的指引
- Vue中使用v-viewer组件实现图片预览功能,支持Vue3
- jenkins+Acunetix实现自动化安全测试
- mac如何安装sz,rz,实现本地和服务器文件传输「开发效率工具」
- 一文看懂智慧城市建设,AI算法如何实现赋能?
- django 编写数据接口
