CryptoUtil工具类
/**
* 工具类--来自官方Demo
*/
package cn.com.sandpay.util;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.X509Certificate;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
/**
* @version 2.0.0
* @ClassName: CryptoUtil
* @Description: sdk加解密工具类,主要用于签名、验证、RSA加解密等
*/
public class CryptoUtil {
public static Logger logger = LoggerFactory.getLogger(CryptoUtil.class);
/**
* 数字签名函数入口
*
* @param plainBytes 待签名明文字节数组
* @param privateKey 签名使用私钥
* @param signAlgorithm 签名算法
* @return 签名后的字节数组
* @throws Exception
*/
public static byte[] digitalSign(byte[] plainBytes, PrivateKey privateKey, String signAlgorithm) throws Exception {
try {
Signature signature = Signature.getInstance(signAlgorithm);
signature.initSign(privateKey);
signature.update(plainBytes);
byte[] signBytes = signature.sign();
return signBytes;
} catch (NoSuchAlgorithmException e) {
throw new Exception(String.format("数字签名时没有[%s]此类算法", signAlgorithm));
} catch (InvalidKeyException e) {
throw new Exception("数字签名时私钥无效", e);
} catch (SignatureException e) {
throw new Exception("数字签名时出现异常", e);
}
}
/**
* 验证数字签名函数入口
*
* @param plainBytes 待验签明文字节数组
* @param signBytes 待验签签名后字节数组
* @param publicKey 验签使用公钥
* @param signAlgorithm 签名算法
* @return 验签是否通过
* @throws Exception
*/
public static boolean verifyDigitalSign(byte[] plainBytes, byte[] signBytes, PublicKey publicKey, String signAlgorithm) throws Exception {
boolean isValid = false;
try {
Signature signature = Signature.getInstance(signAlgorithm);
signature.initVerify(publicKey);
signature.update(plainBytes);
isValid = signature.verify(signBytes);
return isValid;
} catch (NoSuchAlgorithmException e) {
throw new Exception(String.format("验证数字签名时没有[%s]此类算法", signAlgorithm), e);
} catch (InvalidKeyException e) {
throw new Exception("验证数字签名时公钥无效", e);
} catch (SignatureException e) {
throw new Exception("验证数字签名时出现异常", e);
}
}
/**
* 验证数字签名函数入口
*
* @param plainBytes 待验签明文字节数组
* @param signBytes 待验签签名后字节数组
* @param signAlgorithm 签名算法
* @return 验签是否通过
* @throws Exception
*/
public static boolean verifyDigitalSign(byte[] plainBytes, byte[] signBytes, X509Certificate cert, String signAlgorithm) throws Exception {
boolean isValid = false;
try {
Signature signature = Signature.getInstance(signAlgorithm);
signature.initVerify(cert);
signature.update(plainBytes);
isValid = signature.verify(signBytes);
return isValid;
} catch (NoSuchAlgorithmException e) {
throw new Exception(String.format("验证数字签名时没有[%s]此类算法", signAlgorithm));
} catch (InvalidKeyException e) {
throw new Exception("验证数字签名时公钥无效", e);
} catch (SignatureException e) {
throw new Exception("验证数字签名时出现异常", e);
}
}
/**
* RSA加密
*
* @param plainBytes 明文字节数组
* @param publicKey 公钥
* @param keyLength 密钥bit长度
* @param reserveSize padding填充字节数,预留11字节
* @param cipherAlgorithm 加解密算法,一般为RSA/ECB/PKCS1Padding
* @return 加密后字节数组,不经base64编码
* @throws Exception
*/
public static byte[] RSAEncrypt(byte[] plainBytes, PublicKey publicKey, int keyLength, int reserveSize, String cipherAlgorithm)
throws Exception {
int keyByteSize = keyLength / 8; // 密钥字节数
int encryptBlockSize = keyByteSize - reserveSize; // 加密块大小=密钥字节数-padding填充字节数
int nBlock = plainBytes.length / encryptBlockSize;// 计算分段加密的block数,向上取整
if ((plainBytes.length % encryptBlockSize) != 0) { // 余数非0,block数再加1
nBlock += 1;
}
try {
Cipher cipher = Cipher.getInstance(cipherAlgorithm);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// 输出buffer,大小为nBlock个keyByteSize
ByteArrayOutputStream outbuf = new ByteArrayOutputStream(nBlock * keyByteSize);
// 分段加密
for (int offset = 0; offset < plainBytes.length; offset += encryptBlockSize) {