RSA加密原理使用方式签名验证

加密是网络传输中非常重要的一环,它保证了信息的安全性,让他人无法通过抓包来获取通讯的信息也无法通过伪造信息而实现对系统的入侵。其中最为常用的信息传递加密方式就是RSA加密。

RSA加密原理

RSA与传统加密方式不同的是,他是非对称加密,可以在不直接传递密钥的情况下,完成解密。这能够确保信息的安全性,避免了直接传递密钥所造成的被破解的风险。
RSA加密方式是:
(1)乙方生成两把密钥(公钥和私钥)。公钥是公开的,任何人都可以获得,私钥则是保密的。
(2)甲方获取乙方的公钥,然后用它对信息加密。
(3)乙方得到加密后的信息,用私钥解密。
RSA非对称加密算法的原理请参照下面两篇文章,本文主要讲述RSA加密在java程序中的使用。其概念是利用大整数的质数分解的困难性来保障密钥不被破解。

RSA算法原理part1
RSA算法原理part2

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+aes加密传输工具及案例

RSA加密原理使用方式签名验证的更多相关文章

  1. php rsa加密解密实例 及签名验证-自己实践

      <?php /** * Created by PhpStorm. * User: Administrator * Date: 2018/4/1 * Time: 1:50 */ //注意格式一 ...

  2. RSA加密原理与秘钥、公钥生成

    RSA加密(非对称加密) RSA公开密钥密码体制.所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制.(不可逆向运算的加密方法) ...

  3. RSA加密的方式和解密方式

    RSAsecurity.java package com.mstf.rsa; import java.security.KeyFactory; import java.security.KeyPair ...

  4. RSA 非对称加密原理(小白也能看懂哦~)

    来源. https://blog.csdn.net/jijianshuai/article/details/80582187 RSA 加密原理 步骤 说明 描述 备注 1 找出质数 P .Q - 2 ...

  5. rsa加密初探

    RSA加密算法初探 RSA加密算法是早期的非对称加密,公钥和私钥分离,公开公钥,通过确保私钥的安全来保证加密内容的安全.由麻省理工学院的罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi ...

  6. RSA加密、解密、公钥私钥生成

    有时项目中需要用到一些加密和解密工具,这里之前整理了一个demo,记录一下,方便查询 package com.test; import java.security.KeyFactory; import ...

  7. When I see you again(加密原理介绍,代码实现DES、AES、RSA、Base64、MD5)

    关于网络安全的数据加密部分,本来打算总结一篇博客搞定,没想到东西太多,这已是第三篇了,而且这篇写了多次,熬了多次夜,真是again and again.起个名字:数据加密三部曲,前两部链接如下: 整体 ...

  8. Atitit RSA非对称加密原理与解决方案

    Atitit RSA非对称加密原理与解决方案 1.1. 一.一点历史 1 1.2. 八.加密和解密 2 1.3. 二.基于RSA的消息传递机制  3 1.4. 基于rsa的授权验证机器码 4 1.5. ...

  9. IOS RSA 加密方式

    采用RSA加密方式,主要是生成公钥和私钥,公钥用来加密,私钥用来解密,至于其中如何实现的,网上有很多原理. 参见如下: https://github.com/jslim89/RSA-objc PS: ...

随机推荐

  1. English Conversation – NUMBERS

    English Conversation – NUMBERS Share Tweet Share Tagged With: Numbers Study the pronunciation of num ...

  2. RabbitMQ.Net 应用(1)

    风浪子 概述 MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Pu ...

  3. Extjs动态增删组件

    在项目中遇到要动态的增加删除一个组件,于是就查找资料,实现了下面的效果. Ext.onReady(function(){ // Ext.Msg.alert("提示","h ...

  4. [Nginx]实战Nginx:Nginx服务器的安装与配置

    ----------------------------------------------------------------------------------------------- Ngin ...

  5. JAVAWEB 一一 Spirng(AOP面向切面)

    applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <!-- < ...

  6. ArcGIS案例学习笔记-批处理擦除挖空挖除相减

    ArcGIS案例学习笔记-批处理擦除挖空挖除相减 联系方式:谢老师,135-4855-4328,xiexiaokui#qq.com 目的:批处理擦除.挖空.挖除.相减 数据源:chp13/ex5/pa ...

  7. MD5加密和彩虹表

    首先叙述一下彩虹表的原理.本部分内容.图片和例子基本来自英文维基的Rainbow table词条(Rainbow table)——中文维基中目前(2013年10月9日)尚无对应的词条——因此对本答案中 ...

  8. tf.name_scope()和tf.variable_scope() (转)

    网络层中变量存在两个问题: 随着层数的增多,导致变量名的增多: 在调用函数的时候,会重复生成变量,但他们存储的都是一样的变量.   tf.variable不能解决这个问题. 变量作用域使用tf.var ...

  9. js正则表达式子校验

    //正则表达式校验new RegExp(/^[1-9]\d{4,8}$/,"g").test(1234);//执行一个字符串所表达的方法 eval(this['字符串']) 正则表 ...

  10. jquery 页面传值 汉字

    function getURLParameter(name) { return decodeURIComponent( (new RegExp('[?|&]' + name + '=' + ' ...