/**
* RSA算法加密/解密工具类
*/
public class RSAUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(RSAUtils.class);
/** 算法名称 */
private static final String ALGORITHM = "RSA";
/** 默认密钥大小 */
private static final int KEY_SIZE = 1024;
/** 用来指定保存密钥对的文件名和存储的名称 */
private static final String PUBLIC_KEY_NAME = "publicKey";
private static final String PRIVATE_KEY_NAME = "privateKey";
private static final String PUBLIC_FILENAME = "publicKey.properties";
private static final String PRIVATE_FILENAME = "privateKey.properties";
/** 密钥对生成器 */
private static KeyPairGenerator keyPairGenerator = null; private static KeyFactory keyFactory = null;
/** 缓存的密钥对 */
private static KeyPair keyPair = null;
/** Base64 编码/解码器 JDK1.8 */
private static Base64.Decoder decoder = Base64.getDecoder();
private static Base64.Encoder encoder = Base64.getEncoder();
/** 初始化密钥工厂 */
static{
try {
keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
keyFactory = KeyFactory.getInstance(ALGORITHM);
} catch (NoSuchAlgorithmException e) {
LOGGER.error(e.getMessage(),e);
}
}
/** 私有构造器 */
private RSAUtils(){} /**
* 生成密钥对
* 将密钥分别用Base64编码保存到#publicKey.properties#和#privateKey.properties#文件中
* 保存的默认名称分别为publicKey和privateKey
*/
public static synchronized Map<String, Object> generateKeyPair(){
try {
keyPairGenerator.initialize(KEY_SIZE,new SecureRandom(UUID.randomUUID().toString().replaceAll("-","").getBytes()));
keyPair = keyPairGenerator.generateKeyPair();
} catch (InvalidParameterException e){
LOGGER.error("KeyPairGenerator does not support a key length of " + KEY_SIZE + ".",e);
} catch (NullPointerException e){
LOGGER.error("RSAUtils#key_pair_gen is null,can not generate KeyPairGenerator instance.",e);
}
RSAPublicKey rsaPublicKey = (RSAPublicKey)keyPair.getPublic();
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey)keyPair.getPrivate();
String publicKeyString = encoder.encodeToString(rsaPublicKey.getEncoded());
String privateKeyString = encoder.encodeToString(rsaPrivateKey.getEncoded());
storeKey(publicKeyString,PUBLIC_KEY_NAME,PUBLIC_FILENAME);
storeKey(privateKeyString,PRIVATE_KEY_NAME,PRIVATE_FILENAME);
Map<String, Object> keyPair = new HashMap<>();
keyPair.put("public", privateKeyString);
keyPair.put("private", privateKeyString);
return keyPair;
} /**
* 将指定的密钥字符串保存到文件中,如果找不到文件,就创建
* @param keyString 密钥的Base64编码字符串(值)
* @param keyName 保存在文件中的名称(键)
* @param fileName 目标文件名
*/
private static void storeKey(String keyString,String keyName,String fileName){
Properties properties = new Properties();
//存放密钥的绝对地址
String path = null;
try{
path = RSAUtils.class.getClassLoader().getResource(fileName).toString();
path = path.substring(path.indexOf(":") + 1);
}catch (NullPointerException e){
//如果不存#fileName#就创建
LOGGER.warn("storeKey()# " + fileName + " is not exist.Begin to create this file.");
String classPath = RSAUtils.class.getClassLoader().getResource("").toString();
String prefix = classPath.substring(classPath.indexOf(":") + 1);
String suffix = fileName;
File file = new File(prefix + suffix);
try {
file.createNewFile();
path = file.getAbsolutePath();
} catch (IOException e1) {
LOGGER.error(fileName +" create fail.",e1);
}
}
try(OutputStream out = new FileOutputStream(path)){
properties.setProperty(keyName,keyString);
properties.store(out,"There is " + keyName);
} catch (FileNotFoundException e) {
LOGGER.error("ModulusAndExponent.properties is not found.",e);
} catch (IOException e) {
LOGGER.error("OutputStream output failed.",e);
}
} /**
* 获取密钥字符串
* @param keyName 需要获取的密钥名
* @param fileName 密钥所在文件
* @return Base64编码的密钥字符串
*/
private static String getKeyString(String keyName,String fileName){
if (RSAUtils.class.getClassLoader().getResource(fileName) == null){
LOGGER.warn("getKeyString()# " + fileName + " is not exist.Will run #generateKeyPair()# firstly.");
generateKeyPair();
}
try(InputStream in = RSAUtils.class.getClassLoader().getResource(fileName).openStream()){
Properties properties = new Properties();
properties.load(in);
return properties.getProperty(keyName);
} catch (IOException e) {
LOGGER.error("getKeyString()#" + e.getMessage(),e);
}
return null;
} /**
* 从文件获取RSA公钥
* @return RSA公钥
* @throws InvalidKeySpecException
*/
public static RSAPublicKey getPublicKey(){
try {
byte[] keyBytes = decoder.decode(getKeyString(PUBLIC_KEY_NAME,PUBLIC_FILENAME));
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
return (RSAPublicKey)keyFactory.generatePublic(x509EncodedKeySpec);
}catch (InvalidKeySpecException e) {
LOGGER.error("getPublicKey()#" + e.getMessage(),e);
}
return null;
} /**
* 从文件获取RSA私钥
* @return RSA私钥
* @throws InvalidKeySpecException
*/
public static RSAPrivateKey getPrivateKey(){
try {
byte[] keyBytes = decoder.decode(getKeyString(PRIVATE_KEY_NAME,PRIVATE_FILENAME));
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
return (RSAPrivateKey)keyFactory.generatePrivate(pkcs8EncodedKeySpec);
} catch (InvalidKeySpecException e) {
LOGGER.error("getPrivateKey()#" + e.getMessage(),e);
}
return null;
} /**
* RSA公钥加密
* @param content 等待加密的数据
* @param publicKey RSA 公钥 if null then getPublicKey()
* @return 加密后的密文(16进制的字符串)
*/
public static String encryptByPublic(byte[] content,PublicKey publicKey){
if (publicKey == null){
publicKey = getPublicKey();
}
try {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE,publicKey);
//该密钥能够加密的最大字节长度
int splitLength = ((RSAPublicKey)publicKey).getModulus().bitLength() / 8 -11;
byte[][] arrays = splitBytes(content,splitLength);
StringBuffer stringBuffer = new StringBuffer();
for (byte[] array : arrays){
stringBuffer.append(bytesToHexString(cipher.doFinal(array)));
}
return stringBuffer.toString();
} catch (NoSuchAlgorithmException e) {
LOGGER.error("encrypt()#NoSuchAlgorithmException",e);
} catch (NoSuchPaddingException e) {
LOGGER.error("encrypt()#NoSuchPaddingException",e);
} catch (InvalidKeyException e) {
LOGGER.error("encrypt()#InvalidKeyException",e);
} catch (BadPaddingException e) {
LOGGER.error("encrypt()#BadPaddingException",e);
} catch (IllegalBlockSizeException e) {
LOGGER.error("encrypt()#IllegalBlockSizeException",e);
}
return null;
} /**
* RSA私钥加密
* @param content 等待加密的数据
* @param privateKey RSA 私钥 if null then getPrivateKey()
* @return 加密后的密文(16进制的字符串)
*/
public static String encryptByPrivate(byte[] content,PrivateKey privateKey){
if (privateKey == null){
privateKey = getPrivateKey();
}
try {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE,privateKey);
//该密钥能够加密的最大字节长度
int splitLength = ((RSAPrivateKey)privateKey).getModulus().bitLength() / 8 -11;
byte[][] arrays = splitBytes(content,splitLength);
StringBuffer stringBuffer = new StringBuffer();
for(byte[] array : arrays){
stringBuffer.append(bytesToHexString(cipher.doFinal(array)));
}
return stringBuffer.toString();
} catch (NoSuchAlgorithmException e) {
LOGGER.error("encrypt()#NoSuchAlgorithmException",e);
} catch (NoSuchPaddingException e) {
LOGGER.error("encrypt()#NoSuchPaddingException",e);
} catch (InvalidKeyException e) {
LOGGER.error("encrypt()#InvalidKeyException",e);
} catch (BadPaddingException e) {
LOGGER.error("encrypt()#BadPaddingException",e);
} catch (IllegalBlockSizeException e) {
LOGGER.error("encrypt()#IllegalBlockSizeException",e);
}
return null;
} /**
* RSA私钥解密
* @param content 等待解密的数据
* @param privateKey RSA 私钥 if null then getPrivateKey()
* @return 解密后的明文
*/
public static String decryptByPrivate(String content,PrivateKey privateKey){
if (privateKey == null){
privateKey = getPrivateKey();
}
try {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE,privateKey);
//该密钥能够加密的最大字节长度
int splitLength = ((RSAPrivateKey)privateKey).getModulus().bitLength() / 8;
byte[] contentBytes = hexStringToBytes(content);
byte[][] arrays = splitBytes(contentBytes,splitLength);
StringBuffer stringBuffer = new StringBuffer();
String sTemp = null;
for (byte[] array : arrays){
stringBuffer.append(new String(cipher.doFinal(array)));
}
return stringBuffer.toString();
} catch (NoSuchAlgorithmException e) {
LOGGER.error("encrypt()#NoSuchAlgorithmException",e);
} catch (NoSuchPaddingException e) {
LOGGER.error("encrypt()#NoSuchPaddingException",e);
} catch (InvalidKeyException e) {
LOGGER.error("encrypt()#InvalidKeyException",e);
} catch (BadPaddingException e) {
LOGGER.error("encrypt()#BadPaddingException",e);
} catch (IllegalBlockSizeException e) {
LOGGER.error("encrypt()#IllegalBlockSizeException",e);
}
return null;
} /**
* RSA公钥解密
* @param content 等待解密的数据
* @param publicKey RSA 公钥 if null then getPublicKey()
* @return 解密后的明文
*/
public static String decryptByPublic(String content,PublicKey publicKey){
if (publicKey == null){
publicKey = getPublicKey();
}
try {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE,publicKey);
//该密钥能够加密的最大字节长度
int splitLength = ((RSAPublicKey)publicKey).getModulus().bitLength() / 8;
byte[] contentBytes = hexStringToBytes(content);
byte[][] arrays = splitBytes(contentBytes,splitLength);
StringBuffer stringBuffer = new StringBuffer();
String sTemp = null;
for (byte[] array : arrays){
stringBuffer.append(new String(cipher.doFinal(array)));
}
return stringBuffer.toString();
} catch (NoSuchAlgorithmException e) {
LOGGER.error("encrypt()#NoSuchAlgorithmException",e);
} catch (NoSuchPaddingException e) {
LOGGER.error("encrypt()#NoSuchPaddingException",e);
} catch (InvalidKeyException e) {
LOGGER.error("encrypt()#InvalidKeyException",e);
} catch (BadPaddingException e) {
LOGGER.error("encrypt()#BadPaddingException",e);
} catch (IllegalBlockSizeException e) {
LOGGER.error("encrypt()#IllegalBlockSizeException",e);
}
return null;
} /**
* 根据限定的每组字节长度,将字节数组分组
* @param bytes 等待分组的字节组
* @param splitLength 每组长度
* @return 分组后的字节组
*/
public static byte[][] splitBytes(byte[] bytes,int splitLength){
//bytes与splitLength的余数
int remainder = bytes.length % splitLength;
//数据拆分后的组数,余数不为0时加1
int quotient = remainder != 0 ? bytes.length / splitLength + 1:bytes.length / splitLength;
byte[][] arrays = new byte[quotient][];
byte[] array = null;
for (int i =0;i<quotient;i++){
//如果是最后一组(quotient-1),同时余数不等于0,就将最后一组设置为remainder的长度
if (i == quotient -1 && remainder != 0){
array = new byte[remainder];
System.arraycopy(bytes,i * splitLength,array,0,remainder);
} else {
array = new byte[splitLength];
System.arraycopy(bytes,i*splitLength,array,0,splitLength);
}
arrays[i] = array;
}
return arrays;
} /**
* 将字节数组转换成16进制字符串
* @param bytes 即将转换的数据
* @return 16进制字符串
*/
public static String bytesToHexString(byte[] bytes){
StringBuffer sb = new StringBuffer(bytes.length);
String temp = null;
for (int i = 0;i< bytes.length;i++){
temp = Integer.toHexString(0xFF & bytes[i]);
if(temp.length() <2){
sb.append(0);
}
sb.append(temp);
}
return sb.toString();
} /**
* 将16进制字符串转换成字节数组
* @param hex 16进制字符串
* @return byte[]
*/
public static byte[] hexStringToBytes(String hex){
int len = (hex.length() / 2);
hex = hex.toUpperCase();
byte[] result = new byte[len];
char[] chars = hex.toCharArray();
for (int i= 0;i<len;i++){
int pos = i * 2;
result[i] = (byte)(toByte(chars[pos]) << 4 | toByte(chars[pos + 1]));
}
return result;
} /**
* 将char转换为byte
* @param c char
* @return byte
*/
private static byte toByte(char c){
return (byte)"0123456789ABCDEF".indexOf(c);
} public static void main(String[] args) {
String s = "test";
RSAUtils.generateKeyPair();
String c1 = RSAUtils.encryptByPublic(s.getBytes(),null);
String m1 = RSAUtils.decryptByPrivate(c1,null);
String c2 = RSAUtils.encryptByPrivate(s.getBytes(),null);
String m2 = RSAUtils.decryptByPublic(c2,null);
System.out.println(c1);
System.out.println(m1);
System.out.println(c2);
System.out.println(m2);
}
}

java版RSA工具类的更多相关文章

  1. Java版InfluxDB工具类

    InfluxDB工具类 package com.influxdb.test; import java.util.Map; import org.influxdb.InfluxDB; import or ...

  2. 170405、java版MD5工具类

    package com.rick.utils; import java.security.MessageDigest; import java.security.NoSuchAlgorithmExce ...

  3. HttpTool.java(在java tool util工具类中已存在) 暂保留

    HttpTool.java 该类为java源生态的http 请求工具,不依赖第三方jar包 ,即插即用. package kingtool; import java.io.BufferedReader ...

  4. java文件处理工具类

    import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedRead ...

  5. java格式处理工具类

    import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOExceptio ...

  6. Java 敏感词过滤,Java 敏感词替换,Java 敏感词工具类

    Java 敏感词过滤,Java 敏感词替换,Java 敏感词工具类   =========================== ©Copyright 蕃薯耀 2017年9月25日 http://www ...

  7. Java 通过Xml导出Excel文件,Java Excel 导出工具类,Java导出Excel工具类

    Java 通过Xml导出Excel文件,Java Excel 导出工具类,Java导出Excel工具类 ============================== ©Copyright 蕃薯耀 20 ...

  8. 使用java的Calendar工具类获取到本月的第一天起始时间和最后一天结束时间。

    1.使用java的Calendar工具类获取到本月的第一天起始时间和最后一天结束时间. package com.fline.aic.utils; import java.text.DateFormat ...

  9. JAVA 8 日期工具类

    JAVA 8 日期工具类 主题描述 JAVA中日期时间的历史 代码成果 主题描述 JAVA的日期时间一直比较混乱,本来以为joda会是巅峰,但是JAVA 8改变了我的思想.但是即便在JAVA 8面前, ...

随机推荐

  1. bzoj3159决战 码农题 树剖套splay

    最近沉迷码农题无法自拔 首先有一个暴力的想法:对于每个重链维护一个splay,需要翻转的连起来,翻转,接回去 然后发现这样没问题... 一条链只能跨log个重链,也就只有log个splay的子树参与重 ...

  2. idea 卡顿问题

    转载大神总结 https://jingyan.baidu.com/article/c275f6ba14207ee33c756752.html

  3. NET Core中使用Irony

    在.NET Core中使用Irony实现自己的查询语言语法解析器   在之前<在ASP.NET Core中使用Apworks快速开发数据服务>一文的评论部分,.NET大神张善友为我提了个建 ...

  4. missfresh问题记录

    一.基本信息 1.登陆机器    ssh lina02@mjump.missfresh.net -p2222 二.问题 1.分页问题:job_id为空时能查询出来(笛卡尔乘积),需要加上AND res ...

  5. 开源分布式Job系统,调度与业务分离-如何创建周期性的HttpJob任务

    项目介绍: Hangfire:是一个开源的job调度系统,支持分布式JOB!! Hangfire.HttpJob 是我针对Hangfire开发的一个组件,该组件和Hangfire本身是独立的.可以独立 ...

  6. ruby 数组array 排序sort 和sort!

    1. sort → new_ary click to toggle source sort { |a, b| block } → new_ary Returns a new array created ...

  7. 通过代码理解Asp.net4中的几种ClientIDMode设置.

    以前我们可以通过ClientID在JavaScript脚本中服务器端控件.比如: document.getElementById("<%=控件.ClientID %>" ...

  8. text-transform 字母的大小写

    text-transform: none   默认 capitalize    每个单词以大写字母开头 uppercase    仅有大写字母 lowercase     无大写字母,仅有小写字母 i ...

  9. JS将人民币小写金额转换为大写

    /** 数字金额大写转换(可以处理整数,小数,负数) */ function smalltoBIG(n) { var fraction = ['角', '分']; var digit = ['零', ...

  10. html5 新增表单控件和表单属性

    新的输入型控件 email:电子邮箱文本框,跟普通的没什么区别 当输入不是邮箱的时候,验证通不过 移动端的键盘会有变化         tel:电话号码 一般用于手机端,是一个键盘切换 url:网页的 ...