最大加密字节数 53 ,超出最大字节数需要分组加密; 最大解密字节数 64 ,超出最大字节数需要分组解密 (#537)
This commit is contained in:
parent
d373cd7fb3
commit
659edc8b13
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user