Java中RSA非对称密钥加解密使用示例
来源:互联网 发布:角谷猜想知乎 编辑:程序博客网 时间:2024/05/19 13:27
一、简介:
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://www.huosen.net/archives/124.html
0 0
- Java中RSA非对称密钥加解密使用示例
- Java中RSA非对称密钥加解密使用示例
- Java中RSA非对称密钥加解密使用示例
- Java中RSA非对称密钥加解密使用示例
- Java中RSA非对称密钥加解密使用示例
- Java中RSA非对称密钥加解密使用示例
- Java中RSA非对称密钥加解密使用
- RSA非对称密钥加解密使用示例
- Android 使用RSA 非对称加解密
- 非对称加解密(RSA)
- RSA 非对称加解密
- RSA非对称加解密
- RSA非对称加解密算法的使用
- C#RSA非对称加解密
- 非对称加解密基础 - RSA算法
- openssl RSA 非对称加解密
- RSA 非对称加解密算法
- iOS RSA非对称加解密
- BTS PenTesting Lab - Installation
- Hadoop2.7.1概述
- logm--求矩阵的对数
- apache的安装配置 & Tomcat 安装配置
- Ajax跨域、Json跨域、Socket跨域和Canvas跨域等同源策略限制的解决方法
- Java中RSA非对称密钥加解密使用示例
- C++ Primer Plus 第六版(中文版)课后编程题----第三章
- GDI+ 双缓冲实现和局部刷新技术
- 高斯曲线拟合原理及实现
- ViewController生命周期
- Jsoup 网页抓取数据之获取汽车时刻表 实例解析
- UVA146 ID codes
- 递归解决全排列
- spring boot jsp