SpringBoot+VUE 前端加密算法 RSA+DES

前言

为了提高用户登陆的安全性,公司准备整理一份相对安全的登陆模式。

想法

主流加密算法

在这里插入图片描述

主流加密算法

  • (一)对称加密AES ,其特点是:算法简单,加密速度快;

  • (二)非对称加密方式,代表是RSA加密算法,其特点–采用的一对秘钥机制(即加解密秘钥不同),公钥加密、私钥解密,管理简单,缺点是解密速度慢。

    img

    最终方式

    具体过程是先由接收方创建RSA密钥对,接收方通过Internet发送RSA公钥到发送方,同时保存RSA私钥。而发送方创建AES密钥。并用该 AES密钥加密待传送的明文数据,同时用接受的RSA公钥加密AES密钥,最后把用RSA公钥加密后的AES密钥同密文一起通过Internet传输发送 到接收方。当接收方收到这个被加密的AES密钥和密文后,首先调用接收方保存的RSA私钥,并用该私钥解密加密的AES密钥,得到AES密钥。最后用该 AES密钥解密密文得到明文。

基本流程

请求:

  1. 服务器端(server)生成密钥对
  2. server给client自己的公钥
  3. client生成AES密钥(aesKey)
  4. client使用自己的RSA私钥(privateKey)对请求明文数据(params)进行数字签名
  5. 将签名加入到请求参数中,然后转换为json格式
  6. client使用aesKey对json数据进行加密得到密文(data)
  7. client使用sever的RSA公钥对aesKey进行加密(encryptkey)
  8. 分别将data和encryptkey作为参数传输给服务器端

服务器端进行请求响应时将上面流程反过来即可

使用

  1. 安装crypto-js
npm install crypto-js
npm install jsencrypt
  1. AES加密工具类
import CryptoJS from 'crypto-js'
import { JSEncrypt } from 'jsencrypt'
/*** 创建密钥* @returns AES密钥*/
export function createAesKey() {const expect = 16let str = Math.random().toString(36).substr(2)while (str.length < expect) {str += Math.random().toString(36).substr(2)}str = str.substr(0, 16)return str
}
/*** AES加密* @param {*} word 加密字段* @param {*} keyStr AES密钥* @returns */
export function AESencrypt(word, keyStr) {keyStr = keyStr ? keyStr : 'abcdefgabcdefg12';var key = CryptoJS.enc.Utf8.parse(keyStr); //Latin1 w8m31+Yy/Nw6thPsMpO5fg==var srcs = CryptoJS.enc.Utf8.parse(word);var encrypted = CryptoJS.DES.encrypt(srcs, key, {mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});return encrypted.ciphertext.toString();
}
/*** RSA加密算法* @param {*} pas * @returns */
export function RSAencrypt(pas,publickey) {let jse = new JSEncrypt();jse.setPublicKey(publickey);return jse.encrypt(pas)}
  1. 服务端
    RSA工具类
import org.apache.commons.codec.binary.Base64;import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;public class RSAUtil {public static final String KEY_ALGORITHM = "RSA";public static final String SIGNATURE_ALGORITHM = "MD5withRSA";private static final String PUBLIC_KEY = "RSAPublicKey";private static final String PRIVATE_KEY = "RSAPrivateKey";public static byte[] decryptBASE64(String key) {return Base64.decodeBase64(key);}public static String encryptBASE64(byte[] bytes) {return Base64.encodeBase64String(bytes);}/*** 用私钥对信息生成数字签名** @param data       加密数据* @param privateKey 私钥* @return* @throws Exception*/public static String sign(byte[] data, String privateKey) throws Exception {// 解密由base64编码的私钥byte[] keyBytes = decryptBASE64(privateKey);// 构造PKCS8EncodedKeySpec对象PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);// KEY_ALGORITHM 指定的加密算法KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);// 取私钥匙对象PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);// 用私钥对信息生成数字签名Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);signature.initSign(priKey);signature.update(data);return encryptBASE64(signature.sign());}public static PrivateKey strToPrivateKey(String privateKey) throws Exception {// 解密由base64编码的私钥byte[] keyBytes = decryptBASE64(privateKey);// 构造PKCS8EncodedKeySpec对象PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);// KEY_ALGORITHM 指定的加密算法KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);// 取私钥匙对象return keyFactory.generatePrivate(pkcs8KeySpec);}/*** 校验数字签名** @param data      加密数据* @param publicKey 公钥* @param sign      数字签名* @return 校验成功返回true 失败返回false* @throws Exception*/public static boolean verify(byte[] data, String publicKey, String sign)throws Exception {// 解密由base64编码的公钥byte[] keyBytes = decryptBASE64(publicKey);// 构造X509EncodedKeySpec对象X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);// KEY_ALGORITHM 指定的加密算法KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);// 取公钥匙对象PublicKey pubKey = keyFactory.generatePublic(keySpec);Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);signature.initVerify(pubKey);signature.update(data);// 验证签名是否正常return signature.verify(decryptBASE64(sign));}public static byte[] decryptByPrivateKey(byte[] data, String key) throws Exception{// 对密钥解密byte[] keyBytes = decryptBASE64(key);// 取得私钥PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);// 对数据解密Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, privateKey);return cipher.doFinal(data);}/*** 解密<br>* 用私钥解密** @param data* @param key* @return* @throws Exception*/public static byte[] decryptByPrivateKey(String data, String key)throws Exception {return decryptByPrivateKey(decryptBASE64(data),key);}/*** 解密<br>* 用公钥解密** @param data* @param key* @return* @throws Exception*/public static byte[] decryptByPublicKey(byte[] data, String key)throws Exception {// 对密钥解密byte[] keyBytes = decryptBASE64(key);// 取得公钥X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key publicKey = keyFactory.generatePublic(x509KeySpec);// 对数据解密Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, publicKey);return cipher.doFinal(data);}/*** 加密<br>* 用公钥加密** @param data* @param key* @return* @throws Exception*/public static byte[] encryptByPublicKey(String data, String key)throws Exception {// 对公钥解密byte[] keyBytes = decryptBASE64(key);// 取得公钥X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key publicKey = keyFactory.generatePublic(x509KeySpec);// 对数据加密Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, publicKey);return cipher.doFinal(data.getBytes());}/*** 加密<br>* 用私钥加密** @param data* @param key* @return* @throws Exception*/public static byte[] encryptByPrivateKey(byte[] data, String key)throws Exception {// 对密钥解密byte[] keyBytes = decryptBASE64(key);// 取得私钥PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);// 对数据加密Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, privateKey);return cipher.doFinal(data);}/*** 取得私钥** @param keyMap* @return* @throws Exception*/public static String getPrivateKey(Map<String, Key> keyMap)throws Exception {Key key = (Key) keyMap.get(PRIVATE_KEY);return encryptBASE64(key.getEncoded());}/*** 取得公钥** @param keyMap* @return* @throws Exception*/public static String getPublicKey(Map<String, Key> keyMap)throws Exception {Key key = keyMap.get(PUBLIC_KEY);return encryptBASE64(key.getEncoded());}/*** 初始化密钥** @return* @throws Exception*/public static Map<String, Key> initKey() throws NoSuchAlgorithmException {KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);keyPairGen.initialize(1024);KeyPair keyPair = keyPairGen.generateKeyPair();Map<String, Key> keyMap = new HashMap(2);keyMap.put(PUBLIC_KEY, keyPair.getPublic());// 公钥keyMap.put(PRIVATE_KEY, keyPair.getPrivate());// 私钥return keyMap;}
}

DES工具类

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Locale;public class DESUtil {/*** DES解密算法* @param content 解密字段* @param key 解密密钥* @return*/public static String decryptedDES(String content,String key) {try {Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE, generateKey(key));byte[] buf = cipher.doFinal(hexStr2Bytes(content));return new String(buf, "utf-8");} catch (Throwable e) {e.printStackTrace();}return null;}private static SecretKey generateKey(String secretKey)throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");DESKeySpec keySpec = new DESKeySpec(secretKey.getBytes());keyFactory.generateSecret(keySpec);return keyFactory.generateSecret(keySpec);}public static byte[] hexStr2Bytes(String src) {src = src.trim().replace(" ", "").toUpperCase(Locale.US);int m = 0, n = 0;int iLen = src.length() / 2;byte[] ret = new byte[iLen];for (int i = 0; i < iLen; i++) {m = i * 2 + 1;n = m + 1;ret[i] = (byte) (Integer.decode("0x" + src.substring(i * 2, m) + src.substring(m, n)) & 0xFF);}return ret;}
}

解密算法
前端入参
encryptedWords DES加密后的报文
encryptedKey RSA算法加密过的DES密钥

import com.bull3d.core.tool.utils.RedisUtil;
import com.bull3d.system.user.cache.CacheNames;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;/*** @Author: zhangshl* @Date: 2021/4/10 17:21* @Modify: linyuchi* 重新编写解密算法。 2021/04/26*/
@Component
@AllArgsConstructor
public class DecryptUtil {private RedisUtil redisUtil;public String decrypt(String encryptedWords, String encryptedKey){// 解密aes密钥String privateKey = String.valueOf(redisUtil.get(CacheNames.SRA_KRY_PRIVATE));if (null == privateKey){return "";}try {String decrypt = new String(RSAUtil.decryptByPrivateKey(encryptedKey,privateKey));return DESUtil.decryptedDES(encryptedWords,decrypt);} catch (Exception e) {e.printStackTrace();return "";}}
}

前端获取RSA密钥,我其实在服务端设计密钥对放在redis服务器中。过期时间为1天,如果过期则从新生成。

    /*** 获取RSA秘钥*/@ApiOperation(value = "获取RSA秘钥")@GetMapping("/auth/rsa-key")public R<String> rsaKey(){String key = authService.getRsaKey();return R.data(key);}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/556374.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spring cloud微服务_年后进大厂,必备这份微服务面试题:Dubbo+SpringBoot+Cloud

Dubbo面试题Dubbo与DubboX区别Dubbo中zookeeper做注册中心&#xff0c;如果注册中心集群都挂掉&#xff0c;发布者和订阅者之间还能通信么&#xff1f;Dubbo中有哪些角色&#xff1f;Dubbo在安全机制方面是如何解决的Dubbo执行流程&#xff1f;Dubbo支持的协议有哪些&#xff1…

c语言交通违章编程代码,C语言程序设计之交通处罚单管理系统 报告(内含代码).doc...

C语言程序设计姓名&#xff1a;张强强学号&#xff1a;20121003695班序号&#xff1a;011121前言&#xff1a;C语言是近年来国内得到迅速推广使用的一种计算机语言。C语言程序设计课程是计算机专业和信息管理专业的核心专业基础课&#xff0c;无论是计算机专业还是非计算器专业…

前端 - token 是什么?为什么每次请求头(HEADS)里要携带它?___请求时,为什么要携带token?

前端 - token 是什么&#xff1f;为什么每次请求头&#xff08;HEADS&#xff09;里要携带它&#xff1f; Token token 是客户端频繁向服务器端请求数据&#xff0c;服务器频繁的去数据库查询用户名和密码进行对比&#xff0c;判断用户名和密码正确与否&#xff0c;并作出相应…

全栈工程师薪水_2020 Java 全栈工程师进阶路线图,不可错过

技术更新日新月异&#xff0c;对于初入职场或者刚开始学习的同学来说&#xff0c;经常会困惑该往那个方向发展&#xff0c;这一点所有刚开始学习的人基本都有这个体会的。刚开始学习 Java 那会&#xff0c;最大的问题就是不知道该学什么&#xff0c;以及学习的顺序&#xff0c;…

5乘7的c语言程序,C语言程序设计实验5-7教案(20页)-原创力文档

第 7-8 次课程名称 程序设计基础 课程性质 实验课授课班级 网络 16-1 、2 授课地点 14022016 年 11 月 9 日第 5 小节 ~第 8 小节授课时间 2016 年 11 月 16 日第 5 小节~第 8 小节2016 年 11 月 23 日第 5 小节~第 8 小节课题&#xff1a; 实验六、 数组的应用—— 4 学时主要…

python手机安装模块_python如何安装模块 模块安装操作教程

Python是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言&#xff0c;设计具有很强的可读性&#xff0c;相比其他语言经常使用英文关键字&#xff0c;它具有比其他语言更有特色语法结构。那么Python的安装模块该怎么使用呢&#xff1f;让小编来教一下各位吧。模…

cookie 和 token 都存放在 header 中,为什么不会劫持 token?____token和cookie的区别

cookie 和 token 都存放在 header 中&#xff0c;为什么不会劫持 token&#xff1f; cookie:登录后服务端生成的sessionid&#xff0c;并在http请求里返回到客户端&#xff0c;同时服务端保存sessionid&#xff0c;以后客户端的每次http请求都带上cookie&#xff08;sessionid…

语言inc c,汇编语言练习

习题一1&#xff0e;在计算机内部&#xff0c;计算机能够直接执行的程序语言是。A&#xff0e;汇编语言 B。C语言C&#xff0e;机器语言 D。高级语言2&#xff0e;在堆栈段中&#xff0c;存放栈顶地址的寄存器是。A&#xff0e;IP &#xff22;&#xff0e;SP &#xff23;&…

python降维之时间类型数据的处理_使用Python进行数据降维|线性降维

前言为什么要进行数据降维&#xff1f;直观地好处是维度降低了&#xff0c;便于计算和可视化&#xff0c;其深层次的意义在于有效信息的提取综合及无用信息的摈弃&#xff0c;并且数据降维保留了原始数据的信息&#xff0c;我们就可以用降维的数据进行机器学习模型的训练和预测…

cookie、Session、Token、sessionStorage、localStorage简介__Token放在 cookie, sessionStorage 和 localStorage中区别

cookie、Session、Token、sessionStorage、localStorage简介 cookie 是一个非常具体的东西&#xff0c;只得是浏览器里永久存储的一种数据&#xff0c;是浏览器实现的一种数据存储功能。Cookie在计算机中是个存储在浏览器目录中的文本文件&#xff0c;当浏览器运行时&#xf…

歌星大奖赛C语言程序,C_歌星大奖赛

在歌星大奖赛中&#xff0c;有10个评委为参赛的选手打分&#xff0c;分数为1~100分。选手最后得分为&#xff1a;去掉一个最高分和一个最低分后其余8个分数的平均值。请编写一个程序实现。*问题分析与算法设计这个问题的算法十分简单&#xff0c;但是要注意在程序中判断最大、最…

c语言树莓派音乐播放器,使用web端来控制我的树莓派播放音乐

8种机械键盘轴体对比本人程序员&#xff0c;要买一个写代码的键盘&#xff0c;请问红轴和茶轴怎么选&#xff1f;web端控制树莓派播放音乐&#xff0c;PHPNodeJSmpg123&#xff0c;粗糙版。实现后还可以做个app什么的。代码git用到的代码内容可以在这里看~nodempg.js启动一个se…

Nginx学习_狂神

Nginx 公司产品出现瓶颈&#xff1f; 我们公司项目刚刚上线的时候&#xff0c;并发量小&#xff0c;用户使用的少&#xff0c;所以在低并发的情况下&#xff0c;一个jar包启动应用就够了&#xff0c;然后内部tomcat返回内容给用户。 但是慢慢的&#xff0c;使用我们平台的用户…

c语言中运算符的读音是什么,操作符、运算符,operator,音标,读音,翻译,英文例句,英语词典...

补充资料&#xff1a;二进制算术运算二进制算术运算binary arithmetic operation二.165. 原码两位索法为了提高运算速度&#xff0c;在1次操作中可同时考虑两位乘数&#xff0c;求得与两位乘数相对应的部分积&#xff0c;其速度比一位乘法提商1倍&#xff0c;规则如下: 又丫1二…

python怎么重复输出_如何根据输出在Python中重复函数?

你可以用while循环来实现这一点。只要没有break或sys.exit&#xff0c;它就返回到start&#xff0c;这意味着这里的每一个错误输入。希望这有帮助def read_the_file(output):while True:print """Do you want me to read your newly created file?Type [Y]es o…

C语言读取load格式文件,求指导,如何用c语言实现读取*.raw格式图像

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼/*** 这个程序是读取jpg图像的** 后续加上jpg图像打开和存放*/ #include #include #include #include #include #define SOI 0xD8 //文件头#define EOI 0xD9 //文件尾#define APP0 0xE0 //定义交换格式和图像识别信息#define SOF0 …

js当前时间格式化_JS时间格式化

因为new Date().toLocaleString() 在安卓和ios上的格式不一致&#xff0c;所以尽量自己写format生成一个时间数组作为一个简单的举例&#xff0c;我序列化一周的时间对象声明参数let lastMonth []let daylong 86400000判断时间值是否小于9const formatNumber num > { num…

android json传输数据到服务器,Android中post请求传递json数据给服务端的实例

在最近的项目中有个需求是这样的&#xff1a;入参封装成JSON&#xff0c;EXAMPLE&#xff1a;{ "uuid": "iamauuid","clientType": "AND","content": "{\"gender\":\"F\",\"name\":\&qu…

springboot项目中使用shiro 自定义过滤器和token的方式___shiro使用token登录流程

springboot项目中使用shiro 自定义过滤器和token的方式 实现步骤主要是以下几步&#xff1a; 1. 在项目中导入maven依赖 <dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.4.0</versi…

window.print 点击取消后再次打印无效_教程 | 图书馆自助复印打印机使用方法

图书馆自助复印打印机教程当当当&#xff01;教程君又来辽~今天为大家介绍的是咱们图书馆霸气十足的自助复印打印机实行全程无人化管理为读者提供自助打印、复印、扫描服务是你学习的小帮手&#xff01;实行全程无人化管理为读者提供自助打印、复印、扫描服务读者可在校园内任意…