RSA加密原理使用方式签名验证
RSA加密原理使用方式签名验证
加密是网络传输中非常重要的一环,它保证了信息的安全性,让他人无法通过抓包来获取通讯的信息也无法通过伪造信息而实现对系统的入侵。其中最为常用的信息传递加密方式就是RSA加密。
RSA加密原理
RSA与传统加密方式不同的是,他是非对称加密,可以在不直接传递密钥的情况下,完成解密。这能够确保信息的安全性,避免了直接传递密钥所造成的被破解的风险。
RSA加密方式是:
(1)乙方生成两把密钥(公钥和私钥)。公钥是公开的,任何人都可以获得,私钥则是保密的。
(2)甲方获取乙方的公钥,然后用它对信息加密。
(3)乙方得到加密后的信息,用私钥解密。
RSA非对称加密算法的原理请参照下面两篇文章,本文主要讲述RSA加密在java程序中的使用。其概念是利用大整数的质数分解的困难性来保障密钥不被破解。
RSA加密传输的实现
在加密前首先要生成秘钥,秘钥的生成可以使用java中的security包下的KeyPairGenerator来生成指定位数的秘钥。生成的秘钥为byte类型,一般可以用文件保存在使用的时候读取,但是为了方便写在程序里也可以用base64编码成字符串,在使用的时候用base64解码然后获得秘钥的对象。
密钥生成:
/*创建非对称加密的公钥和私钥示例 将生成的公钥和私钥用Base64编码后打印出来*/
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048); //一般加密位数为1024 对安全要求较高的情况下可以使用2048
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
/*将公钥base64编码打印出来*/ System.out.println(Base64.encodeBase64String(publicKey.getEncoded()));
/*将私钥base64编码打印出来*/ System.out.println(Base64.encodeBase64String(privateKey.getEncoded()));
加密我们需要先将密钥字符串base64解码然后生成密钥对象然后使用。
在java提供的jdk1.5中已经提供了相关加密工具类Cipher类,使用起来也比较方便
加密:
/*公钥字符串*/
String pubKey="base64编码的公钥";
/*X.509 标准中定义的公钥编码标准,使用这个类进行转换*/
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
//获得公钥对象
PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
String msg="需要加密的内容";
/*使用Cipher加密*/
/*定义加密方式*/
Cipher cipher = Cipher.getInstance("RSA");
/*使用公钥和加密模式初始化*/
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
/*获取加密内容以UTF-8为标准转化的字节进行加密后再使用base64编码成字符串*/
/*加密后的字符串*/
String enmsg=Base64.encodeBase64String(cipher.doFinal(plainText.getBytes("UTF-8")));
然后同理反向解密
解密:
String priKey="base64编码的私钥";
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(baiduPriKey));
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
String msg="加密后的内容";
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
/*解密后的内容*/
String demsg = new String(cipher.doFinal(Base64.decodeBase64(msg)), "UTF-8");
以上就是加密解密的过程
RSA签名的实现
RSA加密生成的公钥和私钥实际上是一对互相可以加密解密的钥匙对,换句话说 你可以用私钥加密,用公钥解密。但是由于一些特定的加密工具为了方便加密传输位数而指定了公钥的秘钥值,私钥是根据公钥的值计算得出的,所以一般私钥比较大且安全性更高,留作自己系统去解密其他系统传来的数据。
但是我们说道,公钥是可能给复数个其他系统的,你无法得知是哪个系统给你传输的这个数据,所以就有了签名这一说。现在有甲乙两个系统,甲系统要给乙系统传输数据,甲系统的数据使用自己的私钥对传递的信息进行加密,然后加一个签名字段放入要传输的数据中然后整体数据再使用公钥进行加密,传输给乙系统。乙系统拿到数据后,先使用自己的私钥解密数据,然后剔除签名字段,然后解密签名字段看与剔除签名字段的数据进行对比,这一步叫做验签,如果相等则代表此数据时由甲方传来且数据没有被篡改。
java中也提供了相应的签名方法类Signature可以直接使用,现在假设使用json字符串传输做一次签名验签的案例
签名:
/* 1. 准备发送的数据 为保证顺序正确这里使用TreeMap*/
TreeMap<String, String> map = new TreeMap<String, String>();
map.put("msg1", "1324679");
map.put("msg2", "A001");
map.put("msg3", "V1.0");
map.put("msg4", "");
/* 2. 计算验签字段, sign字段不参与签名 map转String方法可以自定义*/
String line = JSON.toJSONString(map);
PrivateKey privateKey="自己的私钥";
//设置签名加密方式
Signature signature = Signature.getInstance("RSA");
signature.initSign(privateKey);//设置私钥
//签名和加密一样 要以字节形式 utf-8字符集得到字节
signature.update(line.getBytes("UTF-8"));
//得到base64编码的签名后的字段
String sign = Base64.encodeBase64String(signature.sign());
//将签名放入map
map.put("sign", sign);
//将要传输的数据转成json
String request = JSON.toJSONString(map);
/*进行传输(可进行正常加密)*/
.......
验签:
...
/*获得请求过来的request(若加密请解密)并转换成map*/
TreeMap<String, String> map = JSON.parseObject(request, new TypeReference<TreeMap<String, String>>() {});
String sign = map2.get("sign");//获得签名
map2.remove("sign");//剔除签名
String line = JSON.toJSONString(map);//转化为字符串
PublicKey publicKey = "对方给的公钥";
//指定签名类型
Signature signature = Signature.getInstance("RSA");
signature.initVerify(publicKey);//放入公钥
signature.update(line .getBytes("UTF-8"));//放入数据
//验签结果
boolean isPassed= signature.verify(Base64.decodeBase64(sign));
System.out.println("验签结果 : " + isPassed);
实际使用的优化方法
rsa算法是一种取模计算,当加密位数很大时(比如2048位生成密钥),实际上消耗的计算量还是很大的,而且由于有签名的存在,相当于传了两份数据过去,一正一反加密验签消耗的计算量就非常大了,为了优化加密传输及减少系统计算量,我们一般需要采取一些优化方法:
1.采取散列算法简化签名
签名实际上只需要验证数据是否没有被篡改/是否是对方系统发来的数据 实际上是没有必要吧整个数据都进行加密传输,可以使用散列算法来进行压缩验证,常用的有sha256和md5,然后将计算后的值进行签名,接收方使用同样的方法进行压缩验签。
2.生成随机对称加密密钥,使用对称加密加密数据,然后将密钥进行RSA加密明文传输
第一种优化虽然优化了签名,减少了数据传输和运算,但是数据本体还是很大,使用rsa加密仍然需要消耗大量的计算能力,于是就有了这种加密方式,生成随机的密钥对称加密数据,然后将对称的密钥进行rsa加密明文传输,对方接受到对称密钥的rsa加密后的字符串,再用私钥解密,得到对称加密的密钥对数据进行解密。
最后附上完整的加密案例及整理的加密解密工具类:
RSA加密原理使用方式签名验证的更多相关文章
- php rsa加密解密实例 及签名验证-自己实践
<?php /** * Created by PhpStorm. * User: Administrator * Date: 2018/4/1 * Time: 1:50 */ //注意格式一 ...
- RSA加密原理与秘钥、公钥生成
RSA加密(非对称加密) RSA公开密钥密码体制.所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制.(不可逆向运算的加密方法) ...
- RSA加密的方式和解密方式
RSAsecurity.java package com.mstf.rsa; import java.security.KeyFactory; import java.security.KeyPair ...
- RSA 非对称加密原理(小白也能看懂哦~)
来源. https://blog.csdn.net/jijianshuai/article/details/80582187 RSA 加密原理 步骤 说明 描述 备注 1 找出质数 P .Q - 2 ...
- rsa加密初探
RSA加密算法初探 RSA加密算法是早期的非对称加密,公钥和私钥分离,公开公钥,通过确保私钥的安全来保证加密内容的安全.由麻省理工学院的罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi ...
- RSA加密、解密、公钥私钥生成
有时项目中需要用到一些加密和解密工具,这里之前整理了一个demo,记录一下,方便查询 package com.test; import java.security.KeyFactory; import ...
- When I see you again(加密原理介绍,代码实现DES、AES、RSA、Base64、MD5)
关于网络安全的数据加密部分,本来打算总结一篇博客搞定,没想到东西太多,这已是第三篇了,而且这篇写了多次,熬了多次夜,真是again and again.起个名字:数据加密三部曲,前两部链接如下: 整体 ...
- Atitit RSA非对称加密原理与解决方案
Atitit RSA非对称加密原理与解决方案 1.1. 一.一点历史 1 1.2. 八.加密和解密 2 1.3. 二.基于RSA的消息传递机制 3 1.4. 基于rsa的授权验证机器码 4 1.5. ...
- IOS RSA 加密方式
采用RSA加密方式,主要是生成公钥和私钥,公钥用来加密,私钥用来解密,至于其中如何实现的,网上有很多原理. 参见如下: https://github.com/jslim89/RSA-objc PS: ...
随机推荐
- java swing 制作一个登陆界面,亲测有效
一.介绍 Swing 是一个为Java设计的GUI工具包. Swing是JAVA基础类的一部分. Swing包括了图形用户界面(GUI)器件如:文本框,按钮,分隔窗格和表. Swing提供许多比AWT ...
- leetcode 错误题解,反面教材 Gas Station
class Solution { public: int canCompleteCircuit(vector<int>& gas, vector<int>& c ...
- js 提示框的实现---组件开发之(一)
自己做了一个简单的提示框,供自己使用,也可以供他人参考,看懂此文,是理解组件开发的入门 思路比较简单: 1.常规写法: 1.1. 创建一个构造函数 1.2. 给构造函数的原型对象添加show 和hid ...
- CAS单点登录原理解析
转自: https://www.cnblogs.com/lihuidu/p/6495247.html 1.基于Cookie的单点登录的回顾 基于Cookie的单点登录核心原理: 将用户名 ...
- 尚硅谷springboot学习8-yaml基本语法
1.基本语法 k:(空格)v:表示一对键值对(空格必须有): 以空格的缩进来控制层级关系:只要是左对齐的一列数据,都是同一个层级的 server: port: 8081 path: /hello 属性 ...
- PHP多例模式介绍_PHP教程
1.多例类可以有多个实例2.多例类必须能够自我创建并管理自己的实例,并向外界提供自己的实例. 大家都知道PHP单例模式,却很少说PHP多例模式,下面是在wikipedia上看到的PHP多例模式的例子: ...
- 在CentOS7中利用yum命令安装mysql
在CentOS7中利用yum命令安装mysql 原创 2016年08月31日 10:42:33 标签: mysql / centos 4832 一.说明 我们是在VMware虚拟机上安装的mysql, ...
- 理解AppDomain和AppPool
应用程序池: 这是微软的一个全新概念:应用程序池是将一个或多个应用程序链接到一个或多个工作进程集合的配置.因为应用程序池中的应用程序与其他应用程序被工作进程边界分隔,所以某个应用程序池中的应用程序不会 ...
- c语言基本数据类型及存储方式
; ; ; ; ; ; ; ; float a9 = 109.23; float a10 = 111.23; double a11 = 113.113; double a12 = 115.113; c ...
- js版RSA算法
// RSA, a suite of routines for performing RSA public-key computations in// JavaScript.//// Requires ...