RSA签名验签工具类
2020-08-25 本文已影响0人
爪哇驿站
一、引入相关架包(该架包主要用于解析PKCS1证书,若使用PKCS8证书无需引入)
<dependency>
<groupId>bouncycastle</groupId>
<artifactId>bcprov-jdk15</artifactId>
<version>140</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpg-jdk16</artifactId>
<version>1.46</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.65</version>
</dependency>
二、SecretUtil工具类
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;
public class SecretUtil {
private static Logger logger = LoggerFactory.getLogger(SecretUtil.class);
public static final String CHARSET = "UTF-8"; // 或者 GBK
// 设置公钥,私钥长度
public static final int KEY_SIZE = 2048;
public static final String PUBLIC_KEY_NAME = "publicKey";
public static final String PRIVATE_KEY_NAME = "privateKey";
// 定义加密算法,有DES、DESede(即3DES)、Blowfish
public static final String ALGORITHM_3DES = "DESede";
public static final String ALGORITHM_RSA = "RSA";
public static final String SIGNATURE_ALGORITHM_SHA256 = "SHA256withRSA";
public static final String SUMMARY_ALGORITHM_SHA256 = "SHA-256";
// transformation的格式是“算法/工作模式/填充模式”
public static final String TRANSFORMATION = "DESede/ECB/PKCS5Padding"; // 或者 DESede/CBC/PKCS5Padding
// 默认3des加密密码
public static final String DEFAULT_SYMMETRIC_KEY = "4f6b7316a2154a15572394da3dc476644f6b7316a2154a15";
/**
* 根据字符串生成密钥字节数组
*
* @param keyStr 密钥字符串
* @return 密钥
* @throws Exception
*/
public static SecretKey build3DesKey(String keyStr) throws Exception {
byte[] key = new byte[24]; //声明一个24位的字节数组,默认里面都是0
byte[] temp = keyStr.getBytes(CHARSET); //将字符串转成字节数组
// 执行数组拷贝, System.arraycopy(源数组,从源数组哪里开始拷贝,目标数组,拷贝多少位)
if (key.length > temp.length) {
//如果temp不够24位,则拷贝temp数组整个长度的内容到key数组中
System.arraycopy(temp, 0, key, 0, temp.length);
} else {
//如果temp大于24位,则拷贝temp数组24个长度的内容到key数组中
System.arraycopy(temp, 0, key, 0, key.length);
}
// DESedeKeySpec会帮你生成24位秘钥,key可以是任意长度
DESedeKeySpec spec = new DESedeKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM_3DES);
SecretKey secretKey = keyFactory.generateSecret(spec);
return secretKey;
}
/**
* 3DES 加密
*
* @param key 密钥
* @param content 加密内容
* @return 密文
*/
public static String encryptBy3Des(String key, String content) {
if (content == null)
return "";
try {
SecretKeySpec secretKey = new SecretKeySpec(hexToBytes(key), ALGORITHM_3DES);
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] res = cipher.doFinal(content.getBytes(CHARSET));
//encodeBase64会对字符串3位一组自动补全,因而最后可能会出现 == 或者 =
return Base64.encodeBase64String(res);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 3DES 加密
*
* @param content 明文
* @return 密文
*/
public static String encryptBy3Des(String content) {
return encryptBy3Des(DEFAULT_SYMMETRIC_KEY, content);
}
/**
* 3DES 解密
*
* @param key 密钥
* @param content 解密内容
* @return 明文
*/
public static String decodeBy3Des(String key, String content) {
if (StringUtils.isEmpty(content))
return "";
try {
SecretKeySpec secretKey = new SecretKeySpec(hexToBytes(key), ALGORITHM_3DES);
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] res = cipher.doFinal(Base64.decodeBase64(content));
return new String(res, CHARSET);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 3DES 解密
*
* @param content 密文
* @return 明文
*/
public static String decodeBy3Des(String content) {
return decodeBy3Des(DEFAULT_SYMMETRIC_KEY, content);
}
/**
* 生成秘钥对
*
* @return map
*/
public static Map<String, String> genRsaKeyPair() {
Map<String, String> keyPairMap = new HashMap<String, String>();
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM_RSA);
keyPairGenerator.initialize(KEY_SIZE, new SecureRandom());
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
//获取公、私钥值
String publicKeyValue = Base64.encodeBase64String(publicKey.getEncoded());
String privateKeyValue = Base64.encodeBase64String(privateKey.getEncoded());
//存入
keyPairMap.put(PUBLIC_KEY_NAME, publicKeyValue);
keyPairMap.put(PRIVATE_KEY_NAME, privateKeyValue);
} catch (Exception e) {
e.printStackTrace();
}
return keyPairMap;
}
/**
* 读取证书文件
*
* @param keyPath 证书文件路径
* @return
* @throws Exception
*/
public static String readKeyFile(String keyPath) {
FileInputStream fis = null;
BufferedReader br = null;
try {
fis = new FileInputStream(keyPath);
br = new BufferedReader(new InputStreamReader(fis));
String readLine;
StringBuilder sb = new StringBuilder();
while ((readLine = br.readLine()) != null) {
if (readLine.charAt(0) == '-') {
continue;
} else {
sb.append(readLine);
sb.append('\r');
}
}
return sb.toString();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fis != null)
fis.close();
if (br != null)
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 根据 PKCS8证书获取公钥
*
* @param key
* @return
*/
public static PublicKey getPublicKeyFromPKSC8(String key) {
try {
byte[] byteKey = Base64.decodeBase64(key);
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(byteKey);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
return keyFactory.generatePublic(x509EncodedKeySpec);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 根据 PKCS8证书获取私钥
*
* @param key
* @return
*/
public static PrivateKey getPrivateKeyFromPKSC8(String key) {
try {
byte[] byteKey = Base64.decodeBase64(key);
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(byteKey);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
return keyFactory.generatePrivate(pkcs8EncodedKeySpec);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 根据 PKCS1证书获取公钥
*
* @param keyPath 证书路径
* @return
*/
public static PublicKey getPublicKeyFromPKSC1(String keyPath) {
try {
PEMParser pemParser = new PEMParser(new FileReader(keyPath));
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
Object object = pemParser.readObject();
KeyPair kp = converter.getKeyPair((PEMKeyPair) object);
return kp.getPublic();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 根据 PKCS1证书获取私钥
*
* @param keyPath 证书路径
* @return
*/
public static PrivateKey getPrivateKeyFromPKSC1(String keyPath) {
try {
PEMParser pemParser = new PEMParser(new FileReader(keyPath));
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
Object object = pemParser.readObject();
KeyPair kp = converter.getKeyPair((PEMKeyPair) object);
return kp.getPrivate();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* sha-256 摘要
*
* @param data
* @return
*/
public static String sha256(byte[] data) {
try {
MessageDigest md = MessageDigest.getInstance(SUMMARY_ALGORITHM_SHA256);
return bytesToHex(md.digest(data));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* sha-256 摘要
*
* @param data
* @return
*/
public static String sha256(String data) {
return sha256(data.getBytes());
}
/**
* 签名
*
* @param privateKey 私钥
* @param requestData 请求参数
* @return
*/
public static String sign(PrivateKey privateKey, String requestData) {
String signature = null;
try {
Signature Sign = Signature.getInstance(SIGNATURE_ALGORITHM_SHA256);
Sign.initSign(privateKey);
Sign.update(requestData.getBytes(CHARSET));
signature = Base64.encodeBase64String(Sign.sign());
logger.info("===签名结果:" + signature);
} catch (Exception e) {
e.printStackTrace();
}
return signature;
}
/**
* 验签
*
* @param publicKey 公钥
* @param requestData 请求参数
* @param signature 签名
* @return
*/
public static boolean verifySign(PublicKey publicKey, String requestData, String signature) {
boolean verifySignRes = false;
try {
Signature verifySign = Signature.getInstance(SIGNATURE_ALGORITHM_SHA256);
verifySign.initVerify(publicKey);
verifySign.update(requestData.getBytes(CHARSET));
verifySignRes = verifySign.verify(Base64.decodeBase64(signature));
logger.info("===验签结果:" + verifySignRes);
} catch (Exception e) {
e.printStackTrace();
}
return verifySignRes;
}
/**
* 构建签名数据, 将 Map 转成 key1=value1&key2=value2...(按照字段名的ASCII 码从小到大排序,即字典序)
*
* @param params 请求参数
* @return
*/
public static String buildSignData(Map<String, String> params) {
StringBuilder sb = new StringBuilder();
// 将参数以参数名的字典升序排序
Map<String, Object> sortParams = new TreeMap<String, Object>(params);
// 遍历排序的字典,并拼接"key=value"格式
for (Map.Entry<String, Object> entry : sortParams.entrySet()) {
// 过滤空参
if (entry.getValue() == null || entry.getValue() == "")
continue;
sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
if (!sortParams.isEmpty()) {
sb.deleteCharAt(sb.length() - 1);
}
logger.info("===sign data:" + sb.toString());
return sb.toString();
}
/**
* hex转byte数组
*
* @param hex
* @return
*/
public static byte[] hexToBytes(String hex) {
int m, n;
int byteLen = hex.length() / 2; // 每两个字符描述一个字节
byte[] ret = new byte[byteLen];
for (int i = 0; i < byteLen; i++) {
m = i * 2 + 1;
n = m + 1;
int intVal = Integer.decode("0x" + hex.substring(i * 2, m) + hex.substring(m, n));
ret[i] = Byte.valueOf((byte) intVal);
}
return ret;
}
/**
* byte数组转hex
*
* @param bytes
* @return
*/
public static String bytesToHex(byte[] bytes) {
String hexArray = "0123456789abcdef";
StringBuilder sb = new StringBuilder(bytes.length * 2);
for (byte b : bytes) {
int bi = b & 0xff;
sb.append(hexArray.charAt(bi >> 4));
sb.append(hexArray.charAt(bi & 0xf));
}
return sb.toString();
}
/**
* 生成随机字符串
*
* @return
*/
public static String createNonceStr() {
String sl = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 16; i++) {
sb.append(sl.charAt(new Random().nextInt(sl.length())));
}
return sb.toString();
}
}
三、使用示例
public static void main(String[] args) {
String key = "123456";
String msg = "13052515170";
System.out.println("【加密前】:" + msg);
//加密
String cipherText = SecretUtil.encryptBy3Des(DEFAULT_SYMMETRIC_KEY, msg);
System.out.println("【加密后】:" + cipherText);
//解密
String msgText = SecretUtil.decodeBy3Des(DEFAULT_SYMMETRIC_KEY, cipherText);
System.out.println("【解密后】:" + msgText);
//签名 验签
Map<String, String> keyPairMap = genRsaKeyPair();
System.out.println("生成公、私钥测试:"+keyPairMap);
String publicKey = keyPairMap.get(PUBLIC_KEY_NAME);
String privateKey = keyPairMap.get(PRIVATE_KEY_NAME);
System.out.println("===开始RSA公、私钥测试===");
String str = "alpha=001&beta=002&gamma=003";
String sign = sign(getPrivateKeyFromPKSC8(privateKey), str);
verifySign(getPublicKeyFromPKSC8(publicKey), str, sign);
System.out.println(privateKey);
System.out.println(">>>>>"+SecretUtil.encryptBy3Des(key, null));
String a = bytesToHex("123".getBytes());
byte[] bytes = hexToBytes(a);
System.out.println(new String(bytes));
}