之前写过一篇java实现AES对称加密解密
在对密码加密传输的场景下 RSA非对称加密解密可能会更加适合。
原理就是后台生成一对公钥和私钥,公钥给前端用来加密,后台用私钥去解密,保证了传输过程中就算被截获也避免密码泄露。
下面是代码:
package com.zhaohy.app.utils;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class RSAUtil {
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 117;
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 128;
/**
* 获取密钥对
*
* @return 密钥对
*/
public static KeyPair getKeyPair() throws Exception {
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(1024);
return generator.generateKeyPair();
}
/**
* 获取私钥
*
* @param privateKey 私钥字符串
* @return
*/
public static PrivateKey getPrivateKey(String privateKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
return keyFactory.generatePrivate(keySpec);
}
/**
* 获取公钥
*
* @param publicKey 公钥字符串
* @return
*/
public static PublicKey getPublicKey(String publicKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
return keyFactory.generatePublic(keySpec);
}
/**
* RSA加密
*
* @param data 待加密数据
* @param publicKey 公钥
* @return
*/
public static String encrypt(String data, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
int inputLen = data.getBytes().length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offset = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offset > 0) {
if (inputLen - offset > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data.getBytes(), offset, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);
}
out.write(cache, 0, cache.length);
i++;
offset = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
// 获取加密内容使用base64进行编码,并以UTF-8为标准转化成字符串
// 加密后的字符串
return new String(Base64.encodeBase64String(encryptedData));
}
/**
* RSA解密
*
* @param data 待解密数据
* @param privateKey 私钥
* @return
*/
public static String decrypt(String data, PrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] dataBytes = Base64.decodeBase64(data);
int inputLen = dataBytes.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offset = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offset > 0) {
if (inputLen - offset > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
}
out.write(cache, 0, cache.length);
i++;
offset = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
// 解密后的内容
return new String(decryptedData, "UTF-8");
}
/**
* 签名
*
* @param data 待签名数据
* @param privateKey 私钥
* @return 签名
*/
public static String sign(String data, PrivateKey privateKey) throws Exception {
byte[] keyBytes = privateKey.getEncoded();
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey key = keyFactory.generatePrivate(keySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initSign(key);
signature.update(data.getBytes());
return new String(Base64.encodeBase64(signature.sign()));
}
/**
* 验签
*
* @param srcData 原始字符串
* @param publicKey 公钥
* @param sign 签名
* @return 是否验签通过
*/
public static boolean verify(String srcData, PublicKey publicKey, String sign) throws Exception {
byte[] keyBytes = publicKey.getEncoded();
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey key = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initVerify(key);
signature.update(srcData.getBytes());
return signature.verify(Base64.decodeBase64(sign.getBytes()));
}
/**
* 文件解密
*
* @param publicKeyStr
* @param srcFileName
* @param destFileName
*/
public static void decryptFileBig(String publicKeyStr, String srcFileName, String destFileName) {
Cipher cipher = null;
InputStream is = null;
OutputStream out = null;
try {
X509EncodedKeySpec encodedKey = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyStr));
KeyFactory keyf = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyf.generatePublic(encodedKey);
cipher = Cipher.getInstance("RSA", new BouncyCastleProvider());
cipher.init(Cipher.DECRYPT_MODE, pubKey);
File f = new File(srcFileName);
is = new FileInputStream(f);
out = new FileOutputStream(destFileName);
int blockSize = cipher.getBlockSize();
int size = Integer.valueOf(String.valueOf(f.length()));
byte[] decryptByte = new byte[size];
is.read(decryptByte);
//分别对各块数据进行解密
int j = 0;
while ((decryptByte.length - j * blockSize) > 0) {
out.write(cipher.doFinal(decryptByte, j * blockSize, blockSize));
j++;
}
} catch (Exception e) {
System.out.println(e);
} finally {
if (null != out) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 加密大文件
* @param privateKeyStr
* @param srcFileName
* @param destFileName
*/
public static void encryptFileBig(String privateKeyStr, String srcFileName, String destFileName) {
if (privateKeyStr == null) {
new Exception("加密私钥为空, 请设置");
}
Cipher cipher = null;
InputStream is = null;
OutputStream out = null;
CipherInputStream cis = null;
try {
// 使用默认RSA
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
Base64.decodeBase64(privateKeyStr));
KeyFactory keyf = KeyFactory.getInstance("RSA");
PrivateKey priKey = keyf.generatePrivate(priPKCS8);
cipher = Cipher.getInstance("RSA", new BouncyCastleProvider());
cipher.init(Cipher.ENCRYPT_MODE, priKey);
int blockSize = cipher.getBlockSize();
is = new FileInputStream(srcFileName);
File f = new File(srcFileName);
int size = Integer.valueOf(String.valueOf(f.length()));
byte[] encryptByte = new byte[size];
is.read(encryptByte);
out = new FileOutputStream(destFileName);
int outputBlockSize = cipher.getOutputSize(encryptByte.length);
int leavedSize = encryptByte.length % blockSize;
int blocksNum = leavedSize == 0 ? encryptByte.length / blockSize : encryptByte.length / blockSize + 1;
byte[] cipherData = new byte[blocksNum * outputBlockSize];
for (int i = 0; i < blocksNum; i++) {
if ((encryptByte.length - i * blockSize) > blockSize) {
cipher.doFinal(encryptByte, i * blockSize, blockSize, cipherData,i * outputBlockSize);
} else {
cipher.doFinal(encryptByte, i * blockSize, encryptByte.length - i * blockSize,cipherData, i * outputBlockSize);
}
}
out.write(cipherData);
} catch (Exception e) {
System.out.println(e);
} finally {
if (null != cis) {
try {
cis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != out) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* RSA文件签名
*
* @param filePath
* @param privateKey
* @param encode
* @return
*/
public static String signFile(String filePath, String privateKey, String encode) {
FileInputStream fis = null;
InputStreamReader isr = null;
BufferedReader bfr = null;
try {
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
KeyFactory keyf = KeyFactory.getInstance("RSA");
PrivateKey priKey = keyf.generatePrivate(priPKCS8);
java.security.Signature signature = java.security.Signature.getInstance("SHA1WithRSA");
signature.initSign(priKey);
fis = new FileInputStream(new File(filePath));
isr = new InputStreamReader(fis, encode);
bfr = new BufferedReader(isr);
String lineTxt = "";
while (!AppFrameworkUtil.isBlank(lineTxt = bfr.readLine())) {
signature.update(lineTxt.getBytes(encode));
}
byte[] signed = signature.sign();
String ret = new String(Base64.encodeBase64(signed));
System.out.println("signed:" + ret);
return ret;
} catch (Exception e) {
System.out.println(e);
} finally {
if (bfr != null) {
try {
bfr.close();
} catch (IOException e) {
}
}
if (isr != null) {
try {
isr.close();
} catch (IOException e) {
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
}
}
}
return null;
}
/**
* RSA文件验签名检查
* @param content 待签名数据
* @param sign 签名值
* @param publicKey 分配给开发商公钥
* @param encode 字符集编码
* @return 布尔值
*/
public static boolean doCheckFile(String filePath, String sign, String publicKey, String encode) {
FileInputStream fis = null;
InputStreamReader isr = null;
BufferedReader bfr = null;
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] encodedKey = Base64.decodeBase64(publicKey);
PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
java.security.Signature signature = java.security.Signature.getInstance("SHA1WithRSA");
signature.initVerify(pubKey);
fis = new FileInputStream(new File(filePath));
isr = new InputStreamReader(fis, "UTF-8");
bfr = new BufferedReader(isr);
String lineTxt = "";
while (!AppFrameworkUtil.isBlank(lineTxt = bfr.readLine())) {
signature.update(lineTxt.getBytes(encode));
}
boolean bverify = signature.verify(Base64.decodeBase64(sign));
return bverify;
} catch (Exception e) {
System.out.println(e);
} finally {
if (bfr != null) {
try {
bfr.close();
} catch (IOException e) {
}
}
if (isr != null) {
try {
isr.close();
} catch (IOException e) {
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
}
}
}
return false;
}
public static void main(String[] args) {
try {
// 生成密钥对
KeyPair keyPair = getKeyPair();
String privateKey = new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));
String publicKey = new String(Base64.encodeBase64(keyPair.getPublic().getEncoded()));
System.out.println("私钥:" + privateKey);
System.out.println("公钥:" + publicKey);
// RSA加密
String data = "123秘密啊";
String encryptData = encrypt(data, getPublicKey(publicKey));
System.out.println("加密后内容:" + encryptData);
// RSA解密
String decryptData = decrypt(encryptData, getPrivateKey(privateKey));
System.out.println("解密后内容:" + decryptData);
// RSA签名
String sign = sign(data, getPrivateKey(privateKey));
System.out.println("sign==" + sign);
// RSA验签
boolean result = verify(data, getPublicKey(publicKey), sign);
System.out.println("验签结果:" + result);
/****大文件加签验签****/
//加签验签
String fileSign = signFile("/home/zhaohy/Documents/test.doc", privateKey, "UTF-8");
System.out.println("fileSign==" + fileSign);
boolean checkFileBoolean = doCheckFile("/home/zhaohy/Documents/test.doc", fileSign, publicKey, "UTF-8");
System.out.println("大文件校验签名结果:" + checkFileBoolean);
//加密解密
encryptFileBig(privateKey, "/home/zhaohy/Documents/test.txt", "/home/zhaohy/Documents/test.dat");
decryptFileBig(publicKey, "/home/zhaohy/Documents/test.dat", "/home/zhaohy/Documents/test1.txt");
} catch (Exception e) {
e.printStackTrace();
System.out.print("加解密异常");
}
}
}
运行结果:
私钥:MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALpLjdbsu172ftiv3eUC/JghSSzNRlp8p9Ilr8XlK/gl3gaPFFo1BAHWWyb9MhoTdE5BvES6E/eW5gVKby8olLa6ILbh9UYif0SKWca7pTt2nqn2Cd8v29/94ZF9i+yMoime3wuS7QxJEHG7qCqps7KVNtP/4/628lq1jB6B3DrPAgMBAAECgYBUtCGrxTt0dBM8psn3ZKJA8XF6A2OnpOIRNL109zxEucL3rHqOgWhvBW2wjpMHNC0/n7fgb9LAUkYHxc5D3OmwXAhvgRzDmMTeoaikrLeJpxX9NQ4TU3CFcL9YabQ+rjB6yMgfbmmA0B/odxpzIZd6ypHq91ogI/rfP4McaX7NwQJBAO9Qm4SoOn/0SzfOE+PjnIyLkDqW2kFRJv+c/4Z0H/yPOIjytHhe6hQQ8KHT2azOP+SeAWbjb152a5Rp/E8da/8CQQDHSKDBSGZuN/Qyk1eGJ80T9+GSQI0oYQfZcHYNUkAKrWceHISL5jMrUXWHSlKjFC5E7RsqQKMn72xisrlLcXExAkEA7YAB11VdOT8opulNtAxfgNvA92RelhQDsAoPTVBRrkQ0xzSXBh6sD93/8ZpdnLHTlv94RLPSAt1jRpcoXxvD4QJBALtv00uYVkdqt3NuZE8ZVmlmp7KQpnQJN4HLpi2HZBbm2+tVdVHEVfJzbrCuNiWO0KohvYAzRYJFTlNSuLd93rECQDcgPHh0qBOW22ggxiqpfbLIURvPAT9urp8NuTM0K0rW3mC2me55yPSDQ7jL1t9vwYkfahc0GUl1V1Cq/449AHU=
公钥:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6S43W7Lte9n7Yr93lAvyYIUkszUZafKfSJa/F5Sv4Jd4GjxRaNQQB1lsm/TIaE3ROQbxEuhP3luYFSm8vKJS2uiC24fVGIn9EilnGu6U7dp6p9gnfL9vf/eGRfYvsjKIpnt8Lku0MSRBxu6gqqbOylTbT/+P+tvJatYwegdw6zwIDAQAB
加密后内容:R7GqGE2r51PmJAt3wtKhsbqfFzeobvzqFlAp8Tv0+3HkevsUF2a+/ZO7Sn53cKGwXIkOkDQN0S/pk/Eacd8Wk1wXKTKx57eSaQJFv/HQ5nDUfvtMWIg0IcHNmHyNBfDPVe/MiMkKf23/a/EyEfCQEzsCQyHLyHoTg34a1SNXTLs=
解密后内容:123秘密啊
sign==p8JR0aserak6iPltfAJx/mlvlp5Ox5NcpvRo7R1rxDItekMhyF82RVizgMqsmEBpWzW9Qkxm6AWzjzEr+XhR7u4KhxEO7euTHC9NGJ0TAtDKqtAsfFaZi8ZyY4MkHnSCFZVMcWMR3GhZ8ALJGe/lSstNSEp8H9lQE8u2o2oYiiw=
验签结果:true
signed:aavuNSCwaT2jZ6XrlAbSJNLBDalkWZ1t0tnQnveUw+3exlpcvRu0xotAlrW0V4voLLeRydLgIjwCwq1YxqFyKcYlOuORzorlmihjSXBZf0GZoJIlTIaUZ8/TJV+CRFObFnnEQ+8QAbRs4b7AB6nv1A2bxMeKulS0OTPxSkSFTdM=
fileSign==aavuNSCwaT2jZ6XrlAbSJNLBDalkWZ1t0tnQnveUw+3exlpcvRu0xotAlrW0V4voLLeRydLgIjwCwq1YxqFyKcYlOuORzorlmihjSXBZf0GZoJIlTIaUZ8/TJV+CRFObFnnEQ+8QAbRs4b7AB6nv1A2bxMeKulS0OTPxSkSFTdM=
大文件校验签名结果:true
可以看到加密解密成功,里面最后加密解密文件自测只对txt或html等文本文件有效,doc或者excel加密文件后解密出来的东西乱码。
参考:https://www.cnblogs.com/pcheng/p/9629621.html
====2021年5月28日更新====
以上分段加密解密时针对1024长度的密文有效2048长度的密文就会报错,所以更新以下工具类,兼容2048而且还有针对pem格式的秘钥处理。
package ly.mp.project.common.otautils;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMDecryptorProvider;
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
import org.bouncycastle.operator.InputDecryptorProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
import org.bouncycastle.pkcs.PKCSException;
public class RSAUtils {
/**
* 秘钥对算法名称
*/
private static final String ALGORITHM = "RSA";
private static final String SIGN_SHA1RSA_ALGORITHMS = "SHA1WithRSA";
private static final String SIGN_SHA256RSA_ALGORITHMS = "SHA256WithRSA";
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK_1024 = 117;
private static final int MAX_ENCRYPT_BLOCK_2048 = 245;
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK_1024 = 128;
private static final int MAX_DECRYPT_BLOCK_2048 = 256;
/**
* RSA2048公私钥长度
*/
private static final int PUBLIC_KEY_LEN_2048 = 392;
private static final int PRIVATE_KEY_LEN_2048 = 1264;
static {
java.security.Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
}
/**
* SHA1WithRSA算法签名
*/
public static String SHA1WithRSASign(String content, String privateKey, String charset) throws Exception {
return signHandle(content, privateKey, charset, SIGN_SHA1RSA_ALGORITHMS);
}
/**
* SHA1WithRSA算法签名
*/
public static String SHA1WithRSASign(byte[] contentByte, String privateKey) throws Exception {
return signHandle(contentByte, privateKey, SIGN_SHA1RSA_ALGORITHMS);
}
/**
* SHA1WithRSAPemKey算法签名
*/
public static String SHA1WithRSAPemKeySign(byte[] contentByte, String privateKey) throws Exception {
return signPemKeyHandle(contentByte, privateKey, SIGN_SHA1RSA_ALGORITHMS);
}
/**
* SHA256WithRSA 算法签名
*/
public static String SHA256WithRSASign(String content, String privateKey, String charset) throws Exception {
return signHandle(content, privateKey, charset, SIGN_SHA256RSA_ALGORITHMS);
}
/**
* SHA256WithRSA 算法签名
*/
public static String SHA256WithRSASign(byte[] contentByte, String privateKey) throws Exception {
return signHandle(contentByte, privateKey, SIGN_SHA256RSA_ALGORITHMS);
}
/**
* SHA256WithRSAPemKey 算法签名
*/
public static String SHA256WithRSAPemKeySign(byte[] contentByte, String privateKey) throws Exception {
return signPemKeyHandle(contentByte, privateKey, SIGN_SHA256RSA_ALGORITHMS);
}
/**
* SHA1WithRSA算法验签
*/
public static boolean SHA1WithRSAVerify(String content, String publicKey, String signInfo, String charset) throws Exception {
return verifyHandle(content, publicKey, signInfo, charset, SIGN_SHA1RSA_ALGORITHMS);
}
/**
* SHA1WithRSA算法验签
*/
public static boolean SHA1WithRSAVerify(byte[] contentByte, String publicKey, String signInfo) throws Exception {
return verifyHandle(contentByte, publicKey, signInfo, SIGN_SHA1RSA_ALGORITHMS);
}
/**
* SHA1WithRSA算法验签
*/
public static boolean SHA1WithRSAPemKeyVerify(byte[] contentByte, String publicKey, String signInfo) throws Exception {
return verifyPemKeyHandle(contentByte, publicKey, signInfo, SIGN_SHA1RSA_ALGORITHMS);
}
/**
* SHA256WithRSA算法验签
*/
public static boolean SHA256WithRSAVerify(String content, String publicKey, String signInfo, String charset) throws Exception {
return verifyHandle(content, publicKey, signInfo, charset, SIGN_SHA256RSA_ALGORITHMS);
}
/**
* SHA256WithRSA算法验签
*/
public static boolean SHA256WithRSAVerify(byte[] contentByte, String publicKey, String signInfo) throws Exception {
return verifyHandle(contentByte, publicKey, signInfo, SIGN_SHA256RSA_ALGORITHMS);
}
/**
* SHA256WithRSA算法验签
*/
public static boolean SHA256WithRSAPemKeyVerify(byte[] contentByte, String publicKey, String signInfo) throws Exception {
return verifyPemKeyHandle(contentByte, publicKey, signInfo, SIGN_SHA256RSA_ALGORITHMS);
}
/**
* 签名处理
*/
public static String signHandle(String content, String privateKey, String charset, String algorithm) throws Exception {
Signature signature = Signature.getInstance(algorithm);
signature.initSign(getPrivateKey(privateKey));
if (charset == null || charset.length() == 0) {
signature.update(content.getBytes());
} else {
signature.update(content.getBytes(charset));
}
byte[] signed = signature.sign();
return new String(Base64.encodeBase64(signed));
}
/**
* 签名处理
*/
public static String signHandle(byte[] contentByte, String privateKey, String algorithm) throws Exception {
Signature signature = Signature.getInstance(algorithm);
signature.initSign(getPrivateKey(privateKey));
signature.update(contentByte);
byte[] signed = signature.sign();
return new String(Base64.encodeBase64(signed));
}
/**
* pemStrKey签名处理
*/
public static String signPemKeyHandle(byte[] contentByte, String privateKey, String algorithm) throws Exception {
Signature signature = Signature.getInstance(algorithm);
signature.initSign(privateKey(privateKey));
signature.update(contentByte);
byte[] signed = signature.sign();
return new String(Base64.encodeBase64(signed));
}
/**
* 验签处理
*/
public static boolean verifyHandle(String content, String publicKey, String signInfo, String charset, String algorithm) throws Exception {
Signature signature = Signature.getInstance(algorithm);
signature.initVerify(getPublicKey(publicKey));
if (charset == null || charset.length() == 0) {
signature.update(content.getBytes());
} else {
signature.update(content.getBytes(charset));
}
return signature.verify(Base64.decodeBase64(signInfo));
}
/**
* 验签处理
*/
public static boolean verifyHandle(byte[] contentByte, String publicKey, String signInfo, String algorithm) throws Exception {
Signature signature = Signature.getInstance(algorithm);
signature.initVerify(getPublicKey(publicKey));
signature.update(contentByte);
return signature.verify(Base64.decodeBase64(signInfo));
}
/**
* 验签处理
*/
public static boolean verifyPemKeyHandle(byte[] contentByte, String publicKey, String signInfo, String algorithm) throws Exception {
Signature signature = Signature.getInstance(algorithm);
signature.initVerify(publicKey(publicKey));
signature.update(contentByte);
return signature.verify(Base64.decodeBase64(signInfo));
}
/**
* 公钥解密
*/
public static String decryptByPublicKey(String publicKey, String cipherText, String charset) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, getPublicKey(publicKey));
byte[] cipherBytes = Base64.decodeBase64(cipherText);
int MAX_DECRYPT_BLOCK = publicKey.length() < PUBLIC_KEY_LEN_2048 ? MAX_DECRYPT_BLOCK_1024 : MAX_DECRYPT_BLOCK_2048;
byte[] decryptedData = sectionHandle(cipherBytes, cipher, MAX_DECRYPT_BLOCK);
return new String(decryptedData, charset);
}
public static String decryptByPemPublicKey(String pemPublicKey, String cipherText, String charset) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, publicKey(pemPublicKey));
byte[] cipherBytes = Base64.decodeBase64(cipherText);
int MAX_DECRYPT_BLOCK = pemPublicKey.length() < PUBLIC_KEY_LEN_2048 ? MAX_DECRYPT_BLOCK_1024 : MAX_DECRYPT_BLOCK_2048;
byte[] decryptedData = sectionHandle(cipherBytes, cipher, MAX_DECRYPT_BLOCK);
return new String(decryptedData, charset);
}
/**
* 私钥加密
*/
public static String encryptByPrivateKey(String privateKey, String content, String charset) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, getPrivateKey(privateKey));
int MAX_ENCRYPT_BLOCK = privateKey.length() < PRIVATE_KEY_LEN_2048 ? MAX_ENCRYPT_BLOCK_1024 : MAX_ENCRYPT_BLOCK_2048;
byte[] encryptedData = sectionHandle(content.getBytes(charset), cipher, MAX_ENCRYPT_BLOCK);
return Base64.encodeBase64String(encryptedData);
}
/**
* pem格式私钥加密
* @param pemPrivateKey
* @param contentByte
* @return
* @throws Exception
*/
public static String encryptByPemPrivateKey(String pemPrivateKey, byte[] contentByte) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, privateKey(pemPrivateKey));
int MAX_ENCRYPT_BLOCK = pemPrivateKey.length() < PRIVATE_KEY_LEN_2048 ? MAX_ENCRYPT_BLOCK_1024 : MAX_ENCRYPT_BLOCK_2048;
byte[] encryptedData = sectionHandle(contentByte, cipher, MAX_ENCRYPT_BLOCK);
return Base64.encodeBase64String(encryptedData);
}
/**
* 私钥加密
* @param privateKey
* @param contentByte
* @return
* @throws Exception
*/
public static String encryptByPrivateKey(String privateKey, byte[] contentByte) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, getPrivateKey(privateKey));
int MAX_ENCRYPT_BLOCK = privateKey.length() < PRIVATE_KEY_LEN_2048 ? MAX_ENCRYPT_BLOCK_1024 : MAX_ENCRYPT_BLOCK_2048;
byte[] encryptedData = sectionHandle(contentByte, cipher, MAX_ENCRYPT_BLOCK);
return Base64.encodeBase64String(encryptedData);
}
/**
* 私钥解密
*/
public static String decryptByPrivateKey(String privateKey, String cipherText, String charset) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKey));
byte[] cipherBytes = Base64.decodeBase64(cipherText);
int MAX_DECRYPT_BLOCK = privateKey.length() < PRIVATE_KEY_LEN_2048 ? MAX_DECRYPT_BLOCK_1024 : MAX_DECRYPT_BLOCK_2048;
byte[] decryptedData = sectionHandle(cipherBytes, cipher, MAX_DECRYPT_BLOCK);
return new String(decryptedData, charset);
}
/**
* pem格式私钥解密
* @param pemPrivateKey
* @param cipherText
* @param charset
* @return
* @throws Exception
*/
public static String decryptByPemPrivateKey(String pemPrivateKey, String cipherText, String charset) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, privateKey(pemPrivateKey));
byte[] cipherBytes = Base64.decodeBase64(cipherText);
int MAX_DECRYPT_BLOCK = pemPrivateKey.length() < PRIVATE_KEY_LEN_2048 ? MAX_DECRYPT_BLOCK_1024 : MAX_DECRYPT_BLOCK_2048;
byte[] decryptedData = sectionHandle(cipherBytes, cipher, MAX_DECRYPT_BLOCK);
return new String(decryptedData, charset);
}
/**
* 公钥加密
*/
public static String encryptByPublicKey(String publicKey, String content, String charset) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, getPublicKey(publicKey));
int MAX_ENCRYPT_BLOCK = publicKey.length() < PUBLIC_KEY_LEN_2048 ? MAX_ENCRYPT_BLOCK_1024 : MAX_ENCRYPT_BLOCK_2048;
byte[] encryptedData = sectionHandle(content.getBytes(charset), cipher, MAX_ENCRYPT_BLOCK);
return Base64.encodeBase64String(encryptedData);
}
/**
* 公钥加密
* @param publicKey
* @param contentByte
* @return
* @throws Exception
*/
public static String encryptByPublicKey(String publicKey, byte[] contentByte) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, getPublicKey(publicKey));
int MAX_ENCRYPT_BLOCK = publicKey.length() < PUBLIC_KEY_LEN_2048 ? MAX_ENCRYPT_BLOCK_1024 : MAX_ENCRYPT_BLOCK_2048;
byte[] encryptedData = sectionHandle(contentByte, cipher, MAX_ENCRYPT_BLOCK);
return Base64.encodeBase64String(encryptedData);
}
/**
* pem格式公钥加密
* @param pemPublicKey
* @param contentByte
* @return
* @throws Exception
*/
public static String encryptByPemPublicKey(String pemPublicKey, byte[] contentByte) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey(pemPublicKey));
int MAX_ENCRYPT_BLOCK = pemPublicKey.length() < PUBLIC_KEY_LEN_2048 ? MAX_ENCRYPT_BLOCK_1024 : MAX_ENCRYPT_BLOCK_2048;
byte[] encryptedData = sectionHandle(contentByte, cipher, MAX_ENCRYPT_BLOCK);
return Base64.encodeBase64String(encryptedData);
}
/**
* 构建RSA密钥对
*/
public static RSAKeyPair generateKeyPair(int keySize) throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
keyPairGenerator.initialize(keySize);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded());
String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
RSAKeyPair rsaKeyPair = new RSAKeyPair(publicKeyString, privateKeyString);
return rsaKeyPair;
}
/**
* 从公私钥文件中获取公私钥字符, 如:rsa_public_key.pem,rsa_private_key.pem
*/
public static String loadPubOrPriKeyByFile(String keyFilePath) throws Exception {
try {
BufferedReader br = new BufferedReader(new FileReader(keyFilePath));
String readLine;
StringBuilder sb = new StringBuilder();
while ((readLine = br.readLine()) != null) {
if (readLine.charAt(0) == '-') {
continue;
} else {
sb.append(readLine);
}
}
br.close();
return sb.toString();
} catch (IOException e) {
throw new Exception("公钥数据流读取错误");
} catch (NullPointerException e) {
throw new Exception("公钥输入流为空");
}
}
/**
* 从证书中获取公钥
*/
public static String loadPublicKeyByCert(String certPath) throws Exception {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(certPath);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream);
PublicKey publicKey = cert.getPublicKey();
return Base64.encodeBase64String(publicKey.getEncoded());
} catch (Exception e) {
throw new Exception("读取秘钥证书异常" + e.getMessage());
} finally {
if (inputStream != null) {
inputStream.close();
}
}
}
/**
* 私钥转换
* 用来加密的RSA私钥的格式是PKCS1格式的(适用于非java),并不是PKCS8格式的(适用于java),把PKCS1格式转为PKCS8格式
*/
private static PrivateKey getPrivateKey(String privateKeyText) throws NoSuchAlgorithmException, InvalidKeySpecException {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
return keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
}
/**
* 公钥转换
*/
private static PublicKey getPublicKey(String publicKeyText) throws NoSuchAlgorithmException, InvalidKeySpecException {
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
return keyFactory.generatePublic(x509EncodedKeySpec);
}
/**
* pem格式读取私钥
* @param pemString
* @param password
* @return
* @throws IOException
*/
public static PrivateKey privateKey(String pemString, String password) throws IOException {
return (PrivateKey) parseKey(pemString, password);
}
/**
* pem格式读取私钥
* @param pemString
* @return
* @throws IOException
*/
public static PrivateKey privateKey(String pemString) throws IOException {
return (PrivateKey) parseKey(pemString, null);
}
/**
* pem格式读取公钥
* @param pemString
* @return
* @throws IOException
*/
public static PublicKey publicKey(String pemString) throws IOException {
return (PublicKey) parseKey(pemString, null);
}
/**
* Parses a Key instance from a PEM representation.
* <p>
* When the provided key is encrypted, the provided pass phrase is applied.
*
* @param pemString a PEM representation of a private key (cannot be null or empty)
* @param passPhrase optional pass phrase (must be present if the private key is encrypted).
* @return a Key instance (never null)
*/
public static Key parseKey(String pemString, String passPhrase) throws IOException {
if (passPhrase == null) {
passPhrase = "";
}
try (StringReader reader = new StringReader(pemString); //
PEMParser pemParser = new PEMParser(reader)) {
final Object object = pemParser.readObject();
final JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME);
final KeyPair kp;
if (object instanceof PEMEncryptedKeyPair) {
// Encrypted key - we will use provided password
final PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(passPhrase.toCharArray());
kp = converter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(decProv));
} else if (object instanceof PKCS8EncryptedPrivateKeyInfo) {
// Encrypted key - we will use provided password
try {
final PKCS8EncryptedPrivateKeyInfo encryptedInfo = (PKCS8EncryptedPrivateKeyInfo) object;
final InputDecryptorProvider provider = new JceOpenSSLPKCS8DecryptorProviderBuilder().build(passPhrase.toCharArray());
final PrivateKeyInfo privateKeyInfo = encryptedInfo.decryptPrivateKeyInfo(provider);
return converter.getPrivateKey(privateKeyInfo);
} catch (PKCSException | OperatorCreationException e) {
throw new IOException("Unable to decrypt private key.", e);
}
} else if (object instanceof PrivateKeyInfo) {
return converter.getPrivateKey((PrivateKeyInfo) object);
} else if (object instanceof SubjectPublicKeyInfo) {
return converter.getPublicKey((SubjectPublicKeyInfo) object);
} else {
// Unencrypted key - no password needed
kp = converter.getKeyPair((PEMKeyPair) object);
}
return kp.getPrivate();
}
}
/**
* 分段加解密处理
*/
private static byte[] sectionHandle(byte[] data, Cipher cipher, int maxLen) throws IllegalBlockSizeException, BadPaddingException, IOException {
int dataLen = data.length;
//偏移量
int offLen = 0;
int i = 0;
byte[] cache;
ByteArrayOutputStream bops = new ByteArrayOutputStream();
while (dataLen - offLen > 0) {
if (dataLen - offLen > maxLen) {
cache = cipher.doFinal(data, offLen, maxLen);
} else {
cache = cipher.doFinal(data, offLen, dataLen - offLen);
}
bops.write(cache);
i++;
offLen = maxLen * i;
}
byte[] handleData = bops.toByteArray();
bops.close();
return handleData;
}
/**
* RSA密钥对对象
*/
public static class RSAKeyPair {
private String publicKey;
private String privateKey;
public RSAKeyPair(String publicKey, String privateKey) {
this.publicKey = publicKey;
this.privateKey = privateKey;
}
public String getPublicKey() {
return publicKey;
}
public String getPrivateKey() {
return privateKey;
}
}
}