Java中使用RSA加解密
最近写了好多和第三方交互需要安全加密传输的需求,涉及到了AES、DES、RSA、SM2、SM3、SM4等,此处记录RSA的使用。
生成rsa秘钥对:
// KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); // 初始化密钥对生成器,密钥大小为512-4096位 keyPairGen.initialize(1024,new SecureRandom()); // 生成一个密钥对,保存在keyPair中 KeyPair keyPair = keyPairGen.generateKeyPair(); // 得到私钥 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到公钥 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公钥字符串 String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded())); // 得到私钥字符串 String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded()))); String str1 = "publicKeyString公钥:" + publicKeyString; writeFile(str1); String str2 = "privateKeyString私钥:" + privateKeyString; writeFile(str2); public static void writeFile(String content) { File file = new File("C:\\Users\\Administrator\\Desktop\\1.txt"); FileOutputStream fos = null; OutputStreamWriter osw = null; try { if (!file.exists()) { boolean hasFile = file.createNewFile(); if (hasFile) { log.info("file not exists, create new file"); } fos = new FileOutputStream(file); } else { fos = new FileOutputStream(file, true); } osw = new OutputStreamWriter(fos, "utf-8"); // 写入内容 osw.write(content); // 换行 osw.write("\r\n"); } catch (Exception e) { log.info("写入文件发生异常", e); } finally { // 关闭流 try { if (osw != null) { osw.close(); } if (fos != null) { fos.close(); } } catch (IOException e) { log.info("关闭流异常", e); } } }
公钥加密私钥模式:
/** * RSA私钥解密 * * @param str 加密字符串 * @param privateKey 私钥 * @return 铭文 * @throws Exception 解密过程中的异常信息 */ public static String privateKeyDecrypt(String str, String privateKey) throws Exception { //64位解码加密后的字符串 byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8")); //base64编码的私钥 byte[] decoded = Base64.decodeBase64(privateKey); RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA") .generatePrivate(new PKCS8EncodedKeySpec(decoded)); //RSA解密 Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, priKey); // String outStr = new String(cipher.doFinal(inputByte)); //当长度过长的时候,需要分割后解密 128个字节 String outStr = new String(getMaxResultDecrypt(str, cipher)); return outStr; } private static byte[] getMaxResultDecrypt(String str, Cipher cipher) throws IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException { byte[] inputArray = Base64.decodeBase64(str.getBytes("UTF-8")); int inputLength = inputArray.length; // 最大解密字节数,超出最大字节数需要分组加密 int MAX_ENCRYPT_BLOCK = 128; // 标识 int offSet = 0; byte[] resultBytes = {}; byte[] cache = {}; while (inputLength - offSet > 0) { if (inputLength - offSet > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(inputArray, offSet, MAX_ENCRYPT_BLOCK); offSet += MAX_ENCRYPT_BLOCK; } else { cache = cipher.doFinal(inputArray, offSet, inputLength - offSet); offSet = inputLength; } resultBytes = Arrays.copyOf(resultBytes, resultBytes.length + cache.length); System.arraycopy(cache, 0, resultBytes, resultBytes.length - cache.length, cache.length); } return resultBytes; } /** * RSA公钥加密 * * @param str 加密字符串 * @param publicKey 公钥 * @return 密文 * @throws Exception 加密过程中的异常信息 */ public static String publicKeyEncrypt(String str, String publicKey) throws Exception { //base64编码的公钥 byte[] decoded = Base64.decodeBase64(publicKey); RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA"). generatePublic(new X509EncodedKeySpec(decoded)); //RSA加密 Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, pubKey); //当长度过长的时候,需要分割后加密 117个字节 byte[] resultBytes = getMaxResultEncrypt(str, cipher); String outStr = Base64.encodeBase64String(resultBytes); return outStr; } private static byte[] getMaxResultEncrypt(String str, Cipher cipher) throws IllegalBlockSizeException, BadPaddingException { byte[] inputArray = str.getBytes(); int inputLength = inputArray.length; // 最大加密字节数,超出最大字节数需要分组加密 int MAX_ENCRYPT_BLOCK = 117; // 标识 int offSet = 0; byte[] resultBytes = {}; byte[] cache = {}; while (inputLength - offSet > 0) { if (inputLength - offSet > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(inputArray, offSet, MAX_ENCRYPT_BLOCK); offSet += MAX_ENCRYPT_BLOCK; } else { cache = cipher.doFinal(inputArray, offSet, inputLength - offSet); offSet = inputLength; } resultBytes = Arrays.copyOf(resultBytes, resultBytes.length + cache.length); System.arraycopy(cache, 0, resultBytes, resultBytes.length - cache.length, cache.length); } return resultBytes; }
私钥加密公钥解密:
/** * 使用公钥解密 */ @SneakyThrows public static String decryptByPublicKey(String data) { try { return new String(getMaxResultDecrypt(data, getPublicKey(Cipher.DECRYPT_MODE))); }catch (Exception e){ throw new Exception("解密失败|"+e.getMessage()); } } /** * 使用RSA私钥解密 * * @param str 加密字符串 */ public static String decryptByPrivateKey(String str) { return new String(getMaxResultDecrypt(str, getPrivateKey(Cipher.DECRYPT_MODE))); } /** * 使用RSA私钥加密 * @param data 加密数据 */ @SneakyThrows public static String encryptByPrivateKey(String data) { try { return Base64.encodeBase64String(getMaxResultEncrypt(data, getPrivateKey(Cipher.ENCRYPT_MODE))); } catch (Exception e) { throw new Exception("加密失败|"+e.getMessage()); } } /** * 当长度过长的时候,需要分割后加密 117个字节 */ @SneakyThrows private static byte[] getMaxResultEncrypt(String str, Cipher cipher){ try { byte[] inputArray = str.getBytes(StandardCharsets.UTF_8.name()); int inputLength = inputArray.length; // 最大加密字节数,超出最大字节数需要分组加密 int maxEncryptBlock = 117; // 标识 int offSet = 0; byte[] resultBytes = {}; byte[] cache; while (inputLength - offSet > 0) { if (inputLength - offSet > maxEncryptBlock) { cache = cipher.doFinal(inputArray, offSet, maxEncryptBlock); offSet += maxEncryptBlock; } else { cache = cipher.doFinal(inputArray, offSet, inputLength - offSet); offSet = inputLength; } resultBytes = Arrays.copyOf(resultBytes, resultBytes.length + cache.length); System.arraycopy(cache, 0, resultBytes, resultBytes.length - cache.length, cache.length); } return resultBytes; }catch (Exception e){ e.printStackTrace(); throw new Exception("加密处理失败,"+e.getMessage()); } } /** * 当长度过长的时候,需要分割后解密 128个字节 */ @SneakyThrows private static byte[] getMaxResultDecrypt(String str, Cipher cipher) { try { byte[] inputArray = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8.name())); int inputLength = inputArray.length; // 最大解密字节数,超出最大字节数需要分组加密 int maxEncryptBlock = 128; int offSet = 0; byte[] resultBytes = {}; byte[] cache; while (inputLength - offSet > 0) { if (inputLength - offSet > maxEncryptBlock) { cache = cipher.doFinal(inputArray, offSet, maxEncryptBlock); offSet += maxEncryptBlock; } else { cache = cipher.doFinal(inputArray, offSet, inputLength - offSet); offSet = inputLength; } resultBytes = Arrays.copyOf(resultBytes, resultBytes.length + cache.length); System.arraycopy(cache, 0, resultBytes, resultBytes.length - cache.length, cache.length); } return resultBytes; }catch (Exception e){ e.printStackTrace(); throw new Exception("解密数据处理异常,"+e.getMessage()); } } /** * 根据加解密类型处理公钥 * */ @SneakyThrows public static Cipher getPublicKey(int mode) { try { String publicKey = formatString(PK); byte[] decoded = Base64.decodeBase64(publicKey); X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decoded); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PublicKey key = keyFactory.generatePublic(x509EncodedKeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(mode, key); return cipher; } catch (Exception e) { throw new Exception("转换公钥异常====>>" + e.getMessage()); } } /** * 根据加解密类型处理私钥 */ @SneakyThrows public static Cipher getPrivateKey(int mode) { try { //mode 加解密模式 ENCRYPT_MODE = 1 DECRYPT_MODE = 2 String privateKey = formatString(SK); byte[] decoded = Base64.decodeBase64(privateKey); PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(decoded); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PrivateKey key = keyFactory.generatePrivate(pkcs8EncodedKeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(mode, key); return cipher; } catch (Exception e) { throw new Exception("转换私钥异常====>>" + e.getMessage()); } } public static String formatString(String source) { if (source == null) { return null; } return source.replace("\\r", "").replace("\\n", "").trim().replace(" ",""); }