Java中RSA非对称密钥加解密使用示例
一、简介: RSA加密算法是最常用的非对称加密算法,CFCA在证书服务中离不了它。RSA是第一个比较完善的公开密钥算法,它既能用于加密,也能用于数字签名。这个算法经受住了多年深入的密码分析,虽然密码分析者既不能证明也不能否定RSA的安全性,但这恰恰说明该算法有一定的可信性,目前它已经成为最流行的公开密钥算法。
二、RSA的公钥、私钥的组成,以及加密、解密的公式可见于下表
三、使用方式:
① 假设A、B机器进行通信,已A机器为主;
② A首先需要用自己的私钥为发送请求数据签名,并将公钥一同发送给B;
③ B收到数据后,需要用A发送的公钥进行验证,已确保收到的数据是未经篡改的;
④ B验签通过后,处理逻辑,并把处理结果返回,返回数据需要用A发送的公钥进行加密(公钥加密后,只能用配对的私钥解密);
⑤ A收到B返回的数据,使用私钥解密,至此,一次数据交互完成。
四、代码示例:
- 第一步获取私钥,为签名做准备。
/**
* 读取私钥 返回PrivateKey
* @param path 包含私钥的证书路径
* @param password 私钥证书密码
* @return 返回私钥PrivateKey
* @throws KeyStoreException
* @throws NoSuchAlgorithmException
* @throws CertificateException
* @throws IOException
* @throws UnrecoverableKeyException
*/
private static PrivateKey getPrivateKey(String path,String password)
throws KeyStoreException, NoSuchAlgorithmException, CertificateException,
IOException, UnrecoverableKeyException {
KeyStore ks = KeyStore.getInstance("PKCS12");
FileInputStream fis = new FileInputStream(path);
char[] nPassword = null;
if ((password == null) || password.trim().equals("")) {
nPassword = null;
} else {
nPassword = password.toCharArray();
}
ks.load(fis, nPassword);
fis.close();
Enumeration<String> en = ks.aliases();
String keyAlias = null;
if (en.hasMoreElements()) {
keyAlias = (String) en.nextElement();
} return (PrivateKey) ks.getKey(keyAlias, nPassword);
} - 签名示例 通过第一步得到的私钥,进行签名操作,具体请看以下代码:
/**
* 私钥签名: 签名方法如下:BASE64(RSA(MD5(src),privatekey)),其中src为需要签名的字符串,
privatekey是商户的CFCA证书私钥。
* @param plainText 待签名字符串
* @param path 签名私钥路径
* @param password 签名私钥密码
* @return 返回签名后的字符串
* @throws Exception
*/
public static String sign(String plainText,String path,String password)
throws Exception {
/*
* MD5加密
*/
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(plainText.getBytes("utf-8"));
byte[] digestBytes = md5.digest();
/*
* 用私钥进行签名 RSA
* Cipher负责完成加密或解密工作,基于RSA
*/
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
//ENCRYPT_MODE表示为加密模式
cipher.init(Cipher.ENCRYPT_MODE, getPrivateKey(path, password));
//加密
byte[] rsaBytes = cipher.doFinal(digestBytes);
//Base64编码
return Base64.byteArrayToBase64(rsaBytes); - B收到数据后,需要使用A提供的公钥信息进行验签,此处使用公钥的N、E进行验签 首先通过公钥N、E得到公钥PublicKey,如下:
/**
* 根据公钥n、e生成公钥
* @param modulus 公钥n串
* @param publicExponent 公钥e串
* @return 返回公钥PublicKey
* @throws Exception
*/
public static PublicKey getPublickKey(String modulus, String publicExponent)
throws Exception {
KeySpec publicKeySpec = new RSAPublicKeySpec(
new BigInteger(modulus, 16), new BigInteger(publicExponent, 16));
KeyFactory factory = KeyFactory.getInstance("RSA");
PublicKey publicKey = factory.generatePublic(publicKeySpec);
return publicKey;
}得到公钥PublicKey后,再去验证签名,代码如下:
/**
* 用公钥证书进行验签
* @param message 签名之前的原文
* @param cipherText 签名
* @param pubKeyn 公钥n串
* @param pubKeye 公钥e串
* @return boolean 验签成功为true,失败为false
* @throws Exception
*/
public static boolean verify(String message, String cipherText,String pubKeyn,
String pubKeye) throws Exception {
Cipher c4 = Cipher.getInstance("RSA/ECB/PKCS1Padding");
// 根据密钥,对Cipher对象进行初始化,DECRYPT_MODE表示解密模式
c4.init(Cipher.DECRYPT_MODE, getPublickKey(pubKeyn,pubKeye));
// 解密
byte[] desDecTextBytes = c4.doFinal(Base64.base64ToByteArray(cipherText));
// 得到前置对原文进行的MD5
String md5Digest1 = Base64.byteArrayToBase64(desDecTextBytes);
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(message.getBytes("utf-8"));
byte[] digestBytes = md5.digest();
// 得到商户对原文进行的MD5
String md5Digest2 = Base64.byteArrayToBase64(digestBytes);
// 验证签名
if (md5Digest1.equals(md5Digest2)) {
return true;
} else {
return false;
}
}至此,签名验签已经完毕
- 提供一个从.cer文件读取公钥的方法:
/**
* 读取公钥cer
* @param path .cer文件的路径 如:c:/abc.cer
* @return base64后的公钥串
* @throws IOException
* @throws CertificateException
*/
public static String getPublicKey(String path) throws IOException,
CertificateException{
InputStream inStream = new FileInputStream(path);
ByteArrayOutputStream out = new ByteArrayOutputStream();
int ch;
String res = "";
while ((ch = inStream.read()) != -1) {
out.write(ch);
}
byte[] result = out.toByteArray();
res = Base64.byteArrayToBase64(result);
return res;
} - 附上所有代码: http://pan.baidu.com/share/link?shareid=23044&uk=2986731784本文转自:http://www.huosen.net/archives/124.html
Java中RSA非对称密钥加解密使用示例的更多相关文章
- RSA非对称式加解密笔记
1.服务器生成[公钥]和[私钥],成对生成: 2.客户端生成证书信息,使用[公钥]进行加密,前提是有公钥,并生成证书信息: 3.客户端发送自身的计算机名.MAC.用户名.证书内容给服务器: 4.服务器 ...
- Java & PHP RSA 互通密钥、签名、验签、加密、解密
RSA加密算法是一种非对称加密算法.在公开密钥加密和电子商业中RSA被广泛使用.RSA是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Le ...
- RSA 加解密 签名 示例
import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileOutputStrea ...
- java使用RSA与AES加密解密
首先了解下,什么是堆成加密,什么是非对称加密? 对称加密:加密与解密的密钥是相同的,加解密速度很快,比如AES 非对称加密:加密与解密的秘钥是不同的,速度较慢,比如RSA 先看代码(先会用在研究) 相 ...
- DH密钥加解密
一.概述 1.与对称加密算法的主要差别在于,加密和解密的密钥不相同,一个公开(公钥),一个保密(私钥).主要解决了对称加密算法密钥分配管理的问题,提高了算法安全性. 2.非对称加密算法的加密.解密的效 ...
- [转]RSA,DSA等加解密算法介绍
From : http://blog.sina.com.cn/s/blog_a9303fd90101cgw4.html 1) MD5/SHA MessageDigest是一个数据的数字指纹. ...
- 使用RSA非对称密钥算法实现硬件设备授权
一.硬件设备授权 即用户在硬件设备输入一个序列号(或一个包含授权信息的文件),然后硬件设备便可正常使用. 二.授权方案 构思授权方案时,参考了下面网址的思路: http://bbs.csdn.n ...
- Java 使用AES/CBC/PKCS7Padding 加解密字符串
介于java 不支持PKCS7Padding,只支持PKCS5Padding 但是PKCS7Padding 和 PKCS5Padding 没有什么区别要实现在java端用PKCS7Padding填充, ...
- 【加解密专辑】对接触到的PGP、RSA、AES加解密算法整理
先贴代码,有空再整理思路 PGP加密 using System; using System.IO; using Org.BouncyCastle.Bcpg; using Org.BouncyCastl ...
随机推荐
- 意外作出了一个javascript的服务器,可以通过js调用并执行任何java(包括 所有java 内核基本库)及C#类库,并最终由 C# 执行你提交的javascript代码! 不敢藏私,特与大家分
最近研发BDC 云开发部署平台的数据路由及服务管理器意外作出了一个javascript的服务器,可以通过js调用并执行任何java(包括 所有java 内核基本库)及C#类库,并最终由 C# 执行你提 ...
- 【基础知识】.Net基础加强08天
一. 文件的读取 1. 有FileStrem,为什么还要StreamWriter和StreamRead StreamWriter和StreamRead是用来读取文本文件的,每次只读取一行文本文件 二. ...
- .NET跨平台:在mac命令行下用vim手写ASP.NET 5 MVC程序
昨天在 Mac 上手写了一个最简单的 ASP.NET 5 程序,直接在 Startup.cs 中通过 Response.WriteAsync() 输出响应内容,详见 .NET跨平台:在Mac上跟着错误 ...
- 在Mac OS X上用自己编译出的CoreCLR运行.NET程序
当昨天被Mac OS X上无法编译CoreCLR的问题困扰时(详见Mac OS X上尝试编译CoreCLR源代码),后来发现这个难题竟然被神人@kangaroo给解决了,连CoreCLR的微软开发人员 ...
- NodeJS Hello world
#2 NodeJS Hello world 打开 https://nodejs.org/api/synopsis.html 将上述代码保存至D:\NODEJS\example.js 打开CMD窗口,定 ...
- 你应该知道的RPC原理
你应该知道的RPC原理 在学校期间大家都写过不少程序,比如写个hello world服务类,然后本地调用下,如下所示.这些程序的特点是服务消费方和服务提供方是本地调用关系. 而一旦踏入公司尤其是大型互 ...
- paip.文件读写api php java python总结.txt
paip.文件读写api php java python总结.txt 一.多种方式读文件内容. 1.按字节读取文件内容 以字节为单位读取文件,常用于读二进制文件,如图片.声音.影像等文件. ...
- 啊哈C!思考快你一步——用编程轻松提升逻辑力
啊哈C!思考快你一步——用编程轻松提升逻辑力(双色)(每个人都应该学习如何编程,因为它教会你如何思考.——史蒂夫.乔布斯) 啊哈磊著 ISBN 978-7-121-21336-6 2013年9月出版 ...
- 运用Mono.Ceci类库修改.NET程序集 走上破解软件的道路
代码注入在C++时代很流行,主要是对现有的程序做一些修改,以达到预期的目的.一部分的破解程序,注册机也是借助于此方法,让被注入的程序绕过验证,达到破解的目录.在.NET中,借助于Mono.Cecil程 ...
- nginx 配置其他路径
gedit /etc/nginx/sites-enabled/default location /hlstest { types { application/vnd.apple.mpegurl m3u ...