基于RSA的前后端登陆密码加密JAVA实现(转)
RSA加密算法简介
SA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用。对极大整数做因数分解的难度决定了RSA算法的可靠性。换言之,对一极大整数做因数分解愈困难,RSA算法愈可靠。假如有人找到一种快速因数分解的算法的话,那么用RSA加密的信息的可靠性就肯定会极度下降。但找到这样的算法的可能性是非常小的。今天只有短的RSA钥匙才可能被强力方式解破。到目前为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。
RSA加密的java实现
实现的思路,由RSA随机生成一对公钥和私钥,公钥方到客户端,私钥放到服务端,发送数据的时候由公钥对传输数据进行加密,然后发送给服务端,服务端用私钥才能对数据进行解密.下面是代码实现的例子
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map; import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException; import org.apache.commons.codec.binary.Base64; public class MyRSAencryptionMethod { private static Map<Integer, String> keyMap = new HashMap<>(); // 用于封装随机产生的公钥与私钥 public static void main(String[] args) {
//生成公钥和私钥
genKeyPair();
//加密字符串
String message = "df723820";
System.out.println("随机生成的公钥为:" + keyMap.get(0));
System.out.println("随机生成的私钥为:" + keyMap.get(1));
String messageEn = encrypt(message, keyMap.get(0));
System.out.println("加密后的字符串为:" + messageEn);
String messageDe = decrypt(messageEn, keyMap.get(1));
System.out.println("还原后的字符串为:" + messageDe);
} //随机生成密钥对
public static void genKeyPair() {
// KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
KeyPairGenerator keyPairGen = null; try {
keyPairGen = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} // 初始化密钥对生成器,密钥大小为96-1024位
assert keyPairGen != null;
keyPairGen.initialize(1024, new SecureRandom());
// 生成一个密钥对,保存在keyPair中
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到私钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公钥
String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
// 得到私钥字符串
String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
// 将公钥和私钥保存到Map
keyMap.put(0, publicKeyString); //0表示公钥
keyMap.put(1, privateKeyString); //1表示私钥
} /** RSA公钥加密
* @param str 加密字符串
* @param publicKey 公钥
* @return 密文
*/
public static String encrypt(String str, String publicKey) {
//base64编码的公钥
byte[] decoded = Base64.decodeBase64(publicKey);
RSAPublicKey pubKey = null;
String outStr = null; try {
pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)));
} catch (InvalidKeySpecException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException | NoSuchPaddingException | NoSuchAlgorithmException e) {
e.printStackTrace();
}
//RSA加密
return outStr;
} /** RSA私钥解密
* @param str 加密字符串
* @param privateKey 私钥
* @return 铭文
*/
public static String decrypt(String str, String privateKey) {
//64位解码加密后的字符串
byte[] inputByte = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8));
//base64编码的私钥
byte[] decoded = Base64.decodeBase64(privateKey);
RSAPrivateKey priKey = null;
//RSA解密
Cipher cipher = null;
String outStr = null; try {
priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, priKey);
outStr = new String(cipher.doFinal(inputByte));
} catch (InvalidKeySpecException | NoSuchAlgorithmException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException e) {
e.printStackTrace();
}
return outStr;
}
}
运行结果:
随机生成的公钥为:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCi+2HgEYFX+8XgpNGK49hwufR3fWkD6vs8gll0qYsnF2RmjiL94w+UOP8IGjapzliZ1w8CFvJ5aO/U5ALG7AzlboZC8xl3n8nmCsVfGNtXQlo2PJVCNziP+6hFar5Jyo7t98Eg9MLQ/VY+qIKmUfd/AXnA12Teik+zGmQeeeGagwIDAQAB
随机生成的私钥为:MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKL7YeARgVf7xeCk0Yrj2HC59Hd9aQPq+zyCWXSpiycXZGaOIv3jD5Q4/wgaNqnOWJnXDwIW8nlo79TkAsbsDOVuhkLzGXefyeYKxV8Y21dCWjY8lUI3OI/7qEVqvknKju33wSD0wtD9Vj6ogqZR938BecDXZN6KT7MaZB554ZqDAgMBAAECgYBdY7A8xasY8FL9m1Pawx410cgsY/c14ILftE1wFOqAlt3YCiAw3NgDdflk+ihSesO4O0wFRYLhYOj0U0boF0B3lOLwefLndglMG1f0dM8lehHiaaDnl8kk5rdRjk3Xc2MCpglM7/Z5Tir9zuuaqS0Ps+cxop8Ebe92D1L4JPybOQJBAPbnGQleStYyrmAPcj6J1hhYCWm3V4H8csepAiMNAfsYwLN21Z8j7muiYTtHyTRTuXVn7KaJ1OKCT3qu5YkpcVUCQQCo/LReIR7xRjdsgvnf/G0Q5h6lyJ5w7FKmS/rWiKxRtGcG826MqJc1lP9iBtiHh9RY39s6LwXwxcZJySw01jx3AkEAs4fa9qrvs8zqasMQiVTkrpLlVU+Re907AN9txFrjA9g91sEkGDGiXfWWyeoq7berdSl6NKaoe4PRkx21ngTaeQJBAJdD3ZCExVXkLKiNdW7yXg7KbpSnyGv8nt8NFDQFk3pvqemm7kYqg3ALN69fwWNQStxjRbIHdaHY524VDeUeAHECQAzE19Ktuiq9xdBngwuojWnoYgKo59mJbqhJiykIdcrYsClcyyF0DMK36thg+KvCRzMLDYBjiyXsbVUXXZj0BRc=
加密后的字符串为:TtFXKWl6Kb3O8TcA0UmosQQcBdIFRdctViqh7OVtY/vX7j4ry2O0Ess+AxEYism4qHEnjPNsqqWTjWGpywDuR2VW+xpni7qLrDR4wmJea9Mp4952R1aLdzeHJy940jCBlXs9zzQHX2ymcmziN2//B2tr3VmHdaBjsX827IezMy8=
还原后的字符串为:df723820
再次运行一次结果:
随机生成的公钥为:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpah3f/oGknklFOCExGJXOXkmj5AwW9Hs6ABDR7DoGXPH08MmYYPZL7eD+baTavOb5/t3JJFswWqq/Uf2j9lCrZYaxDkwOmW/PuSkPxaKaxAnRlbdg6EFlh3j+gn1kxB+74cRQBplb1nqSVgCYSuqaSx8KlMAxv6X4XBKNcmlZHQIDAQAB
随机生成的私钥为:MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKlqHd/+gaSeSUU4ITEYlc5eSaPkDBb0ezoAENHsOgZc8fTwyZhg9kvt4P5tpNq85vn+3ckkWzBaqr9R/aP2UKtlhrEOTA6Zb8+5KQ/FoprECdGVt2DoQWWHeP6CfWTEH7vhxFAGmVvWepJWAJhK6ppLHwqUwDG/pfhcEo1yaVkdAgMBAAECgYBHczHWXohe3UMZpmqZQj0sJCf6rxtKMyIlfBGb930hYeHJ5COh2IMH0vOpWqTEfBcOKKdxRZwP8K1Cs1m95QxwDTpKGQ13pwvmLT0iv8Zo+OliRUpriPt+UE+zdO/wIJ3cpJr47nxSsYn4L5RqoJsWqpdJpj/MeB90QdyNM3muAQJBANjoIZ9bUlFJERzYVp0f0ZwBt16u30Ro4Fi6QniWp8Do6/xN0Fab0nuQI/GqRI8ZHdYlTpCgMMNtixz8kRTITbECQQDH8r0xhOuDUh29G+SuUQ+NqzszIwZjPlWBAmxE2ZOWiNx4P+nHWxu2rUlUcCp9c3c3t60SVoNR6Z9lm6msxgEtAkAitkNrNTofOAo9C4IQ8x6gUMX/qQyh7ga5LFWm5rVB8gSSBAHrWlR84bxe2FjQbbyQoLfJ/VjQbZ9trB2rrcKBAkBSgMS0RCZxv1ZqC7JmgygpyrfYt+EQ3k2lt/w4xJZzjPF75NNv4RYkYIhbgRTnQte0c+PEJ1J0YDPXV03B7snZAkEAsoeJzIlIfDLcbG9uVOdxgeyuyww3g72YA8/aOWBiTGZ625Ue5dzvbCI91bpXeBI1q2/aG1XeKasBVhU9+3J+fA==
加密后的字符串为:Am11mhbFpvhHzmq+jcyud7qP2suyDE6iAWpSBnWnE6kdQwvWFy6/ujbMqq6UdOpSf+9I4T8DGGTsFbCjc2Cbv1TDfe+S+IoWRBS4qz9EOc0+116+0yzrPpoIi5bxHcxLgSGfY21kXQHMwSK2TG4jQwPaT5/7CXBB++s2TRt1LSE=
还原后的字符串为:df723820
可以看出公钥每次都是一样。
RSA加密的前端用法
前端用crypto-js进行加密,
npm i jsencrypt,
然后页面头引入import JSEncrypt from 'jsencrypt';
const encrypt = new JSEncrypt();
encrypt.setPublicKey('你的公钥');
password = encrypt.encrypt(‘你的密码’);// 加密后的字符串
后续
在实际应用中RSA加密也还是远远不够,一般还会加入MD5加密的方式,以及加密验证,token等等方式作为请求连接的校验,比如后端加密一个MD5字符串,给前端之后,前端用特定组合加上传输数据返回一个RSA加密的字符串,后端接收后解密,然后和自身的字符串进行对比,以确认数据来源的准确性.
出处链接:https://www.jianshu.com/p/d1e303b976aa
基于RSA的前后端登陆密码加密JAVA实现(转)的更多相关文章
- 【SpringSecurity系列2】基于SpringSecurity实现前后端分离无状态Rest API的权限控制原理分析
源码传送门: https://github.com/ningzuoxin/zxning-springsecurity-demos/tree/master/01-springsecurity-state ...
- (转)也谈基于NodeJS的全栈式开发(基于NodeJS的前后端分离)
原文链接:http://ued.taobao.org/blog/2014/04/full-stack-development-with-nodejs/ 随着不同终端(pad/mobile/pc)的兴起 ...
- 基于 koajs 的前后端分离实践
一.什么是前后端分离? 前后端分离的概念和优势在这里不再赘述,有兴趣的同学可以看各个前辈们一系列总结和讨论: 系列文章:前后端分离的思考与实践(1-6) slider: 淘宝前后端分离实践 知乎提问: ...
- 也谈基于NodeJS的全栈式开发(基于NodeJS的前后端分离)
前言 为了解决传统Web开发模式带来的各种问题,我们进行了许多尝试,但由于前/后端的物理鸿沟,尝试的方案都大同小异.痛定思痛,今天我们重新思考了“前后端”的定义,引入前端同学都熟悉的NodeJS,试图 ...
- 基于NodeJS进行前后端分离
1.什么是前后端分离 传统的SPA模式:所有用到的展现数据都是后端通过异步接口(AJAX/JSONP)的方式提供的,前端只管展现. 从某种意义上来说,SPA确实做到了前后端分离,但这种方式存在两个问题 ...
- [转] 基于NodeJS的前后端分离的思考与实践(五)多终端适配
前言 近年来各站点基于 Web 的多终端适配进行得如火如荼,行业间也发展出依赖各种技术的解决方案.有如基于浏览器原生 CSS3 Media Query 的响应式设计.基于云端智能重排的「云适配」方案等 ...
- 基于NodeJS的全栈式开发(基于NodeJS的前后端分离)
也谈基于NodeJS的全栈式开发(基于NodeJS的前后端分离) 前言 为了解决传统Web开发模式带来的各种问题,我们进行了许多尝试,但由于前/后端的物理鸿沟,尝试的方案都大同小异.痛定思痛,今天我们 ...
- 基于Kubernetes实现前后端应用的金丝雀发布
基于Kubernetes实现前后端应用的金丝雀发布 公司的研发管理平台实现了Gitlab+Kubernetes的Devops,在ToB和ToC场景中,由于用户量大,且预发布环境和生产环境或多或少存在差 ...
- 前后端分离时代,Java 程序员的变与不变!
事情的起因是这样的,有个星球的小伙伴向邀请松哥在知乎上回答一个问题,原题是: 前后端分离的时代,Java后台程序员的技术建议? 松哥认真看了下这个问题,感觉对于初次接触前后端分离的小伙伴来说,可能都会 ...
随机推荐
- 如何用 Redis 统计独立用户访问量
众所周至,拼多多的待遇也是高的可怕,在挖人方面也是不遗余力,对于一些工作3年的开发,稍微优秀一点的,都给到30K的Offer,当然,拼多多加班也是出名的,一周上6天班是常态,每天工作时间基本都是超过1 ...
- vue学习-day01(vue指令)
目录: 1.什么是vue.js 2.为什么要学习前端的流行框架 3.框架和库的区别 4.后端MVC和前端的MVVM的区别 5.vue.js的基本代码--hollo world代 ...
- XML 浏览器支持
几乎所有的主流浏览器均支持 XML 和 XSLT. Mozilla Firefox 从 1.0.2 版本开始,Firefox 就已开始支持 XML 和 XSLT(包括 CSS). Mozilla Mo ...
- c# B/S下 如何优化文件上传速度和实现断点续传问题
IE的自带下载功能中没有断点续传功能,要实现断点续传功能,需要用到HTTP协议中鲜为人知的几个响应头和请求头. 一. 两个必要响应头Accept-Ranges.ETag 客户端每次提交下载请求时,服务 ...
- LOJ #539. 「LibreOJ NOIP Round #1」旅游路线 倍增floyd + 思维
考试的时候是这么想的: 求出每一个点花掉 $i$ 的花费向其他点尽可能走的最长距离,然后二分这个花费,找到第一个大于 $d$ 的就输出$.$然而,我这个记忆化搜索 $TLE$ 的很惨$.$这里讲一下正 ...
- Spring Cloud Stream教程(四)消费群体
虽然发布订阅模型可以轻松地通过共享主题连接应用程序,但通过创建给定应用程序的多个实例来扩展的能力同样重要.当这样做时,应用程序的不同实例被放置在竞争的消费者关系中,其中只有一个实例预期处理给定消息. ...
- Spring Cloud Stream教程(三)持续发布 - 订阅支持
应用之间的通信遵循发布订阅模式,其中通过共享主题广播数据.这可以在下图中看到,它显示了一组交互式的Spring Cloud Stream应用程序的典型部署. 图6. Spring Cloud Stre ...
- maven 高级玩法
maven 高级玩法 标签(空格分隔): maven 实用技巧 Maven 提速 多线程 # 用 4 个线程构建,以及根据 CPU 核数每个核分配 1 个线程进行构建 $ mvn -T 4 clean ...
- HBase调优案例(二)——高并发下bulkload出现超时
原因分析: 导入数据——>HBase,在客户端会发生非常多的rpc请求到regionServer,从而加大regionServer上的压力,如果regionServer比较忙碌(handle被占 ...
- Android由出生年月日计算年龄(周岁)
先从String类型的出生日期(“yyyy-MM-dd”)中提取int类型的年.月.日:再计算岁数. 程序如下: /** * 根据出生日期计算年龄的工具类BirthdayToAgeUtil */ pu ...