最大加密字节数 53 ,超出最大字节数需要分组加密; 最大解密字节数 64 ,超出最大字节数需要分组解密 (#537)

This commit is contained in:
SanJin 2023-07-21 08:31:30 +08:00 committed by GitHub
parent d373cd7fb3
commit 659edc8b13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -14,6 +14,7 @@ import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
/**
* Copyright 1999-2018 Alibaba Group Holding Ltd.
@ -38,23 +39,33 @@ public class CryptoUtils {
private static final String DEFAULT_PRIVATE_KEY_STRING = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAnijqyfhag+ZuzsNH2YZDO65RAz16tBNU+nDEjMHQRNiTIp987T3updVEsDoo+ZpX7+yJZ7BHu+l9hiNZqPDkqQIDAQABAkBgErbczRIewWFaE+GXTymUHUV01Gmu7XdXUhzy6+CZkIcEnyTpUgPilGUydiIyeiY8usvWKGjFWxLoKeJDY1wBAiEA5M9uqc9XpL5uitLWHiiq7pRxhnJb/B+wZyHqLVhCLekCIQCw9D/Fsx7vHRgymWYExHvCka7w5SyWUmNzQOOKjZUIwQIhAMqbo7JaF5GZzui+qTsrZ7C7YYtb2Hf414t7TJG6hV+BAiBXuZ7r+fL6A+h9HUNQVcAtI2AhGNxT4aBgAOlNRQd/gQIgCGqaZsOdnL9624SI1DwhBt4x24q3350pWwzgfl4Kbbo=";
/**
* 加密算法RSA
* 最大加密字节数超出最大字节数需要分组加密
*/
private static final int MAX_ENCRYPT_BLOCK = 53;
/**
* 最大解密字节数超出最大字节数需要分组解密
*/
private static final int MAX_DECRYPT_BLOCK = 64;
/**
* 解密算法 RSA
*
* @param cipherText 需要加密的字符串
* @return 加密后的字符串
* @throws Exception 加密过程中的异常信息
* @param cipherText - 需要解密的字符串
* @return String - 密后的字符串
* @throws Exception - 密过程中的异常信息
*/
public static String decrypt(String cipherText) throws Exception {
return decrypt((String) null, cipherText);
}
/**
* 加密算法RSA
* 解密算法 RSA
*
* @param publicKeyText 公钥
* @param cipherText 需要加密的字符串
* @return 密后的字符串
* @throws Exception 密过程中的异常信息
* @param publicKeyText - 公钥
* @param cipherText - 需要解密的字符串
* @return String - 密后的字符串
* @throws Exception - 密过程中的异常信息
*/
public static String decrypt(String publicKeyText, String cipherText) throws Exception {
PublicKey publicKey = getPublicKey(publicKeyText);
@ -62,10 +73,10 @@ public class CryptoUtils {
}
/**
* 加密算法RSA
* 加密算法 RSA
*
* @param x509File 公钥文件
* @return 加密后的字符串
* @param x509File - 公钥文件
* @return PublicKey - 加密后的字符串
*/
public static PublicKey getPublicKeyByX509(String x509File) {
if (x509File == null || x509File.length() == 0) {
@ -92,10 +103,10 @@ public class CryptoUtils {
}
/**
* 加密算法RSA
* 加密算法 RSA
*
* @param publicKeyText 公钥
* @return 加密后的字符串
* @param publicKeyText - 公钥字符串
* @return PublicKey - 公钥
*/
public static PublicKey getPublicKey(String publicKeyText) {
if (publicKeyText == null || publicKeyText.length() == 0) {
@ -104,8 +115,7 @@ public class CryptoUtils {
try {
byte[] publicKeyBytes = Base64.base64ToByteArray(publicKeyText);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(
publicKeyBytes);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA", "SunRsaSign");
return keyFactory.generatePublic(x509KeySpec);
@ -115,10 +125,10 @@ public class CryptoUtils {
}
/**
* 加密算法RSA
* 加密算法RSA 通过公钥文件获取公钥
*
* @param publicKeyFile 公钥文件
* @return 加密后的字符串
* @param publicKeyFile - 公钥文件
* @return PublicKey - 加密后的字符串
*/
public static PublicKey getPublicKeyByPublicKeyFile(String publicKeyFile) {
if (publicKeyFile == null || publicKeyFile.length() == 0) {
@ -153,12 +163,12 @@ public class CryptoUtils {
}
/**
* 加密算法RSA
* 解密算法 RSA
*
* @param publicKey 公钥
* @param cipherText 需要加密的字符串
* @return 密后的字符串
* @throws Exception 密过程中的异常信息
* @param publicKey - 公钥
* @param cipherText - 需要解密的字符串
* @return String - 密后的字符串
* @throws Exception - 密过程中的异常信息
*/
public static String decrypt(PublicKey publicKey, String cipherText) throws Exception {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
@ -168,8 +178,7 @@ public class CryptoUtils {
// 因为 IBM JDK 不支持私钥加密, 公钥解密, 所以要反转公私钥
// 也就是说对于解密, 可以通过公钥的参数伪造一个私钥对象欺骗 IBM JDK
RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
RSAPrivateKeySpec spec = new RSAPrivateKeySpec(rsaPublicKey.getModulus(),
rsaPublicKey.getPublicExponent());
RSAPrivateKeySpec spec = new RSAPrivateKeySpec(rsaPublicKey.getModulus(), rsaPublicKey.getPublicExponent());
Key fakePrivateKey = KeyFactory.getInstance("RSA").generatePrivate(spec);
//It is a stateful object. so we need to get new one.
cipher = Cipher.getInstance("RSA");
@ -179,31 +188,46 @@ public class CryptoUtils {
if (cipherText == null || cipherText.length() == 0) {
return cipherText;
}
byte[] cipherBytes = Base64.base64ToByteArray(cipherText);
byte[] plainBytes = cipher.doFinal(cipherBytes);
int inputLength = cipherBytes.length;
// 标识
int offSet = 0;
byte[] resultBytes = {};
byte[] cache = {};
// 分段解密
while (inputLength - offSet > 0) {
if (inputLength - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(cipherBytes, offSet, MAX_DECRYPT_BLOCK);
offSet += MAX_DECRYPT_BLOCK;
} else {
cache = cipher.doFinal(cipherBytes, 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 new String(plainBytes);
return new String(resultBytes);
}
/**
* 加密算法RSA
* 加密算法 RSA
*
* @param plainText 需要加密的字符串
* @return 加密后的字符串
* @throws Exception 加密过程中的异常信息
* @param plainText - 需要加密的字符串
* @return String - 加密后的字符串
* @throws Exception - 加密过程中的异常信息
*/
public static String encrypt(String plainText) throws Exception {
return encrypt((String) null, plainText);
}
/**
* 加密算法RSA
* 加密算法 RSA
*
* @param key 加密的密钥
* @param plainText 需要加密的字符串
* @return 加密后的字符串
* @throws Exception 加密过程中的异常信息
* @param key - 加密的密钥
* @param plainText - 需要加密的字符串
* @return String - 加密后的字符串
* @throws Exception - 加密过程中的异常信息
*/
public static String encrypt(String key, String plainText) throws Exception {
if (key == null) {
@ -215,12 +239,12 @@ public class CryptoUtils {
}
/**
* 加密算法RSA
* 加密算法 RSA
*
* @param keyBytes 加密的密钥
* @param plainText 需要加密的字符串
* @return 加密后的字符串
* @throws Exception 加密过程中的异常信息
* @param keyBytes - 加密的密钥
* @param plainText - 需要加密的字符串
* @return String - 加密后的字符串
* @throws Exception - 加密过程中的异常信息
*/
public static String encrypt(byte[] keyBytes, String plainText) throws Exception {
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
@ -232,20 +256,38 @@ public class CryptoUtils {
} catch (InvalidKeyException e) {
//For IBM JDK, 原因请看解密方法中的说明
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKey;
RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(rsaPrivateKey.getModulus(),
rsaPrivateKey.getPrivateExponent());
RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(rsaPrivateKey.getModulus(), rsaPrivateKey.getPrivateExponent());
Key fakePublicKey = KeyFactory.getInstance("RSA").generatePublic(publicKeySpec);
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, fakePublicKey);
}
return Base64.byteArrayToBase64(cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8)));
byte[] inputArray = plainText.getBytes();
int inputLength = inputArray.length;
// 标识
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 Base64.byteArrayToBase64(resultBytes);
}
/**
* 生成密钥对
*
* @param keySize 密钥对长度
* @return 密钥对
* @param keySize - 密钥对长度
* @return byte[][] - 密钥对
*/
public static byte[][] genKeyPairBytes(int keySize) {
byte[][] keyPairBytes = new byte[2][];
@ -266,8 +308,8 @@ public class CryptoUtils {
/**
* 生成密钥对
*
* @param keySize 密钥对长度
* @return Base64编码后的密钥对
* @param keySize - 密钥对长度
* @return String[] - Base64编码后的密钥对
*/
public static String[] genKeyPair(int keySize) {
byte[][] keyPairBytes = genKeyPairBytes(keySize);
@ -276,4 +318,5 @@ public class CryptoUtils {
keyPairs[1] = Base64.byteArrayToBase64(keyPairBytes[1]);
return keyPairs;
}
}
}