RSA工具类

it2022-05-05  140

<!-- BouncyCastle必要的maven依赖 --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.56</version> </dependency>

package com.modules.utils; import org.bouncycastle.jce.provider.BouncyCastleProvider; import javax.crypto.Cipher; import java.math.BigInteger; import java.security.*; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.RSAPrivateKeySpec; import java.security.spec.RSAPublicKeySpec; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class EncryForRSAUtil { private static String digits = "0123456789abcdef"; static { Security.addProvider(new BouncyCastleProvider()); } /** * 随机生成密钥对 未验证 * @return HashMap<String , Object> * @throws NoSuchAlgorithmException */ public static HashMap<String , Object> getKeys() throws NoSuchAlgorithmException { HashMap<String , Object> map = new HashMap<>(); // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); // 初始化密钥对生成器,密钥大小为96-1024位 keyPairGen.initialize(1024); // 生成一个密钥对,保存在keyPair中 KeyPair keyPair = keyPairGen.generateKeyPair(); //得到公钥 RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic(); //得到私钥 RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate(); map.put("publicKey" , publicKey); map.put("privateKey" , privateKey); return map; } /** * 使用模和指数生成RSA公钥 * 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA * * /None/NoPadding】 * @param argM 模 N * @param argE 指数 E * @return */ public static RSAPublicKey getPublicKey(String argM , String argE){ try { BigInteger bigM = new BigInteger(argM); BigInteger bigE = new BigInteger(argE); KeyFactory factory = KeyFactory.getInstance("RSA", "BC"); RSAPublicKeySpec spec = new RSAPublicKeySpec(bigM , bigE); return (RSAPublicKey)factory.generatePublic(spec); }catch (Exception e){ e.printStackTrace(); return null; } } /** * 使用模和指数生成RSA私钥 * 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA * * /None/NoPadding】 * @param argM 模 N * @param argE 指数 E * @return */ public static RSAPrivateKey getPrivateKey(String argM , String argE){ try { BigInteger bigM = new BigInteger(argM); BigInteger bigE = new BigInteger(argE); KeyFactory factory = KeyFactory.getInstance("RSA", "BC"); RSAPrivateKeySpec spec = new RSAPrivateKeySpec(bigM , bigE); return (RSAPrivateKey) factory.generatePrivate(spec); }catch (Exception e){ e.printStackTrace(); return null; } } /** * 公钥加密 * @param data * @param publicKey * @return * @throws Exception */ public static String encryptByPublicKey(String data , RSAPublicKey publicKey) throws Exception { byte[] bInput = data.getBytes("UTF8"); Cipher cipher = Cipher.getInstance("RSA/NONE/PKCS1Padding", "BC"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); //模 长 int CellLength = publicKey.getModulus().bitLength() / 8; int MaxLength = CellLength - 11; int GroupLength = (int)Math.ceil((double)bInput.length * 1.0D / (double)MaxLength); byte[] result = new byte[GroupLength * CellLength]; for(int i = 0; i < GroupLength; ++i) { int len = MaxLength < bInput.length - MaxLength * i ? MaxLength : bInput.length - MaxLength * i; byte[] inByte = new byte[len]; System.arraycopy(bInput, MaxLength * i, inByte, 0, len); byte[] temp = cipher.doFinal(inByte); System.arraycopy(temp, 0, result, i * CellLength, CellLength); } return StringUtil.toHex(result , digits); } /** * 公钥加密 * @param data 明文数据 * @param argM 模 * @param argE 指数 * @return * @throws Exception */ public static String encryptByPublicKey(String data , String argM , String argE) throws Exception { RSAPublicKey publicKey = getPublicKey(argM , argE); return encryptByPublicKey(data , publicKey); } /** * 私钥解密 未验证 * @param data * @param privateKey * @return * @throws Exception */ public static String decryByPrivateKey(String data, RSAPrivateKey privateKey) throws Exception { byte[] bInput = StringUtil.hexStr2Bytes(data); Cipher cipher = Cipher.getInstance("RSA/NONE/PKCS1Padding", "BC"); cipher.init(Cipher.DECRYPT_MODE, privateKey); //模 长 int CellLength = privateKey.getModulus().bitLength() / 8; int MaxLength = CellLength - 11; int GroupLength = (int)Math.ceil((double)bInput.length * 1.0D / (double)CellLength); List<byte[]> plainList = new ArrayList(); int len = 0; for(int i = 0; i < GroupLength; ++i) { byte[] inByte = new byte[CellLength]; System.arraycopy(bInput, CellLength * i, inByte, 0, CellLength); byte[] temp = cipher.doFinal(inByte); plainList.add(temp); len += temp.length; } byte[] plainText = new byte[len]; for(int i = 0; i < GroupLength; ++i) { System.arraycopy(plainList.get(i), 0, plainText, i * MaxLength, ((byte[])plainList.get(i)).length); } return byteToString(plainText); } /** * 私钥解密 未验证 * @param data 密文 * @param argM 模 * @param argE 指数 * @return * @throws Exception */ public static String decryByPrivateKey(String data , String argM , String argE) throws Exception { RSAPrivateKey privateKey = getPrivateKey(argM , argE); return decryByPrivateKey(data , privateKey); } public static String byteToString(byte[] bytes) { return byteToString(bytes, bytes.length); } public static String byteToString(byte[] bytes, int length) { char[] chars = new char[length]; for(int i = 0; i != chars.length; ++i) { chars[i] = (char)(bytes[i] & 255); } return new String(chars); } } <!-- StringUtil工具类 --> package com.modules.utils; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; import java.util.regex.Matcher; import java.util.regex.Pattern; public class StringUtil { public static boolean isChinese(String strName) { char[] ch = strName.toCharArray(); for (int i = 0; i < ch.length; i++) { char c = ch[i]; if (isChinese(c)) { return true; } } return false; } public static boolean isChinese(char c) { Character.UnicodeBlock ub = Character.UnicodeBlock.of(c); if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) { return true; } return false; } public static String isChineseToUniCode(String str){ StringBuilder sb = new StringBuilder(); char[] ch = str.toCharArray(); for (int i = 0; i < ch.length; i++) { char c = ch[i]; if (StringUtil.isChinese(c)) { sb.append(cnToUnicode(Character.toString(c))); }else { sb.append(Character.toString(c)); } } return sb.toString(); } public static String isUniCodeToChinese(String unicode){ List<String> list = new ArrayList<>(); String reg= "\\\\u[0-9,a-f,A-F]{4}"; Pattern p = Pattern.compile(reg); Matcher m=p.matcher(unicode); while (m.find()){ list.add(m.group()); } for (int i = 0, j = 2; i < list.size(); i++) { String code = list.get(i).substring(j, j + 4); char ch = (char) Integer.parseInt(code, 16); unicode = unicode.replace(list.get(i),String.valueOf(ch)); } return unicode; } public static String unicodeToCn(String unicode) { /** 以 \ u 分割,因为java注释也能识别unicode,因此中间加了一个空格*/ String[] strs = unicode.split("\\\\u"); String returnStr = ""; // 由于unicode字符串以 \ u 开头,因此分割出的第一个字符是""。 for (int i = 1; i < strs.length; i++) { returnStr += (char) Integer.valueOf(strs[i], 16).intValue(); } return returnStr; } /** * 如果字符串包含中文,则将中文转为unicode编码 * @param cn * @return */ public static String cnToUnicode(String cn) { char[] chars = cn.toCharArray(); String returnStr = ""; for (int i = 0; i < chars.length; i++) { returnStr += "\\u" + Integer.toString(chars[i], 16); } return returnStr; } public static String getRandomString(int arg0){ String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; Random random=new Random(); StringBuffer sb=new StringBuffer(); for(int i = 0;i < arg0;i++){ int number=random.nextInt(62); sb.append(str.charAt(number)); } return sb.toString(); } public static byte uniteBytes(String src0, String src1) { byte b0 = Byte.decode("0x" + src0); b0 = (byte)(b0 << 4); byte b1 = Byte.decode("0x" + src1); byte ret = (byte)(b0 | b1); return ret; } /** * 字符串(16进制)转byte数组 * @param src * @return */ public static byte[] hexStr2Bytes(String src) { // int m = false; // int n = false; int l = src.length() / 2; byte[] ret = new byte[l]; for(int i = 0; i < l; ++i) { int m = i * 2 + 1; int n = m + 1; ret[i] = StringUtil.uniteBytes(src.substring(i * 2, m), src.substring(m, n)); } return ret; } /** * byte数组转字符串(16进制) * @param data * @param digits * @return */ public static String toHex(byte[] data , String digits) { return toHex(data, data.length , digits); } /** * byte数组转字符串(16进制) * @param data * @param length * @param digits * @return */ public static String toHex(byte[] data, int length , String digits) { StringBuffer buf = new StringBuffer(); for(int i = 0; i != length; ++i) { int v = data[i] & 255; buf.append(digits.charAt(v >> 4)); buf.append(digits.charAt(v & 15)); } return buf.toString(); } /** * byte数组转HEX字符串 * @param b * @return */ public static String byte2hex(byte[] b) { String hs = ""; String stmp = ""; for(int n = 0; n < b.length; ++n) { stmp = Integer.toHexString(b[n] & 255); if (stmp.length() == 1) { hs = hs + "0" + stmp; } else { hs = hs + stmp; } } return hs.toUpperCase(); } public static byte[] hex2byte(String s) { int l = s.length() / 2; byte[] b = new byte[l]; for(int i = 0; i < l; ++i) { int m = i * 2 + 1; int n = m + 1; b[i] = StringUtil.uniteBytes(s.substring(i * 2, m), s.substring(m, n)); } return b; } }  

最新回复(0)