package com.nova.sankuai.infra.utils.rongbei;
|
|
import lombok.SneakyThrows;
|
|
import javax.crypto.Cipher;
|
import java.io.ByteArrayOutputStream;
|
import java.security.KeyFactory;
|
import java.security.Signature;
|
import java.security.interfaces.RSAPrivateKey;
|
import java.security.interfaces.RSAPublicKey;
|
import java.security.spec.KeySpec;
|
import java.security.spec.PKCS8EncodedKeySpec;
|
import java.security.spec.X509EncodedKeySpec;
|
import java.util.Base64;
|
|
/**
|
* RSA 支持类
|
*/
|
public class RsaSupport {
|
/**
|
* 默认值-密钥key算法
|
*/
|
public static final String DEFAULT_KEY_ALGORITHM = "RSA";
|
/**
|
* 默认值-签名算法
|
*/
|
public static final String DEFAULT_SIGNATURE_ALGORITHM = "SHA256WithRSA";
|
/**
|
* 默认值-加解密算法
|
*/
|
public static final String DEFAULT_CIPHER_ALGORITHM = "RSA/ECB/PKCS1Padding";
|
/**
|
* 默认值-默认字符编码
|
*/
|
public static final String DEFAULT_CHARSET_NAME = "utf-8";
|
|
/**
|
* 默认值-加密块长度
|
*/
|
private final int DEFAULT_MAX_ENCRYPT_BLOCK = 117;
|
|
private final String KEY_ALGORITHM;
|
private final String SIGNATURE_ALGORITHM;
|
private final String CIPHER_ALGORITHM;
|
private final String CHARSET_NAME;
|
|
/**
|
* rsa-公钥
|
*/
|
private String pukStr;
|
/**
|
* rsa-私钥
|
*/
|
private String prkStr;
|
|
public RsaSupport() {
|
this.KEY_ALGORITHM = DEFAULT_KEY_ALGORITHM;
|
this.SIGNATURE_ALGORITHM = DEFAULT_SIGNATURE_ALGORITHM;
|
this.CIPHER_ALGORITHM = DEFAULT_CIPHER_ALGORITHM;
|
this.CHARSET_NAME = DEFAULT_CHARSET_NAME;
|
}
|
|
public RsaSupport(String keyAlgorithm, String signatureAlgorithm, String cipherAlgorithm, String charsetName) {
|
this.KEY_ALGORITHM = keyAlgorithm;
|
this.SIGNATURE_ALGORITHM = signatureAlgorithm;
|
this.CIPHER_ALGORITHM = cipherAlgorithm;
|
this.CHARSET_NAME = charsetName;
|
}
|
|
public RsaSupport(String keyAlgorithm, String signatureAlgorithm, String cipherAlgorithm, String charsetName,
|
String pukStr, String prkStr) {
|
this.KEY_ALGORITHM = keyAlgorithm;
|
this.SIGNATURE_ALGORITHM = signatureAlgorithm;
|
this.CIPHER_ALGORITHM = cipherAlgorithm;
|
this.CHARSET_NAME = charsetName;
|
this.pukStr = pukStr;
|
this.prkStr = prkStr;
|
}
|
|
/**
|
* 使用私钥对数据进行签名
|
*
|
* @param data
|
* 需要签名的数据
|
* @return 返回加签名后的BASE64编码的字符串
|
* @throws Exception
|
*/
|
public String signByPrivateKey(String data) {
|
return signByPrivateKey(data, prkStr);
|
}
|
|
/**
|
* 使用私钥对数据进行签名
|
*
|
* @param data
|
* 需要签名的数据
|
* @param prkStr
|
* 私钥(使用BASE64进行编码)
|
* @return 返回加签名后的BASE64编码的字符串
|
* @throws Exception
|
*/
|
@SneakyThrows
|
public String signByPrivateKey(String data, String prkStr) {
|
if (prkStr != null) {
|
prkStr = prkStr.replaceAll(" ", "");
|
}
|
byte[] privateKeyByte = java.util.Base64.getDecoder().decode(prkStr);
|
// 私钥格式,从字节数组中构建的私钥内容
|
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyByte);
|
// 密钥工厂
|
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
|
// 通过密钥工厂,从指定的密钥中生成RSA格式的私钥对象
|
RSAPrivateKey privateKey = (RSAPrivateKey)keyFactory.generatePrivate(keySpec);
|
// 签名算法
|
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
|
// 签名算法采用私钥初始化
|
signature.initSign(privateKey);
|
// 将字符串编码为指定字符集字符数组,此处传入被签名的内容
|
signature.update(data.getBytes(CHARSET_NAME));
|
// 签名,并将签名后的内容编码为base64的字符串返回
|
return java.util.Base64.getEncoder().encodeToString(signature.sign());
|
}
|
|
/**
|
* 使用公钥进行数字签名的校验
|
*
|
* @param data
|
* 需要进行验签的原始数据
|
* @param sign
|
* 签名 (BASE64编码字符串)
|
* @return
|
* @throws Exception
|
*/
|
public boolean verifyByPublicKey(String data, String sign) {
|
return verifyByPublicKey(data, sign, pukStr);
|
}
|
|
/**
|
* 使用公钥进行数字签名的校验
|
*
|
* @param data
|
* 需要进行验签的原始数据
|
* @param pukStr
|
* 公钥(BASE64编码字符串)
|
* @param sign
|
* 签名 (BASE64编码字符串)
|
* @return
|
* @throws Exception
|
*/
|
public boolean verifyByPublicKey(String data, String sign, String pukStr) {
|
try {
|
if (pukStr != null) {
|
pukStr = pukStr.replaceAll(" ", "");
|
}
|
// 公钥字符串解码
|
byte[] publicKeyByte = java.util.Base64.getDecoder().decode(pukStr);
|
// x509格式结构的公钥
|
X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(publicKeyByte);
|
// RSA算法之密钥生成器
|
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
|
// 从结构性数据,转换为公钥对象
|
RSAPublicKey publicKey = (RSAPublicKey)keyFactory.generatePublic(encodedKeySpec);
|
// 签名算法
|
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
|
// 初始化验证用的公钥
|
signature.initVerify(publicKey);
|
// 更新需要要整的内容
|
signature.update(data.getBytes(CHARSET_NAME));
|
// 判断是否是对应的签名
|
return signature.verify(Base64.getDecoder().decode(sign));
|
} catch (Exception e) {
|
e.printStackTrace();
|
return false;
|
}
|
}
|
|
/**
|
* 公钥加密
|
*
|
* @param plainText
|
* @return
|
* @throws Exception
|
*/
|
public String encryptByPublicKey(String plainText) {
|
return encryptByPublicKey(plainText, pukStr);
|
}
|
|
/**
|
* 公钥加密
|
*
|
* @param plainText
|
* @param pukStr
|
* @return
|
* @throws Exception
|
*/
|
@SneakyThrows
|
public String encryptByPublicKey(String plainText, String pukStr) {
|
if (null == plainText) {
|
return null;
|
}
|
|
if (pukStr != null) {
|
pukStr = pukStr.replaceAll(" ", "");
|
}
|
|
byte[] dataB = plainText.getBytes(CHARSET_NAME);
|
byte[] publicKeyByte = Base64.getDecoder().decode(pukStr);
|
X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(publicKeyByte);
|
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
|
RSAPublicKey publicKey = (RSAPublicKey)keyFactory.generatePublic(encodedKeySpec);
|
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
|
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
int inputLen = dataB.length;
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
int offSet = 0;
|
byte[] cache;
|
int i = 0;
|
// 对数据分段加密
|
while (inputLen - offSet > 0) {
|
if (inputLen - offSet > DEFAULT_MAX_ENCRYPT_BLOCK) {
|
cache = cipher.doFinal(dataB, offSet, DEFAULT_MAX_ENCRYPT_BLOCK);
|
} else {
|
cache = cipher.doFinal(dataB, offSet, inputLen - offSet);
|
}
|
out.write(cache, 0, cache.length);
|
i++;
|
offSet = i * DEFAULT_MAX_ENCRYPT_BLOCK;
|
}
|
byte[] encryptedData = out.toByteArray();
|
out.close();
|
return Base64.getEncoder().encodeToString(encryptedData);
|
}
|
|
/**
|
* 私钥解密
|
*
|
* @param encryptedStr
|
* @return
|
* @throws Exception
|
*/
|
public String decryptByPrivateKey(String encryptedStr) {
|
return decryptByPrivateKey(encryptedStr, prkStr);
|
}
|
|
/**
|
* 私钥解密
|
*
|
* @param encryptedStr
|
* @param prkStr
|
* @return
|
* @throws Exception
|
*/
|
@SneakyThrows
|
public String decryptByPrivateKey(String encryptedStr, String prkStr) {
|
if (null == encryptedStr) {
|
return null;
|
}
|
|
if (prkStr != null) {
|
prkStr = prkStr.replaceAll(" ", "");
|
}
|
|
byte[] dataB = Base64.getDecoder().decode(encryptedStr);
|
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
|
KeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(prkStr));
|
RSAPrivateKey privateKey = (RSAPrivateKey)keyFactory.generatePrivate(keySpec);
|
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
|
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
// 模长
|
int key_len = privateKey.getModulus().bitLength() / 8;
|
byte[] decryptedData = null;
|
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
try {
|
int dataLength = dataB.length;
|
for (int i = 0; i < dataLength; i += key_len) {
|
int decryptLength = dataLength - i < key_len ? dataLength - i : key_len;
|
byte[] doFinal = cipher.doFinal(dataB, i, decryptLength);
|
bout.write(doFinal);
|
}
|
decryptedData = bout.toByteArray();
|
} finally {
|
if (bout != null) {
|
bout.close();
|
}
|
}
|
return new String(decryptedData);
|
}
|
}
|