一、简介: 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

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

  1. RSA非对称式加解密笔记

    1.服务器生成[公钥]和[私钥],成对生成: 2.客户端生成证书信息,使用[公钥]进行加密,前提是有公钥,并生成证书信息: 3.客户端发送自身的计算机名.MAC.用户名.证书内容给服务器: 4.服务器 ...

  2. Java & PHP RSA 互通密钥、签名、验签、加密、解密

    RSA加密算法是一种非对称加密算法.在公开密钥加密和电子商业中RSA被广泛使用.RSA是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Le ...

  3. RSA 加解密 签名 示例

    import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileOutputStrea ...

  4. java使用RSA与AES加密解密

    首先了解下,什么是堆成加密,什么是非对称加密? 对称加密:加密与解密的密钥是相同的,加解密速度很快,比如AES 非对称加密:加密与解密的秘钥是不同的,速度较慢,比如RSA 先看代码(先会用在研究) 相 ...

  5. DH密钥加解密

    一.概述 1.与对称加密算法的主要差别在于,加密和解密的密钥不相同,一个公开(公钥),一个保密(私钥).主要解决了对称加密算法密钥分配管理的问题,提高了算法安全性. 2.非对称加密算法的加密.解密的效 ...

  6. [转]RSA,DSA等加解密算法介绍

    From : http://blog.sina.com.cn/s/blog_a9303fd90101cgw4.html 1)      MD5/SHA MessageDigest是一个数据的数字指纹. ...

  7. 使用RSA非对称密钥算法实现硬件设备授权

    一.硬件设备授权 即用户在硬件设备输入一个序列号(或一个包含授权信息的文件),然后硬件设备便可正常使用.    二.授权方案 构思授权方案时,参考了下面网址的思路: http://bbs.csdn.n ...

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

    介于java 不支持PKCS7Padding,只支持PKCS5Padding 但是PKCS7Padding 和 PKCS5Padding 没有什么区别要实现在java端用PKCS7Padding填充, ...

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

    先贴代码,有空再整理思路 PGP加密 using System; using System.IO; using Org.BouncyCastle.Bcpg; using Org.BouncyCastl ...

随机推荐

  1. 46 个非常有用的 PHP 代码片段

    在编写代码的时候有个神奇的工具总是好的!下面这里收集了 40+ PHP 代码片段,可以帮助你开发 PHP 项目. 这些 PHP 片段对于 PHP 初学者也非常有帮助,非常容易学习,让我们开始学习吧- ...

  2. IPv6协议

    IPv4协议仅能提供约2.5亿个IP地址, 即使使用CIDR和NAT等技术进行扩展也无法满足日益增长的需要. IETF于1996年开始研究下一代IP协议IPv6, 并于1998年12月正式公布(RFC ...

  3. 某些版本的IIS可能有SessionID混淆的Bug

    某公司为我服务的甲方公司开发一个挺重要的应用.已经上线了一年多了,不停的修修改改.也算正常使用.正所谓,秀恩爱,死得快.No 作就No Die.也少知道是那个Smarty Pants闲的蛋疼说新修改的 ...

  4. 免费好用的web应用托管平台

    1.前言 曾经很久以前,想找一个免费的空间部署一个属于自己的技术博客真是太难了,使用过SAE,但是很快就面临收费了,后面也就不了了之了.目前自己又找到一个免费的PAAS平台,可以部署各种语言的web应 ...

  5. dubbo的安装和使用

    dubbo的安装和使用

  6. IOS行货自动打包

    通常打包采用xcodebuild和xcrun两个命令,xcodebuild负责编译,xcrun负责将app打成ipa.   常见步骤如下: 1.清理工程 /usr/bin/xcodebuild -ta ...

  7. 还有人在用SQL Server 2000或2005吗? 2014来了!

    你的项目,还在用SQL Server 2000或2005吗? 很多人甚至还没有来得及用过SQL Server 2008,SQL Server 2012,现在SQL Server 2014已经出来了! ...

  8. 【简单易懂的AMV图文教程-2】VEGAS基础进阶——认识关键帧

    [简单易懂的AMV图文教程-2]VEGAS基础进阶--认识关键帧 经过了上一期VEGAS基础教程的学习,相信大家都能独立完成一些比较简单的纯剪辑作品了.今天在这里为大家继续介绍VEGAS的一大基础应用 ...

  9. React同构直出原理浅析

    通常,当客户端请求一个包含React组件页面的时候,服务端首先响应输出这个页面,客户端和服务端有了第一次交互.然后,如果加载组件的过程需要向服务端发出Ajax请求等,客户端和服务端又进行了一次交互,这 ...

  10. PlaceholderImageView

    PlaceholderImageView 说明 1. PlaceHolderImageView基于SDWebImage编写 2. 给定一个图片的urlString,以及一个placeholderIma ...