最近有一个外部合作项目要求在数据传输过程中使用RSA加密算法对数据进行加密,所以需要编写一个加解密的工具类,因为对方不是java语言,所以是各自实现的这个工具,本文主要讨论实现以及双方调试过程中的一些插曲,希望给大家不要再次踩坑。
关于加解密的核心部分,网上有很多博主都有实现过,我也是参考了一些博主的方法自己实现了一个加解密的工具。
package com.tomcat360.third.util.RSA;import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;import javax.crypto.Cipher;import org.apache.commons.codec.binary.Base64;
import org.apache.tomcat.util.http.fileupload.IOUtils;/*** RSA加密解密 此工具类能使用指定的字符串,每次生成相同的公钥和私钥且在linux和windows密钥也相同;相同的原文和密钥生成的密文相同*/
public class RSAUtil {public static final String CHARSET = "UTF-8";public static final String RSA_ALGORITHM = "RSA";public static Map<String, String> createKeys(int keySize){//为RSA算法创建一个KeyPairGenerator对象KeyPairGenerator kpg;try{kpg = KeyPairGenerator.getInstance(RSA_ALGORITHM);}catch(NoSuchAlgorithmException e){throw new IllegalArgumentException("No such algorithm-->[" + RSA_ALGORITHM + "]");}//初始化KeyPairGenerator对象,密钥长度kpg.initialize(keySize);//生成密匙对KeyPair keyPair = kpg.generateKeyPair();//得到公钥Key publicKey = keyPair.getPublic();String publicKeyStr = Base64.encodeBase64URLSafeString(publicKey.getEncoded());//得到私钥Key privateKey = keyPair.getPrivate();String privateKeyStr = Base64.encodeBase64URLSafeString(privateKey.getEncoded());Map<String, String> keyPairMap = new HashMap<String, String>();keyPairMap.put("publicKey", publicKeyStr);keyPairMap.put("privateKey", privateKeyStr);return keyPairMap;}/*** 得到公钥* @param publicKey 密钥字符串(经过base64编码)* @throws Exception*/public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {//通过X509编码的Key指令获得公钥对象KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);return key;}/*** 得到私钥* @param privateKey 密钥字符串(经过base64编码)* @throws Exception*/public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {//通过PKCS#8编码的Key指令获得私钥对象KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);return key;}/*** 公钥加密* @param data* @param publicKey* @return*/public static String publicEncrypt(String data, RSAPublicKey publicKey){try{Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, publicKey);return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), publicKey.getModulus().bitLength()));}catch(Exception e){throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);}}/*** 私钥解密* @param data* @param privateKey* @return*/public static String privateDecrypt(String data, RSAPrivateKey privateKey){try{Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, privateKey);return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), privateKey.getModulus().bitLength()), CHARSET);}catch(Exception e){throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);}}/*** 私钥加密* @param data* @param privateKey* @return*/public static String privateEncrypt(String data, RSAPrivateKey privateKey){try{Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, privateKey);return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), privateKey.getModulus().bitLength()));}catch(Exception e){throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);}}/*** 公钥解密* @param data* @param publicKey* @return*/public static String publicDecrypt(String data, RSAPublicKey publicKey){try{Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, publicKey);return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), publicKey.getModulus().bitLength()), CHARSET);}catch(Exception e){throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);}}private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize){int maxBlock = 0;if(opmode == Cipher.DECRYPT_MODE){maxBlock = keySize / 8;}else{maxBlock = keySize / 8 - 11;}ByteArrayOutputStream out = new ByteArrayOutputStream();int offSet = 0;byte[] buff;int i = 0;try{while(datas.length > offSet){if(datas.length-offSet > maxBlock){buff = cipher.doFinal(datas, offSet, maxBlock);}else{buff = cipher.doFinal(datas, offSet, datas.length-offSet);}out.write(buff, 0, buff.length);i++;offSet = i * maxBlock;}}catch(Exception e){throw new RuntimeException("加解密阀值为["+maxBlock+"]的数据时发生异常", e);}byte[] resultDatas = out.toByteArray();IOUtils.closeQuietly(out);return resultDatas;}public static void main (String[] args) throws Exception {Map<String, String> keyMap = RSAUtil.createKeys(1024);String  publicKey = keyMap.get("publicKey");String  privateKey = keyMap.get("privateKey");System.out.println("公钥: \n\r" + publicKey);System.out.println("私钥: \n\r" + privateKey);System.out.println("公钥加密——私钥解密");String str = "站在大明门前守卫的禁卫军,事先没有接到\n" +"有关的命令,但看到大批盛装的官员来临,也就\n" +"以为确系举行大典,因而未加询问。进大明门即\n" +"为皇城。文武百官看到端门午门之前气氛平静,\n" +"城楼上下也无朝会的迹象,既无几案,站队点名\n" +"的御史和御前侍卫“大汉将军”也不见踪影,不免\n" +"心中揣测,互相询问:所谓午朝是否讹传?";System.out.println("\r明文:\r\n" + str);System.out.println("\r明文大小:\r\n" + str.getBytes().length);String encodedData = RSAUtil.publicEncrypt(str, RSAUtil.getPublicKey(publicKey));System.out.println("密文:\r\n" + encodedData);String decodedData = RSAUtil.privateDecrypt(encodedData, RSAUtil.getPrivateKey(privateKey));System.out.println("解密后文字: \r\n" + decodedData);}
}

实现基本上就是这样,都是大同小异。不过,问题来了,结下来才是重点。
**1. RSA加密算法对于加密数据的长度是有要求的。一般来说,明文长度小于等于密钥长度(Bytes)-11。解决这个问题需要对较长的明文进行分段加解密,这个上面的代码已经实现了。
2. 一旦涉及到双方开发,语言又不相同,不能够采用同一个工具的时候,切记要约定以下内容。
a)约定双方的BASE64编码
b)约定双方分段加解密的方式。我踩的坑也主要是这里,不仅仅是约定大家分段的大小,更重要的是分段加密后的拼装方式。doFinal方法加密完成后得到的仍然是byte[],因为最终呈现的是编码后的字符串,所以你可以分段加密,分段编码和分段加密,一次编码两种方式(上面的代码采用的是后一种,也推荐采用这一种)。相信我不是所有人的脑回路都一样的,尤其是当他采用的开发语言和你不通时。**

RSA加密解密算法的java实现相关推荐

  1. RSA加密解密及数字签名Java实现--转

    RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的.当时他们三人都在麻省理工学院 ...

  2. rsa加解密算法报告c语言,RSA加密解密算法c语言程序Word版

    <RSA加密解密算法c语言程序Word版>由会员分享,可在线阅读,更多相关<RSA加密解密算法c语言程序Word版(5页珍藏版)>请在人人文库网上搜索. 1.传播优秀Word版 ...

  3. golang实现RSA加密解密算法

    golang实现RSA加密解密算法 前言 一.生成密钥对(公钥私钥) 二.根据公钥加密 二.根据私钥解密 总结 前言 直接看正文吧! 一.生成密钥对(公钥私钥) 代码如下(示例): //生成私钥pri ...

  4. python实现rsa加密源代码_python实现RSA加密(解密)算法

    RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准. 今天只有短的RSA钥匙才可能被强力方式解破.到2008年为止,世界上还没有任何可靠 ...

  5. java php rsa加密解密算法_PHP rsa加密解密算法原理解析

    php服务端与客户端交互.提供开放api时,通常需要对敏感的部分api数据传输进行数据加密,这时候rsa非对称加密就能派上用处了,下面通过一个例子来说明如何用php来实现数据的加密解密 1.加密解密的 ...

  6. RSA加密解密算法代码实现【scalajava】

    1. 什么是RSA加密算法? 1.1 对称加密和非对称加密 对称加密:对称加密指的就是加密和解密使用同一个秘钥,所以叫做对称加密.对称加密只有一个秘钥,作为私钥.常见的对称加密算法:DES,AES,3 ...

  7. 用实例给新手讲解易懂的RSA加密解密算法

    用实例给新手讲解易懂的RSA加密算法 RSA加密算法是最常用的非对称加密算法,CFCA在证书服务中离不了它.我查过论坛上很少这方面的介绍,恰好看到一本书中作者用实例对它进行了简化而生动的描述,使得高深 ...

  8. RSA 加密解密算法实现(简单,易懂)!!!

    目录 一.什么是RSA算法 1.对称加密 2.非对称加密 3.非对称加密的应用 二.RSA算法的基础操作步骤 1.生成公钥和私钥 2.用公钥加密信息 3.用私钥解密信息 三.AC代码 六.RSA算法的 ...

  9. RSA加密解密算法工具_JAVA

    这个版本绝对能用,本人亲测 注意:需要下载两个jar包 [commons-codec-1.11-bin.zip]下载地址如下: http://commons.apache.org/proper/com ...

最新文章

  1. 几种常用的C#排序方法简介
  2. 年薪百万的华为「天才少年」:谢凌曦分享「进阶」之路,选题最重要!
  3. div居中 边框设置 文字行高设置
  4. 网上书店 整体需求分析
  5. 存储块的删除与状态查询
  6. SOCKET,TCP/UDP,HTTP,FTP
  7. 《Web前端开发修炼之道》-读书笔记CSS部分
  8. python虚拟cpu性能_基于Tensorflow:CPU性能分析
  9. 【图像隐写】基于matlab分层自嵌入数字水印内容认证与恢复【含Matlab源码 1641期】
  10. 数组实现c语言学生成绩管理系统
  11. fgui的ui管理框架_ET框架FGUIxasset的梦幻联动
  12. freemarker导出word文档中的复选框打钩功能
  13. 【科研绘图】Adobe illustrator加Origin组合绘图
  14. sql server 2000收缩数据库【极简操作】
  15. 收藏 | 超全开源数据集,你真的不想要吗?(附链接)
  16. like语句太慢 sqlserver_MySQL Like模糊查询速度太慢如何解决
  17. 移动应用程序设计/开发:jQuery Mobile入门指南
  18. win10用户查看系统激活码方式
  19. UBUNTU12.4 安装磊科无线网卡驱动
  20. 【综合评价】基于黏菌算法优化投影寻踪模型的综合评价附matlab代码

热门文章

  1. 吹爆的一种深度拷贝方式
  2. vm 安装unbuntu
  3. 如何复制word中带修订标记的段落
  4. 软件行业薪酬待遇调查:涨薪不给力致员工跳槽
  5. 使用 zabbix 监控 tomcat(包含jvm监控)
  6. PPT设计:PPT封面页9种设计布局/思维
  7. java 中 IO 流分为几种?
  8. 如何调用API接口在线生成在微信可用的网址二维码
  9. lammps案例:空位形成能的模拟与计算
  10. Linux 虚拟内存和物理内存的理解(转)