Java中RSA非对称密钥加解密使用示例

一、简介: RSA加密算法是最常用的非对称加密算法,CFCA在证书服务中离不了它。RSA是第一个比较完善的公开密钥算法,它既能用于加密,也能用于数字签名。这个算法经受住了多年深入的密码分析,虽然密码分析者既不能证明也不能否定RSA的安全性,但这恰恰说明该算法有一定的可信性,目前它已经成为最流行的公开密钥算法。

二、RSA的公钥、私钥的组成,以及加密、解密的公式可见于下表

三、使用方式:

①  假设A、B机器进行通信,已A机器为主;

②  A首先需要用自己的私钥为发送请求数据签名,并将公钥一同发送给B;

③  B收到数据后,需要用A发送的公钥进行验证,已确保收到的数据是未经篡改的;

④  B验签通过后,处理逻辑,并把处理结果返回,返回数据需要用A发送的公钥进行加密(公钥加密后,只能用配对的私钥解密);

⑤  A收到B返回的数据,使用私钥解密,至此,一次数据交互完成。

四、代码示例:

    1. 第一步获取私钥,为签名做准备。

      /**
           * 读取私钥  返回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);
          }  

    2. 签名示例  通过第一步得到的私钥,进行签名操作,具体请看以下代码:

      /**
           * 私钥签名: 签名方法如下: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); 

    3. 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;
              }
          }  

      至此,签名验签已经完毕

    4. 提供一个从.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;
          }  

    5. 附上所有代码: http://pan.baidu.com/share/link?shareid=23044&uk=2986731784本文转自:http://www.huosen.net/archives/124.html
时间: 2024-11-05 18:34:30

Java中RSA非对称密钥加解密使用示例的相关文章

Cryptography中的对称密钥加解密:fernet算法探究

原创文章,欢迎转发朋友圈,转载请注明出处 cryptography是python语言中非常著名的加解密库,在算法层面提供了高层次的抽象,使用起来非常简单.直观,pythonic,同时还保留了各种不同算法的低级别接口,保留灵活性. 我们知道加密一般分为对称加密(Symmetric Key Encryption)和非对称加密(Asymmetric Key Encryption).,各自对应多种不同的算法,每种算法又有不同的密钥位长要求,另外还涉及到不同的分组加密模式,以及末尾补齐方式.因此需要高层次

【加解密专辑】对接触到的PGP、RSA、AES加解密算法整理

先贴代码,有空再整理思路 PGP加密 using System; using System.IO; using Org.BouncyCastle.Bcpg; using Org.BouncyCastle.Bcpg.OpenPgp; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities.IO; using System.Linq; namespace Server5.V2.Common { public static c

Java 使用AES/CBC/PKCS7Padding 加解密字符串

介于java 不支持PKCS7Padding,只支持PKCS5Padding 但是PKCS7Padding 和 PKCS5Padding 没有什么区别要实现在java端用PKCS7Padding填充,需要用到bouncycastle组件来实现 所以需要一个jar 来支持.bcprov-jdk16-146.jar 下载地址:http://central.maven.org/maven2/org/bouncycastle/bcprov-jdk16/1.46/bcprov-jdk16-1.46.jar

C#RSA对接JAVA中RSA方式

C#中通过FromXmlString属性加载的是XML形式,而JAVA中用到的是解析后的PEM格式的字符串,总之读取证书中信息无非是转换方式问题 /// <summary> /// c# 使用 java 的公钥进行rsa加密 utf8编码 通过解析公钥加密数据 /// </summary> /// <param name="publickey"></param> /// <returns></returns> pu

关于rsa非对称加密、解密、签名、验签

测试数据: 1 var xmlprikey =""; 2 var xmlpubkey =""; 3 rsa = new RSACryption(); 4 //待处理字符串 5 var str="hello成功啊啊!¥%……&*([email protected]#$%^&*()@#$%^&*()_}::{>>?}{>?{?"; 6 var strlen= str.Length; 7 rsa.RSAKey(

php RSA公钥私钥加解密和验证用法

现在很多项目中会使用到rsa加解密和验证相关的技术,分别整理代码如下,方便记忆和使用. [签名和验证] 1 //获得签名 2 function getSign($data) { 3 $pem = 'my_rsa_private_key.pem'; 4 $privateKey = openssl_get_privatekey(file_get_contents($pem)); 5 openssl_sign($data, $sign, $privateKey); 6 openssl_free_key

程序中对密码进行加解密的C代码示例

问题的提出 在实际的软件项目中,经常涉及到对密码的处理,如用户登录密码.数据库密码.FTP密码等.为了增加软件的灵活性,一般都要求将这些密码放到一个配置文件中.但密码原文容易记录,若被软件入侵者获取,则后果不堪设想.因此我们不能直接将密码原文填入配置文件中,而要先对密码进行加密,然后将加密之后的密文填入配置文件,等程序读取配置之后再进行解密处理. 整个流程如图1所示. 图1 加解密总体流程 示例程序流程 为了演示整个加解密的流程,设计了一个演示程序,其执行流程如图2所示. 图2 示例程序流程 示

Java基础加密之BASE64加解密

BASE64加解密,加密与解密实际是指编码(encode)和解码(decode)的过程,其变换是非常简单的,仅仅能够避免信息被直接识别. Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式. Base64使用A--Z,a--z,0--9,+,/ 这64个字符. Base64是一种很常见的编码规范,其作用是将二进制序列转换为人类可读的ASCII字符序列 Base64编码表 Value Encoding  Value Encoding  Value Encodin

vue中使用base64进行加解密

vue进行Base64加解密 背景 项目中需要对特殊字符进行处理,避免json和数据库的特殊字符(""等)冲突,刚好学了信息安全,干脆整个加解密,wkk.. 使用步骤 打开dos,在项目根目录运行npm install --save js-base64 在组件中引入let Base64 = require('js-base64').Base64 使用 Base64.encode(明文) Base64.decode(密文) 原文地址:https://www.cnblogs.com/quj