密钥传输和签名加密流程(国密)
密钥传输流程
系统内置一套公钥和私钥
打开前端时自动获取其中公钥(公钥不需要加密)
前端随机生成一个 sm4 的 key 和 iv,使用公钥对 key 和 iv 进行加密,传到后台 (已加密),后台使用私钥解密能拿到原始 key 和 iv,
然后在生成一套公私钥,key、iv 和公钥存到 redis 中。每个用户的 key、iv和公私钥都是不一样的,重新打开页面也会重新生成 key、iv和公私钥。私钥使用 sm4 的 cbc 模式加密后传给前端已加密。前端再使用刚才随机生成的 key 和 iv 解密拿到私钥。前端使用这个私钥对请求进行签名。
前端向后端加密传输
前端拦截请求,对请求中 body 使用 sm2 的公钥加密或使用 sm4 cbc 模式加密(目前使用的 sm2 加密)后端收到请求后,在验签之前使用私钥把 body 数据解密,然后再验签。前端拦截请求,对请求中 body 先使用 sm3 计算哈希,然后把哈希值和明文数据拼接后,使用 sm2 公钥加密或使用 sm4 cbc 模式加密(目前使用的 sm2 加密)
后端收到请求后,在验签之前使用私钥把 body 数据解密,然后验证 sm3 哈希是否正确,最好在验签。
后端向前端加密传输
- 后端接口返回之前,对返回数据使用 sm2 公钥加密或使用 sm4 cbc 模式加密(目前使用 sm4 cbc)
- 使用 sm2 私钥对数据签名
- 前端后端返回数据后,先用 sm2 公钥验证签名,然后再对数据进行解密后使用。
请求签名流程
使用上一步拿到的私钥进行签名
前端
- 获取当前时间戳
- 生成随机字符串
- 合并请求参数、随机字符串、时间戳
- 对合并后的对象按照属性名称进行排序
- 使用 sm3 获取(方法+排序后对象)的摘要当作签名值
使用私钥对摘要和请求方法进行签名(sm2)- 把时间戳、随机字符串、签名方法请求头中。
后端
- 判断有没有时间戳、随机字符串、签名。没有则拒绝
- 判断时间戳时间和当前时间,不能超过 60s
- 使用和前端同样的方式对参数、随机字符串、时间戳进行合并排序、计算摘要
使用公钥对请求方法和处理后的数据验签。
排序方法
参与排序的包括 body、query、params
1 | function sortObject(obj) { |
此文章版权归houxiaozhao所有,如有转载,请注明来自原作者