package com.nova.sankuai.infra.utils.baofu.rsa; import com.nova.sankuai.infra.utils.baofu.FormatUtil; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; /** * Rsa加解密工具
*
* 公钥采用X509,Cer格式的
* 私钥采用PKCS12加密方式的PFX私钥文件
* 加密算法为1024位的RSA,填充算法为PKCS1Padding
* * @author 行者 * @version 4.1.0 */ public final class RsaCodingUtil { // ====================================================================================== // 公钥加密私钥解密段 // ====================================================================================== /** * 指定Cer公钥路径加密 * * @param src * @param pubCerPath * @return hex串 */ public static String encryptByPubCerFile(String src, String pubCerPath) { PublicKey publicKey = RsaReadUtil.getPublicKeyFromFile(pubCerPath); if (publicKey == null) { return null; } return encryptByPublicKey(src, publicKey); } /** * 用公钥内容加密 * * @param src * @param pubKeyText * @return hex串 */ public static String encryptByPubCerText(String src, String pubKeyText) { PublicKey publicKey = RsaReadUtil.getPublicKeyByText(pubKeyText); if (publicKey == null) { return null; } return encryptByPublicKey(src, publicKey); } /** * 公钥加密返回 * * @param src * @param publicKey * @return hex串 */ public static String encryptByPublicKey(String src, PublicKey publicKey) { byte[] destBytes = rsaByPublicKey(src.getBytes(), publicKey, Cipher.ENCRYPT_MODE); if (destBytes == null) { return null; } return FormatUtil.byte2Hex(destBytes); } /** * 根据私钥文件解密 * * @param src * @param pfxPath * @param priKeyPass * @return * @throws Exception */ public static String decryptByPriPfxFile(String src, String pfxPath, String priKeyPass) throws Exception { if (FormatUtil.isEmpty(src) || FormatUtil.isEmpty(pfxPath)) { return null; } PrivateKey privateKey = RsaReadUtil.getPrivateKeyFromFile(pfxPath, priKeyPass); if (privateKey == null) { return null; } return decryptByPrivateKey(src, privateKey); } /** * 根据私钥文件流解密 * * @param src * @param priKeyPass * @return * @throws Exception */ public static String decryptByPriPfxStream(String src, byte[] pfxBytes, String priKeyPass) throws Exception { if (FormatUtil.isEmpty(src)) { return null; } PrivateKey privateKey = RsaReadUtil.getPrivateKeyByStream(pfxBytes, priKeyPass); if (privateKey == null) { return null; } return decryptByPrivateKey(src, privateKey); } /** * 私钥解密 * * @param src * @param privateKey * @return */ public static String decryptByPrivateKey(String src, PrivateKey privateKey) { if (FormatUtil.isEmpty(src)) { return null; } try { byte[] destBytes = rsaByPrivateKey(FormatUtil.hex2Bytes(src), privateKey, Cipher.DECRYPT_MODE); if (destBytes == null) { return null; } return new String(destBytes, "UTF-8"); } catch (UnsupportedEncodingException e) { // //log.error("解密内容不是正确的UTF8格式:", e); } catch (Exception e) { // //log.error("解密内容异常", e); } return null; } // ====================================================================================== // 私钥加密公钥解密 // ====================================================================================== /** * 根据私钥文件加密 * * @param src * @param pfxPath * @param priKeyPass * @return * @throws Exception */ public static String encryptByPriPfxFile(String src, String pfxPath, String priKeyPass) throws Exception { PrivateKey privateKey = RsaReadUtil.getPrivateKeyFromFile(pfxPath, priKeyPass); if (privateKey == null) { return null; } return encryptByPrivateKey(src, privateKey); } /** * 根据私钥文件流加密 * * @param src * @param priKeyPass * @return * @throws Exception */ public static String encryptByPriPfxStream(String src, byte[] pfxBytes, String priKeyPass) throws Exception { PrivateKey privateKey = RsaReadUtil.getPrivateKeyByStream(pfxBytes, priKeyPass); if (privateKey == null) { return null; } return encryptByPrivateKey(src, privateKey); } /** * 根据私钥加密 * * @param src * @param privateKey */ public static String encryptByPrivateKey(String src, PrivateKey privateKey) { byte[] destBytes = rsaByPrivateKey(src.getBytes(), privateKey, Cipher.ENCRYPT_MODE); if (destBytes == null) { return null; } return FormatUtil.byte2Hex(destBytes); } /** * 指定Cer公钥路径解密 * * @param src * @param pubCerPath * @return */ public static String decryptByPubCerFile(String src, String pubCerPath) { PublicKey publicKey = RsaReadUtil.getPublicKeyFromFile(pubCerPath); if (publicKey == null) { return null; } return decryptByPublicKey(src, publicKey); } /** * 根据公钥文本解密 * * @param src * @param pubKeyText * @return */ public static String decryptByPubCerText(String src, String pubKeyText) { PublicKey publicKey = RsaReadUtil.getPublicKeyByText(pubKeyText); if (publicKey == null) { return null; } return decryptByPublicKey(src, publicKey); } /** * 根据公钥解密 * * @param src * @param publicKey * @return */ public static String decryptByPublicKey(String src, PublicKey publicKey) { try { byte[] destBytes = rsaByPublicKey(FormatUtil.hex2Bytes(src), publicKey, Cipher.DECRYPT_MODE); if (destBytes == null) { return null; } return new String(destBytes, "UTF-8"); } catch (UnsupportedEncodingException e) { // //log.error("解密内容不是正确的UTF8格式:", e); } return null; } // ====================================================================================== // 公私钥算法 // ====================================================================================== /** * 公钥算法 * * @param srcData * 源字节 * @param publicKey * 公钥 * @param mode * 加密 OR 解密 * @return */ public static byte[] rsaByPublicKey(byte[] srcData, PublicKey publicKey, int mode) { try { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(mode, publicKey); // 分段加密 int blockSize = (mode == Cipher.ENCRYPT_MODE) ? cipher.getOutputSize(srcData.length)-11 : cipher.getOutputSize(srcData.length); byte[] encryptedData = null; for (int i = 0; i < srcData.length; i += blockSize) { // 注意要使用2的倍数,否则会出现加密后的内容再解密时为乱码 byte[] doFinal = cipher.doFinal(subarray(srcData, i, i + blockSize)); encryptedData = addAll(encryptedData, doFinal); } return encryptedData; } catch (NoSuchAlgorithmException e) { // //log.error("公钥算法-不存在的解密算法:", e); } catch (NoSuchPaddingException e) { // //log.error("公钥算法-无效的补位算法:", e); } catch (IllegalBlockSizeException e) { // //log.error("公钥算法-无效的块大小:", e); } catch (BadPaddingException e) { // //log.error("公钥算法-补位算法异常:", e); } catch (InvalidKeyException e) { // //log.error("公钥算法-无效的私钥:", e); } return null; } /** * 私钥算法 * * @param srcData * 源字节 * @param privateKey * 私钥 * @param mode * 加密 OR 解密 * @return */ public static byte[] rsaByPrivateKey(byte[] srcData, PrivateKey privateKey, int mode) { try { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(mode, privateKey); // 分段加密 int blockSize = (mode == Cipher.ENCRYPT_MODE) ? cipher.getOutputSize(srcData.length)-11 : cipher.getOutputSize(srcData.length); byte[] decryptData = null; for (int i = 0; i < srcData.length; i += blockSize) { byte[] doFinal = cipher.doFinal(subarray(srcData, i, i + blockSize)); decryptData = addAll(decryptData, doFinal); } return decryptData; } catch (NoSuchAlgorithmException e) { // //log.error("私钥算法-不存在的解密算法:", e); } catch (NoSuchPaddingException e) { //log.error("私钥算法-无效的补位算法:", e); } catch (IllegalBlockSizeException e) { //log.error("私钥算法-无效的块大小:", e); } catch (BadPaddingException e) { //log.error("私钥算法-补位算法异常:", e); } catch (InvalidKeyException e) { //log.error("私钥算法-无效的私钥:", e); } return null; } // /////////////========================== public static byte[] subarray(byte[] array, int startIndexInclusive, int endIndexExclusive) { if (array == null) { return null; } if (startIndexInclusive < 0) { startIndexInclusive = 0; } if (endIndexExclusive > array.length) { endIndexExclusive = array.length; } int newSize = endIndexExclusive - startIndexInclusive; if (newSize <= 0) { return new byte[0]; } byte[] subarray = new byte[newSize]; System.arraycopy(array, startIndexInclusive, subarray, 0, newSize); return subarray; } public static byte[] addAll(byte[] array1, byte[] array2) { if (array1 == null) { return clone(array2); } else if (array2 == null) { return clone(array1); } byte[] joinedArray = new byte[array1.length + array2.length]; System.arraycopy(array1, 0, joinedArray, 0, array1.length); System.arraycopy(array2, 0, joinedArray, array1.length, array2.length); return joinedArray; } public static byte[] clone(byte[] array) { if (array == null) { return null; } return (byte[]) array.clone(); } }