import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Joiner;
import com.odianyun.exception.factory.OdyExceptionFactory;
import com.odianyun.finance.model.vo.ums.MerchantFundsShareVO;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import javax.net.ssl.*;
import java.io.*;
import java.net.URL;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;
/**
* @Author liuwei
* @Date: 2022/5/12
* @Describe: 银联商务工具类
*/
public class ChinaUmsUtil {
private static final Logger logger = LoggerFactory.getLogger(ChinaUmsUtil.class);
/**
* 编码格式,值为
*/
public final static String CHARSET_UTF8 = "UTF-8";
/**
* 加密解密算法,值为
*/
public final static String TRANSFORMATION_RSA = "RSA";
/**
* 签名验签算法,值为
*/
public final static String ALGORITHM_SHA256WITHRSA = "SHA256withRSA";
/**
* 证书类型
*/
public static final String CERT_TYPE_PKCS12 = "PKCS12";
/**
* 哈希算法,值为
*/
public final static String ALGORITHM_HASH_SHA256 = "SHA-256";
/**
* 根据公钥base64字符串获取公钥
*
* @param publicKeyStr Base64编码后的公钥字节数组
* @return
* @throws Exception
*/
public static PublicKey getPublicKey(String publicKeyStr) throws Exception {
byte[] publicKeyByte = org.apache.commons.codec.binary.Base64.decodeBase64(publicKeyStr);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyByte);
KeyFactory keyFactory = KeyFactory.getInstance(TRANSFORMATION_RSA);
return keyFactory.generatePublic(keySpec);
}
/**
* 根据私钥Base64字符串获取私钥对象
*
* @param privateKeyStr
* @return
* @throws Exception
*/
public static PrivateKey getPrivateKey(String privateKeyStr) throws Exception {
byte[] privateKeyByte = org.apache.commons.codec.binary.Base64.decodeBase64(privateKeyStr);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyByte);
KeyFactory keyFactory = KeyFactory.getInstance(TRANSFORMATION_RSA);
return keyFactory.generatePrivate(keySpec);
}
/**
* 读取证书为base64
*
* @param path
* @return
*/
public static String getPubKeyBase64Str(String path) {
String key = "";
// 读取证书文件
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
FileInputStream in = new FileInputStream(path);
//生成一个证书对象并使用从输入流 inStream 中读取的数据对它进行初始化。
Certificate c = cf.generateCertificate(in);
PublicKey publicKey = c.getPublicKey();
key = Base64.encode(publicKey.getEncoded());
} catch (CertificateException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return key;
}
/**
* 根据pfx证书得到私钥 base64
*
* @param path
* @param password
* @return
* @throws Exception
*/
public static String getPrivateKeyBase64(String path, String password) throws Exception {
File pfxFile = new File(path);
PrivateKey privateKey = null;
KeyStore keystore = KeyStore.getInstance(CERT_TYPE_PKCS12);
keystore.load(new ByteArrayInputStream(FileUtils.readFileToByteArray(pfxFile)), password.toCharArray());
Enumeration enums = keystore.aliases();
String keyAlias = "";
while (enums.hasMoreElements()) {
keyAlias = (String) enums.nextElement();
if (keystore.isKeyEntry(keyAlias)) {
privateKey = (PrivateKey) keystore.getKey(keyAlias, password.toCharArray());
}
}
byte[] privateKeyByte = privateKey.getEncoded();
return org.apache.commons.codec.binary.Base64.encodeBase64String(privateKeyByte);
}
/**
* 签名
*
* @param requestBody
* @return
*/
public static String toSign(JSONObject requestBody, String privateKeyStr) throws Exception {
Map<String, String> params = new TreeMap<>();
//过滤掉空属性及Map或List等复杂对象
requestBody.entrySet().stream().filter(
p -> p.getKey() != "url"
&& p.getKey() != "privateKey"
&& p.getKey() != "publicKey"
&& p.getValue() != null
&& !(p.getValue() instanceof Map)
&& !(p.getValue() instanceof Iterable))
.forEach(p -> {
if (!p.getValue().equals("")) {
params.put(p.getKey(), p.getValue().toString());
}
});
String signStr = Joiner.on("&").withKeyValueSeparator("=").join(params);
byte[] sign = signRsa(signStr.getBytes(), getPrivateKey(privateKeyStr), ALGORITHM_SHA256WITHRSA);
params.put("signature", byteArr2HexString(sign));
return JSON.toJSONString(params);
}
/**
* 签名
*
* @param rawData 签名裸数据
* @param privateKey 私钥
* @param algorithm 签名验签算法
* @return
*/
public static byte[] signRsa(byte[] rawData, PrivateKey privateKey, String algorithm) {
try {
Signature instance = Signature.getInstance(algorithm);
instance.initSign(privateKey);
instance.update(rawData);
return instance.sign();
} catch (Exception e) {
//签名失败
throw OdyExceptionFactory.businessException(e.getMessage() + "签名失败");
}
}
/**
* 验签
*
* @param rawData 验签裸数据
* @param signature 签名
* @param publicKey 公钥
* @param algorithm 签名验签算法
* @return true-验签通过,false-验签不通过
*/
public static Boolean verify(byte[] rawData, byte[] signature, PublicKey publicKey, String algorithm) {
try {
Signature instance = Signature.getInstance(algorithm);
instance.initVerify(publicKey);
instance.update(rawData);
return instance.verify(signature);
} catch (Exception e) {
throw OdyExceptionFactory.businessException("验签失败");
}
}
/**
* 加密
*
* @param data 明文数据
* @param publicKey 公钥
* @param transformation 加密算法,支持{@link #TRANSFORMATION_RSA RSA}
* @return
*/
public static byte[] encrpty(byte[] data, PublicKey publicKey, String transformation) {
try {
Cipher cipher = Cipher.getInstance(transformation);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data);
} catch (Exception e) {
throw OdyExceptionFactory.businessException("加密失败");
}
}
/**
* 解密
*
* @param data 密文数据
* @param privateKey 私钥
* @param transformation 加密算法,支持{@link #TRANSFORMATION_RSA RSA}
* @return
*/
public static byte[] decrpty(byte[] data, PrivateKey privateKey, String transformation) {
try {
Cipher cipher = Cipher.getInstance(transformation);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
} catch (Exception e) {
throw OdyExceptionFactory.businessException("解密失败");
}
}
/**
* 发送https请求条件 重写取消证书验证
*/
private static class TrustAnyTrustManager implements X509TrustManager {
//信任管理器
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
//信任证书。
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
//返回受信任的X509证书数组。
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
}
/**
* 接受任何域名
*/
private static class TrustAnyHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
/**
* 方式请求服务器(https协议) 重写取消证书验证
*
* @param url
* @param content
* @return
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
* @throws IOException
*/
public static String remoteRequest(String url, String content) throws NoSuchAlgorithmException, KeyManagementException, IOException {
//指定信任管理器对象
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new SecureRandom());
URL console = new URL(url);
HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
conn.setSSLSocketFactory(sc.getSocketFactory());
conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
conn.setDoOutput(true);
//设置请求头
conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
conn.setConnectTimeout(60000);
conn.connect();
DataOutputStream out = new DataOutputStream(conn.getOutputStream());
out.write(content.getBytes(CHARSET_UTF8));
// 刷新、关闭
out.flush();
out.close();
InputStream is = conn.getInputStream();
if (is != null) {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = is.read(buffer)) != -1) {
outStream.write(buffer, 0, len);
}
is.close();
return outStream.toString();
}
return null;
}
/**
* 将流转换为字符串
*
* @param inputStream
* @return
*/
private static String streamTostring(InputStream inputStream) {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String str;
StringBuilder stringBuilder = new StringBuilder();
try {
while ((str = bufferedReader.readLine()) != null) {
stringBuilder.append(str);
}
} catch (IOException e) {
e.printStackTrace();
}
return stringBuilder.toString();
}
/**
* 字节数组转换为十六进制字符串
*
* @param bytearr 字节数组
* @return 十六进制字符串
*/
public static String byteArr2HexString(byte[] bytearr) {
if (bytearr == null) {
return "null";
}
StringBuffer sb = new StringBuffer();
for (int k = 0; k < bytearr.length; k++) {
if ((bytearr[k] & 0xFF) < 16) {
sb.append("0");
}
sb.append(Integer.toString(bytearr[k] & 0xFF, 16));
}
return sb.toString();
}
/**
* 十六进制字符串转换为字节数组
*
* @param hexstring 十六进制字符串
* @return 字节数组
*/
public static byte[] hexString2ByteArr(String hexstring) {
if ((hexstring == null) || (hexstring.length() % 2 != 0)) {
return new byte[0];
}
byte[] dest = new byte[hexstring.length() / 2];
for (int i = 0; i < dest.length; i++) {
String val = hexstring.substring(2 * i, 2 * i + 2);
dest[i] = (byte) Integer.parseInt(val, 16);
}
return dest;
}
/**
* 哈希
*
* @param data 明文数据
* @param algorithm 哈希算法,
* @return 密文数据
*/
public static byte[] hash(byte[] data, String algorithm) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
throw OdyExceptionFactory.businessException("不支持" + algorithm + "算法");
}
md.update(data);
return md.digest();
}
/**
* 哈希,字符串对字符串
*
* @param data 明文数据,字符串
* @param charset 编码格式,支持{@link # UTF-8}, {@link # GBK}和
* {@link # GB2312};也可自定义
* @param algorithm 哈希算法,支持{@link # MD5},
* {@link # SHA-256}和
* {@link # SHA-1};也可自定义
* @return 如果输入为空,则直接返回;不为空,返回密文数据,十六进制字符串
*/
public static String hashHex(String data, String charset, String algorithm) {
if (StringUtils.isEmpty(data)) {
return data;
}
try {
return byteArr2HexString(hash(data.getBytes(charset), algorithm));
} catch (UnsupportedEncodingException e) {
throw OdyExceptionFactory.businessException("不支持" + charset + "编码格式");
}
}
/**
* 哈希,字符串对字符串
*
* @param data 明文数据,字符串,UTF-8 编码
* @param algorithm 哈希算法,
* @return 如果输入为空,则直接返回;不为空,返回密文数据,十六进制字符串
*/
public static String hashHex(String data, String algorithm) {
return hashHex(data, CHARSET_UTF8, algorithm);
}
/**
* 获取签名裸数据
*
* @param requestBody
*/
public static String getReturnRawData(JSONObject requestBody) {
Map<String, String> params = new TreeMap<>();
//过滤掉空属性及Map或List等复杂对象
requestBody.entrySet().stream().filter(
p -> p.getKey() != "signature"
&& p.getValue() != null
&& !(p.getValue() instanceof Map)
&& !(p.getValue() instanceof Iterable))
.forEach(p -> {
if (!p.getValue().equals("")) {
params.put(p.getKey(), p.getValue().toString());
}
});
return Joiner.on("&").withKeyValueSeparator("=").join(params);
}
/**
* 验证
*
* @param merchantFundsShareVO
* @param publicKeyStr
* @return
*/
public static boolean validate(MerchantFundsShareVO merchantFundsShareVO, String publicKeyStr) {
logger.info("=======银联商务开始验签===========");
try {
String signature = merchantFundsShareVO.getSignature();
String rawDataStr = getReturnRawData(JSONObject.parseObject(JSON.toJSONString(merchantFundsShareVO)));
Boolean flag = false;
try {
flag = verify(rawDataStr.getBytes(), hexString2ByteArr(signature), getPublicKey(publicKeyStr), ALGORITHM_SHA256WITHRSA);
} catch (Exception e) {
flag = verify(hash(rawDataStr.getBytes(), ALGORITHM_HASH_SHA256), hexString2ByteArr(signature), getPublicKey(publicKeyStr), TRANSFORMATION_RSA);
}
logger.info("验签结果:{}", flag);
return flag;
} catch (Exception e) {
logger.info("【返回验签异常】" + e.getMessage());
return false;
}
}
}
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Enumeration;
/**
* Created by ssl on 2017/9/5.
*/
public class PFXUtil {
/**
* 读取证书为base64
*
* @param path
* @return
*/
public static String getPubKeyBase64Str(String path) {
String key = "";
// 读取证书文件
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
FileInputStream in = new FileInputStream(path);
//生成一个证书对象并使用从输入流 inStream 中读取的数据对它进行初始化。
Certificate c = cf.generateCertificate(in);
PublicKey publicKey = c.getPublicKey();
key = Base64.encode(publicKey.getEncoded());
} catch (CertificateException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return key;
}
/**
* 获取RSA算法的keyFactory
*
* @return
*/
private static KeyFactory getKeyFactory() throws Exception {
return getKeyFactory("RSA");
}
/**
* 获取指定算法的keyFactory
*
* @param algorithm
* @return
*/
private static KeyFactory getKeyFactory(String algorithm) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
return keyFactory;
}
/**
* 根据pfx证书获取keyStore
*
* @param pfxData
* @param password
* @return
* @throws Exception
*/
private static KeyStore getKeyStore(byte[] pfxData, String password) throws Exception {
KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore.load(new ByteArrayInputStream(pfxData), password.toCharArray());
return keystore;
}
/**
* 根据pfx证书得到私钥
*
* @param pfxData
* @param password
* @throws Exception
*/
public static PrivateKey getPrivateKeyByPfx(byte[] pfxData, String password) throws Exception {
PrivateKey privateKey = null;
KeyStore keystore = getKeyStore(pfxData, password);
Enumeration enums = keystore.aliases();
String keyAlias = "";
while (enums.hasMoreElements()) {
keyAlias = (String) enums.nextElement();
if (keystore.isKeyEntry(keyAlias)) {
privateKey = (PrivateKey) keystore.getKey(keyAlias, password.toCharArray());
}
}
return privateKey;
}
/**
* 根据pfx证书得到私钥
*
* @param pfxPath
* @param password
* @return
* @throws Exception
*/
public static PrivateKey getPrivateKeyByPfx(String pfxPath, String password) throws Exception {
File pfxFile = new File(pfxPath);
return getPrivateKeyByPfx(FileUtils.readFileToByteArray(pfxFile), password);
}
/**
* 根据私钥字节数组获取私钥对象
*
* @param privateKeyByte
* @return
* @throws Exception
*/
public static PrivateKey getPrivateKey(byte[] privateKeyByte) throws Exception {
PrivateKey privateKey = null;
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyByte);
KeyFactory keyFactory = getKeyFactory();
privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
/**
* 根据私钥Base64字符串获取私钥对象
*
* @param privateKeyStr
* @return
* @throws Exception
*/
public static PrivateKey getPrivateKey(String privateKeyStr) throws Exception {
byte[] privateKeyByte = Base64.decodeBase64(privateKeyStr);
return getPrivateKey(privateKeyByte);
}
/**
* 根据公钥字节数组获取公钥
*
* @param publicKeyByte 公钥字节数组
* @return
* @throws Exception
*/
public static PublicKey getPublicKey(byte[] publicKeyByte) throws Exception {
PublicKey publicKey = null;
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyByte);
KeyFactory keyFactory = getKeyFactory();
publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}
/**
* 根据公钥base64字符串获取公钥
*
* @param publicKeyStr Base64编码后的公钥字节数组
* @return
* @throws Exception
*/
public static PublicKey getPublicKey(String publicKeyStr) throws Exception {
byte[] publicKeyByte = Base64.decodeBase64(publicKeyStr);
return getPublicKey(publicKeyByte);
}
/**
* 根据pfx证书获取证书对象
*
* @param pfxData pfx的字节数组
* @param password pfx证书密码
* @return
* @throws Exception
*/
public static X509Certificate getX509Certificate(byte[] pfxData, String password) throws Exception {
X509Certificate x509Certificate = null;
KeyStore keystore = getKeyStore(pfxData, password);
Enumeration enums = keystore.aliases();
String keyAlias = "";
while (enums.hasMoreElements()) {
keyAlias = (String) enums.nextElement();
if (keystore.isKeyEntry(keyAlias)) {
x509Certificate = (X509Certificate) keystore.getCertificate(keyAlias);
}
}
return x509Certificate;
}
/**
* 根据pfx证书获取证书对象
*
* @param pfxPath pfx证书路径
* @param password pfx证书密码
* @return
* @throws Exception
*/
public static X509Certificate getX509Certificate(String pfxPath, String password) throws Exception {
File pfxFile = new File(pfxPath);
return getX509Certificate(FileUtils.readFileToByteArray(pfxFile), password);
}
//生成pkcs12
/**
* 根据私钥、公钥证书、密码生成pkcs12
*
* @param privateKey 私钥
* @param x509Certificate 公钥证书
* @param password 需要设置的密钥
* @return
* @throws Exception
*/
public static byte[] generatorPkcx12(PrivateKey privateKey, X509Certificate x509Certificate, String password)
throws Exception {
Certificate[] chain = {x509Certificate};
KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore.load(null, password.toCharArray());
keystore.setKeyEntry(x509Certificate.getSerialNumber().toString(), privateKey, password.toCharArray(), chain);
ByteArrayOutputStream bytesos = new ByteArrayOutputStream();
keystore.store(bytesos, password.toCharArray());
byte[] bytes = bytesos.toByteArray();
return bytes;
}
//合成pfx
/**
* 根据私钥、公钥证书、密钥,保存为pfx文件
*
* @param privateKey 私钥
* @param x509Certificate 公钥证书
* @param password 打开pfx的密钥
* @param saveFile 保存的文件
* @return
* @throws Exception
*/
public static String generatorPFX(PrivateKey privateKey, X509Certificate x509Certificate, String password, File
saveFile) throws Exception {
//判断文件是否存在
if (!saveFile.exists()) {
//判断文件的目录是否存在
if (!saveFile.getParentFile().exists()) {
saveFile.getParentFile().mkdirs();
}
saveFile.createNewFile();
}
byte[] pkcs12Byte = generatorPkcx12(privateKey, x509Certificate, password);
FileUtils.writeByteArrayToFile(saveFile, pkcs12Byte);
return saveFile.getPath();
}
public static void main(String[] args) throws Exception {
String pfxPath = "D:\\Java\\ideaIUProject\\ls_ody_pre\\back-finance-web\\src\\main\\resources\\rsa_private_dev.pfx";
String password = "123456";
//私钥:pfx文件中获取私钥对象
PrivateKey privateKey = getPrivateKeyByPfx(pfxPath, password);
byte[] privateKeyByte = privateKey.getEncoded();
String privateKeyStr = Base64.encodeBase64String(privateKeyByte);
System.out.println("私钥Base64字符串:" + privateKeyStr);
//=====私钥Base64字符串转私钥对象
PrivateKey privateKey2 = getPrivateKey(privateKeyStr);
System.out.println("私钥Base64字符串2:" + Base64.encodeBase64String(privateKey2.getEncoded()));
//证书:从pfx文件中获取证书对象
X509Certificate certificate = getX509Certificate(pfxPath, password);
System.out.println("证书主题:" + certificate.getSubjectDN().getName());
String publicKeyStr = Base64.encodeBase64String(certificate.getPublicKey().getEncoded());
System.out.println("公钥Base64字符串:" + publicKeyStr);
//=====根据公钥Base64字符串获取公钥对象
System.out.println("公钥Base64字符串2:" + Base64.encodeBase64String(getPublicKey(publicKeyStr).getEncoded()));
//PFX:合成pfx(需要私钥、公钥证书)
String savePath = generatorPFX(privateKey, certificate, "1", new File
("C:\\Users\\49383\\Desktop\\文件\\009\\009.pfx"));
System.out.println(savePath);
}
}
import cn.com.nantian.dto.SuperDto;
import cn.com.nantian.exceptions.SecureUtilException;
import net.sf.cglib.beans.BeanMap;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import javax.net.ssl.*;
import javax.security.cert.X509Certificate;
import java.io.*;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.*;
import static org.apache.commons.codec.binary.Base64.decodeBase64;
/**
* Util汇总整合工具类,主要对请求和回复的报文进行组装解析,签名,验签,加密,解密等操作
*
* @author Roi
*/
public class SuperUtil {
private static final Logger logger = LoggerFactory.getLogger(SuperUtil.class);
public static final String SYS_VAR_RAW_DATA = "rawData";
static PrivateKey privateKey;
static PublicKey pubKey;
static String channelId;
static String preURL;
static String verNo;
static String groupId;
/**
* 初始化参数
*/
static {
try{
InputStream is = SuperUtil.class.getResourceAsStream("/config/ConstantsDefine.local.properties");
Properties pps = new Properties();
pps.load(is);
String privateKeyPath = pps.getProperty("FAN_RPIVATE_KEY_PATH");
String privateKeyPwd = pps.getProperty("FAN_RPIVATE_KEY_PWD");
String publicKeyPath = pps.getProperty("FAN_RPUBLIC_KEY_PATH");
InputStream priKeyStoreFileStream = SuperUtil.class.getResourceAsStream(privateKeyPath);
privateKey = getPriKeyPkcs12(priKeyStoreFileStream, privateKeyPwd);
InputStream pubKeyStoreFileStream = SuperUtil.class.getResourceAsStream(publicKeyPath);
X509Certificate cert = X509Certificate.getInstance(pubKeyStoreFileStream);
pubKey = cert.getPublicKey();
channelId = pps.getProperty("CHANNEL_ID");
preURL = pps.getProperty("URL_PRE");
verNo = pps.getProperty("VER_NO");
//TODO 请修改ConstantsDefine.local.properties配置文件中集团号
groupId = pps.getProperty("GROUP_ID");
}catch(Exception e){
throw new RuntimeException("配置文件读取失败!");
}
}
/**
* 获取Json格式报文加签;发送;并对返回值进行处理后验签
*
* @param superDto
* @return
*/
public static void oneStep(SuperDto superDto) {
Map<String, String> srcMap = sign(superDto);
String result = JSONArray.fromObject(srcMap).toString();
System.out.println(result);
try {
String resposeStr = post(preURL + superDto.getTransCode(), result.substring(1, result.length() - 1), "UTF-8");
System.out.println(resposeStr);
if(null == resposeStr){
logger.info("数据返回超时");
}
SuperDto returnDto = new SuperDto();
returnDto = jsonStrToDto(resposeStr, returnDto.getClass());
Boolean flag = validate(returnDto);
if (flag) {
logger.info("返回报文验签成功");
} else {
logger.info("返回报文验签失败");
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 对参数进行判断
* null,""," " == {true}
*
* @param str
* @return
*/
public static Boolean isEmpty(String str){
if (StringUtils.isEmpty(str) || "".equals(str.replace(" ",""))){
return true;
}
return false;
}
/**
* 获取map类型报文
*
* @param superDto
* @return
*/
public static Map getSrcMap(SuperDto superDto) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String dateTime = sdf.format(Calendar.getInstance().getTime());
Map<String, String> srcMap = new HashMap<String, String>();
/*----------------------报文头start------------------------*/
if (isEmpty(superDto.getTransCode())){
logger.error("未定义交易码");
}
srcMap.put("transCode", superDto.getTransCode());
srcMap.put("verNo", verNo);
srcMap.put("channelId", channelId);
srcMap.put("groupId", groupId);
//请求系统日期
srcMap.put("srcReqDate", dateTime.substring(0, 8));
//请求系统时间
srcMap.put("srcReqTime", dateTime.substring(8));
//请求系统流水号,须唯一,该处取时间戳以表示不重复序列,生产环境不建议使用
srcMap.put("srcReqId", String.valueOf(System.currentTimeMillis()));
/*----------------------报文头end--------------------------*/
/*----------------------报文体start------------------------*/
if(isEmpty(superDto.getMerNo())){
logger.error("未定义企业用户号");
}
srcMap.put("merNo", superDto.getMerNo());
try {
switch (Integer.parseInt(superDto.getTransCode())){
case 202001:
if(isEmpty(superDto.getMerOrderNo()) || isEmpty(superDto.getPayAmt())){
logger.error("未定义商户订单号或者划付金额");
break;
}
srcMap.put("merOrderNo", superDto.getMerOrderNo());
srcMap.put("payAmt", superDto.getPayAmt());
srcMap.put("ps", superDto.getPs());
break;
case 202002:
if (isEmpty(superDto.getPayAmt())){
logger.error("未定义划付金额");
break;
}
srcMap.put("payAmt", superDto.getPayAmt());
srcMap.put("ps", superDto.getPs());
break;
case 202003:
if(isEmpty(superDto.getMerOrderNo()) || isEmpty(superDto.getPayAmt()) || isEmpty(superDto.getCardNo()) ||
isEmpty(superDto.getPs())){
logger.error("未定义商户订单号或者划付金额或者卡号或者附言");
break;
}
srcMap.put("merOrderNo", superDto.getMerOrderNo());
srcMap.put("payAmt", superDto.getPayAmt());
// srcMap.put("cardNo", superDto.getCardNo());
srcMap.put("cardNo",hashHex(superDto.getCardNo(), "SHA-256"));
srcMap.put("ps", superDto.getPs());
break;
case 202004:
if(isEmpty(superDto.getPayAmt()) || isEmpty(superDto.getPayType()) || isEmpty(superDto.getCardNo()) ||
isEmpty(superDto.getPs())){
logger.error("未定义划付金额或者分账类型或者卡号或者附言");
break;
}
srcMap.put("payAmt", superDto.getPayAmt());
srcMap.put("cardNo", hashHex(superDto.getCardNo(), "SHA-256"));
srcMap.put("payType", superDto.getPayType());
srcMap.put("ps", superDto.getPs());
break;
case 202006:
break;
case 202007:
if(isEmpty(superDto.getTransDate()) || isEmpty(superDto.getQueryItem()) || isEmpty(superDto.getQueryValue())){
logger.error("未定义交易日期或者查询项或者查询值");
break;
}
srcMap.put("transDate", superDto.getTransDate());
srcMap.put("queryItem", superDto.getQueryItem());
srcMap.put("queryValue", superDto.getQueryValue());
break;
case 202008:
if(isEmpty(superDto.getReqDate()) || isEmpty(superDto.getReqJournalNo())){
logger.error("未定义请求日期或者请求交易流水号");
break;
}
srcMap.put("reqDate", superDto.getReqDate());
srcMap.put("reqJournalNo", superDto.getReqJournalNo());
break;
case 202009://单笔实时代付
String result = singleChargePay(superDto);
if(StringUtils.isNotEmpty(result)){
logger.error(result);
break;
}
srcMap.put("merNo", superDto.getMerNo());
srcMap.put("acctType", superDto.getAcctType());
srcMap.put("payAmt", superDto.getPayAmt());
srcMap.put("acctName", superDto.getAcctName());
srcMap.put("acctNo", superDto.getAcctNo());
srcMap.put("bankNo", superDto.getBankNo());
srcMap.put("bankName", superDto.getBankName());
srcMap.put("matchMode", superDto.getMatchMode());
srcMap.put("ps", superDto.getPs());
srcMap.put("resume", superDto.getResume());
srcMap.put("payerName", superDto.getPayerName());
srcMap.put("payerAcctNo", superDto.getPayerAcctNo());
srcMap.put("reserve1", superDto.getReserve1());
srcMap.put("reserve2", superDto.getReserve2());
break;
case 202011://商户余额查询
if(isEmpty(superDto.getAcctType())){
logger.error("未定义账户类型");
break;
}
srcMap.put("merNo", superDto.getMerNo());
srcMap.put("acctType", superDto.getAcctType());
break;
case 202012://订单批量查询
if(StringUtils.isEmpty(superDto.getOrderType())){
logger.error("订单类型不能为空");
break;
}
if(StringUtils.isEmpty(superDto.getTransDate())){
logger.error("交易日期不能为空");
break;
}
if(StringUtils.isEmpty(superDto.getPageIdx())){
superDto.setPageIdx("1");
}
srcMap.put("merNo", superDto.getMerNo());
srcMap.put("orderType", superDto.getOrderType());
srcMap.put("transDate", superDto.getTransDate());
srcMap.put("beginAmt", superDto.getBeginAmt());
srcMap.put("endAmt", superDto.getEndAmt());
srcMap.put("payerAcctNo", superDto.getPayerAcctNo());
srcMap.put("payerName", superDto.getPayerName());
srcMap.put("pageIdx", superDto.getPageIdx());
break;
case 202010://单笔订单批量
if(StringUtils.isEmpty(superDto.getOrderType())){
logger.error("订单类型不能为空");
break;
}
if(StringUtils.isEmpty(superDto.getTransDate())){
logger.error("交易日期不能为空");
break;
}
if(StringUtils.isEmpty(superDto.getReqJournalNo())){
logger.error("请求流水号不能为空");
break;
}
srcMap.put("merNo", superDto.getMerNo());
srcMap.put("orderType", superDto.getOrderType());
srcMap.put("transDate", superDto.getTransDate());
srcMap.put("reqJournalNo", superDto.getReqJournalNo());
break;
case 202013:
srcMap.put("merNo", superDto.getMerNo());
srcMap.put("acctType", superDto.getAcctType());
srcMap.put("payAmt", superDto.getPayAmt());
srcMap.put("acctName", superDto.getAcctName());
srcMap.put("acctNo", superDto.getAcctNo());
srcMap.put("transDate", superDto.getTransDate());
srcMap.put("reserve1", superDto.getReserve1());
srcMap.put("reserve2", superDto.getReserve2());
break;
default:
break;
}
} catch (Exception e) {
throw new RuntimeException("报文出错了!");
}
/*----------------------报文体end-------------------------*/
return srcMap;
}
public static String singleChargePay(SuperDto superDto){
if(isEmpty(superDto.getMerNo())){
return "企业用户号不能为空";
}
if(isEmpty(superDto.getAcctType())){
return "账户类型不能为空";
}
if(isEmpty(superDto.getPayAmt())){
return "代付金额不能为空";
}
if(isEmpty(superDto.getAcctName())){
return "收款账户名称不能为空";
}
if(isEmpty(superDto.getAcctNo())){
return "收款账户号不能为空";
}
if(isEmpty(superDto.getMatchMode())){
return "行名行号匹配模式不能为空";
}
if(isEmpty(superDto.getPs())){
return "附言不能为空";
}
//行名行号匹配模式为模糊匹配时,必填准确行号
if("2".equals(superDto.getMatchMode())){
if(isEmpty(superDto.getBankName())){
return "行名行号匹配模式为模糊匹配,开户行行名不能为空";
}
}
if("0".equals(superDto.getMatchMode())){
if(isEmpty(superDto.getBankNo())){
return "行名行号匹配模式为精准匹配,开户行行号不能为空";
}
}
return "";
}
/**
* json字符串转为Object对象
*
* @param jsonStr
* @param dtoClass
* @param <T>
* @return
*/
public static <T> T jsonStrToDto(String jsonStr, Class<T> dtoClass) {
try {
Object dto;
JSONObject jsonDto = JSONObject.fromObject(jsonStr);
dto = JSONObject.toBean(jsonDto, dtoClass);
return (T) dto;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 获取报文签名裸数据
*
* @param superDto
*/
public static Map getRawData(SuperDto superDto) {
Map<String, String> srcMap = getSrcMap(superDto);
List<String> sortKeys = new ArrayList<String>(srcMap.keySet());
Collections.sort(sortKeys);
StringBuffer sb = new StringBuffer();
for (String key : sortKeys) {
sb.append(key);
sb.append("=");
sb.append(srcMap.get(key));
sb.append("&");
}
String rawData = sb.toString();
System.out.println(rawData.substring(0, rawData.length() - 1));
srcMap.put(SYS_VAR_RAW_DATA, rawData.substring(0, rawData.length() - 1));
return srcMap;
}
/**
* 签名
*
* @param superDto
*/
public static Map sign(SuperDto superDto) {
Map<String, String> srcMap = getRawData(superDto);
String rawData = srcMap.get(SYS_VAR_RAW_DATA);
srcMap.remove(SYS_VAR_RAW_DATA);
try {
byte[] signB = signRsa(rawData.getBytes(), privateKey, ALGORITHM_SHA256WITHRSA);
srcMap.put("signature", byteArr2HexString(signB));
System.out.println(byteArr2HexString(signB));
return srcMap;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 加密解密算法,值为{@value}
*/
public final static String TRANSFORMATION_RSA = "RSA";
/**
* 签名验签算法,值为{@value}
*/
public final static String ALGORITHM_MD5WITHRSA = "MD5withRSA";
/**
* 签名验签算法,值为{@value}
*/
public final static String ALGORITHM_SHA256WITHRSA = "SHA256withRSA";
/**
* 签名验签算法,值为{@value}
*/
public final static String ALGORITHM_SHA1WITHRSA = "SHA1withRSA";
/**
* 签名
*
* @param rawData 签名裸数据
* @param privateKey 私钥
* @param algorithm 签名验签算法
* @return
* @throws SecureUtilException
*/
public static byte[] signRsa(byte[] rawData, PrivateKey privateKey, String algorithm) throws SecureUtilException {
try {
Signature instance = Signature.getInstance(algorithm);
instance.initSign(privateKey);
instance.update(rawData);
return instance.sign();
} catch (Exception e) {
SecureUtilException sue = new SecureUtilException("签名失败");
sue.initCause(e);
throw sue;
}
}
/**
* 验签
*
* @param rawData 验签裸数据
* @param signature 签名
* @param publicKey 公钥
* @param algorithm 签名验签算法, 支持{@link #ALGORITHM_MD5WITHRSA MD5withRSA} /
* {@link #ALGORITHM_SHA256WITHRSA SHA256withRSA} /
* {@link #ALGORITHM_SHA1WITHRSA SHA1withRSA}
* @return true-验签通过,false-验签不通过
* @throws SecureUtilException
*/
public static Boolean verify(byte[] rawData, byte[] signature, PublicKey publicKey, String algorithm)
throws SecureUtilException {
try {
Signature instance = Signature.getInstance(algorithm);
instance.initVerify(publicKey);
instance.update(rawData);
return instance.verify(signature);
} catch (Exception e) {
SecureUtilException sue = new SecureUtilException("验签失败");
sue.initCause(e);
throw sue;
}
}
/**
* 加密
*
* @param data 明文数据
* @param publicKey 公钥
* @param transformation 加密算法,支持{@link #TRANSFORMATION_RSA RSA}
* @return
* @throws SecureUtilException
*/
public static byte[] encrpty(byte[] data, PublicKey publicKey, String transformation) throws SecureUtilException {
try {
Cipher cipher = Cipher.getInstance(transformation);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data);
} catch (Exception e) {
SecureUtilException sue = new SecureUtilException("加密失败");
sue.initCause(e);
throw sue;
}
}
/**
* 解密
*
* @param data 密文数据
* @param privateKey 私钥
* @param transformation 加密算法,支持{@link #TRANSFORMATION_RSA RSA}
* @return
* @throws SecureUtilException
*/
public static byte[] decrpty(byte[] data, PrivateKey privateKey, String transformation) throws SecureUtilException {
try {
Cipher cipher = Cipher.getInstance(transformation);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
} catch (Exception e) {
SecureUtilException sue = new SecureUtilException("解密失败");
sue.initCause(e);
throw sue;
}
}
/**
* 发送https请求条件
*/
private static class TrustAnyTrustManager implements X509TrustManager {
//信任管理器
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
//信任证书。
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
//返回受信任的X509证书数组。
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
}
private static class TrustAnyHostnameVerifier implements HostnameVerifier {
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
/**
*
* post方式请求服务器(https协议)
*
* @param url
* 请求地址
* @param content
* 参数
* @param charset
* 编码
* @return
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
* @throws IOException
*
*/
public static String post(String url, String content, String charset) throws NoSuchAlgorithmException, KeyManagementException, IOException {
//指定信任管理器对象。
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom());
URL console = new URL(url);
HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
// HttpURLConnection conn = (HttpURLConnection) console.openConnection();
conn.setSSLSocketFactory(sc.getSocketFactory());
conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
conn.setDoOutput(true);
//设置请求头
conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
conn.setConnectTimeout(60000);
conn.connect();
DataOutputStream out = new DataOutputStream(conn.getOutputStream());
out.write(content.getBytes(charset));
// 刷新、关闭
out.flush();
out.close();
InputStream is = conn.getInputStream();
if (is != null) {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = is.read(buffer)) != -1) {
outStream.write(buffer, 0, len);
}
is.close();
return outStream.toString();
}
return null;
}
/**
* 将流转换为字符串
*
* @param inputStream
* @return
*/
private static String streamTostring(InputStream inputStream) {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String str;
StringBuilder stringBuilder = new StringBuilder();
try {
while ((str = bufferedReader.readLine()) != null) {
stringBuilder.append(str);
}
} catch (IOException e) {
e.printStackTrace();
}
return stringBuilder.toString();
}
/**
* 证书类型,值为{@value}
*/
public static final String CERT_TYPE_JKS = "JKS";
/**
* 证书类型,值为{@value}
*/
public static final String CERT_TYPE_PKCS12 = "PKCS12";
/**
* 证书类型,值为{@value}
*/
public static final String CERT_TYPE_PKCS8 = "PKCS8";
private static KeyStore keyStore = null;//签名证书
/**
* 将证书文件读取为证书存储对象:证书文件类型可为:JKS(.keystore等),PKCS12(.pfx)
*
* @param keyFileIn 证书文件文件流
* @param keypwd 证书密码
* @param type 证书类型
* @return 证书对象
*/
public static KeyStore getKeyStore(InputStream keyFileIn, String keypwd, String type) {
try {
if (CERT_TYPE_JKS.equals(type)) {
keyStore = KeyStore.getInstance(type);
} else if (CERT_TYPE_PKCS12.equals(type)) {
/**
* 动态注册SUN JCE<br/>
* JCE(Java Cryptography Extension)是一组包,它们提供用于加密、密钥生成和协商以及 Message
* Authentication Code(MAC)算法的框架和实现。<br/>
* 设置安全提供者为BouncyCastleProvider
*/
if (Security.getProvider("BC") == null) {
// 将提供程序添加到下一个可用位置。
Security.addProvider(new BouncyCastleProvider());
} else {
Security.removeProvider("BC");
Security.addProvider(new BouncyCastleProvider());
}
keyStore = KeyStore.getInstance(type);
}
char[] nPassword = null;
nPassword = null == keypwd || "".equals(keypwd.trim()) ? null : keypwd.toCharArray();
keyStore.load(keyFileIn, nPassword);
if (keyFileIn != null)
keyFileIn.close();
return keyStore;
} catch (Exception e) {
if (Security.getProvider("BC") == null) {
logger.info("BC Provider not installed.");
}
logger.error("Fail: load privateKey certificate", e);
} finally {
if (keyFileIn != null)
try {
keyFileIn.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 从私钥证书中获取私钥
*
* @param keyFileIn 证书文件流.pfx, .keystore)
* @param keypwd 证书密码
* @param type 证书类型
* @return:私钥
*/
public static PrivateKey getPriKey(InputStream keyFileIn, String keypwd, String type) {
PrivateKey privateKey = null;
getKeyStore(keyFileIn, keypwd, type);
try {
Enumeration<String> aliasenum = keyStore.aliases();
String keyAlias = null;
if (aliasenum.hasMoreElements()) {
// 第一个条目
keyAlias = (String) aliasenum.nextElement();
}
privateKey = (PrivateKey) keyStore.getKey(keyAlias, keypwd.toCharArray());
} catch (Exception e) {
logger.error("Fail: get private key from private certificate", e);
}
return privateKey;
}
/**
* 从私钥证书中获取PKCS12标准私钥<br/>
*
* @param keyFileIn 私钥文件流 .pfx
* @param keypwd 证书密码
* @return:私钥
*/
public static PrivateKey getPriKeyPkcs12(InputStream keyFileIn, String keypwd) {
return getPriKey(keyFileIn, keypwd, CERT_TYPE_PKCS12);
}
/**
* 从私钥证书中获取JKS标准私钥<br/>
*
* @param keyFileIn 私钥文件流 .keystore .jks
* @param keypwd 密码
* @return
*/
public static PrivateKey getPriKeyJks(InputStream keyFileIn, String keypwd, String type) {
return getPriKey(keyFileIn, keypwd, CERT_TYPE_JKS);
}
/**
* 从私钥证书中获取PKCS8标准私钥<br/>
*
* @param keyFileIn 私钥文件流
* @return 私钥
*/
public static PrivateKey getPriKeyPkcs8(InputStream keyFileIn) {
PrivateKey privateKey = null;
try {
byte[] buffer = readFile(keyFileIn);
buffer = decodeBase64(buffer);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
privateKey = keyFactory.generatePrivate(keySpec);
} catch (Exception e) {
logger.error("Fail: get private key from private certificate", e);
} finally {
if (keyFileIn != null)
try {
keyFileIn.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return privateKey;
}
/**
* 从公钥证书中获取公钥<br/>
*
* @param keyFileIn 文件流 .cer
* @return
*/
public static PublicKey getPubKey(InputStream keyFileIn) {
java.security.cert.X509Certificate publicCert = getPubCert(keyFileIn, null);
PublicKey publicKey = publicCert.getPublicKey();
return publicKey;
}
/**
* 读取文件的方法<br/>
*
* @param keyFileIn 文件流
* @return
* @throws Exception
*/
private static byte[] readFile(InputStream keyFileIn) throws Exception {
BufferedReader br;
InputStreamReader isr = new InputStreamReader(keyFileIn);
br = new BufferedReader(isr);
String readLine;
StringBuilder sb = new StringBuilder();
while ((readLine = br.readLine()) != null) {
if (readLine.startsWith("--")) {
continue;
}
sb.append(readLine);
}
br.close();
isr.close();
keyFileIn.close();
return sb.toString().getBytes();
}
/**
* 读取公钥证书<br/>
*
* @param keyFileIn 文件路径 .cer
* @return 证书对象
*/
public static java.security.cert.X509Certificate getPubCert(InputStream keyFileIn, String provider) {
CertificateFactory cf = null;
InputStream in = null;
java.security.cert.X509Certificate x509Certificate = null;
try {
if ("BC".equals(provider)) {
cf = CertificateFactory.getInstance("X.509", "BC");
} else {
cf = CertificateFactory.getInstance("X.509");
}
in = keyFileIn;
x509Certificate = (java.security.cert.X509Certificate) cf.generateCertificate(in);
if (in != null)
in.close();
} catch (Exception e) {
logger.error("Fail: load public certificate", e);
return null;
} finally {
if (null != in) {
try {
in.close();
} catch (IOException e) {
logger.error("Fail: close FileInputStream", e);
}
}
}
return x509Certificate;
}
/**
* RSA密钥生成
*
* <pre>
* 由{@link java.security}生成的RSA公钥格式为X509,私钥格式为PKCS#8
* </pre>
*
* @author 丁盛
*
*/
/**
* 密钥长度, 值为{@value}
*/
public static final int KEY_SIZE_1024 = 1024;
/**
* 密钥长度, 值为{@value}
*/
public static final int KEY_SIZE_2048 = 2048;
/**
* 密钥对MAP中公钥的key值,值为{@value}
*/
public static final String PUBLIC_KEY = "publicKey";
/**
* 密钥对MAP中私钥的key值,值为{@value}
*/
public static final String PRIVATE_KEY = "privateKey";
/**
* 生成密钥对
*
* @param keySize 密钥长度, 目前仅支持{@link #KEY_SIZE_1024 1024位}和
* {@link #KEY_SIZE_2048 2048位}
* @return 密钥对 {@link String} : {@link Object}
* <p>
* 公钥 {@link #PUBLIC_KEY publicKey} :
* {@link RSAPublicKey}
* </p>
* <p>
* 私钥 {@link #PRIVATE_KEY privateKey} :
* {@link RSAPrivateKey}
* </p>
* @throws SecureUtilException
*/
public static Map<String, Object> genKeyPair(int keySize) throws SecureUtilException {
if (keySize != KEY_SIZE_1024 && keySize != KEY_SIZE_2048) {
SecureUtilException sue = new SecureUtilException("暂不支持" + keySize + "位");
throw sue;
}
Map<String, Object> keyPairMap = new HashMap<String, Object>();
KeyPairGenerator keyPairGen = null;
try {
keyPairGen = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
SecureUtilException sue = new SecureUtilException("生成密钥对发生异常");
sue.initCause(e);
throw sue;
}
keyPairGen.initialize(keySize);
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
keyPairMap.put(PUBLIC_KEY, publicKey);
keyPairMap.put(PRIVATE_KEY, privateKey);
return keyPairMap;
}
/**
* RSA公钥生成
*
* <pre>
* 支持Der, X509, .NET, PEM, SSL格式与公钥
* {@link RSAPublicKey}的相互转换
* </pre>
*
* @author 丁盛
*
*
*
* 从模和指数生成公钥
*
* @param modulus 模
* @param publicExponent 公钥指数
* @return 公钥 {@link RSAPublicKey}
* @throws SecureUtilException
*/
public static RSAPublicKey getRsaPublicKey(BigInteger modulus, BigInteger publicExponent)
throws SecureUtilException {
try {
RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, publicExponent);
KeyFactory kf = KeyFactory.getInstance("RSA");
return (RSAPublicKey) kf.generatePublic(spec);
} catch (Exception e) {
SecureUtilException sue = new SecureUtilException("生成公钥发生异常");
sue.initCause(e);
throw sue;
}
}
/**
* 从Der格式公钥生成公钥
* <p>
* <pre>
* DER格式公钥编码规则解析
* 30 SEQUENCE
* 81 长编码 89 长度
* 02 integer
* 81 长编码 81 长度
* 00 因为后面第一个字节的第一个bit是1,所以加了一个00.如果后面第一个bit不是0,则不加00
* e772...1295
* 02 INTEGER
* 03 短编码,长度
* 01 00 01
* </pre>
*
* @param publicKeyDer Der格式公钥字符串
* @return 公钥 {@link RSAPublicKey}
* @throws SecureUtilException
*/
public static RSAPublicKey generatePublicKeyFromDer(String publicKeyDer) throws SecureUtilException {
try {
ASN1InputStream in = new ASN1InputStream(hexString2ByteArr(publicKeyDer));
org.bouncycastle.asn1.pkcs.RSAPublicKey publicKey = org.bouncycastle.asn1.pkcs.RSAPublicKey
.getInstance(in.readObject());
RSAPublicKeySpec spec = new RSAPublicKeySpec(publicKey.getModulus(), publicKey.getPublicExponent());
KeyFactory kf = KeyFactory.getInstance("RSA");
if (in != null)
in.close();
return (RSAPublicKey) kf.generatePublic(spec);
} catch (Exception e) {
SecureUtilException sue = new SecureUtilException("生成公钥发生异常");
sue.initCause(e);
throw sue;
}
}
/**
* 从X509格式公钥生成公钥
* <p>
* <pre>
* X509格式公钥编码规则解析
* 30 SEQUENCE
* 81 长编码 9f 长度
* 30 SEQUENCE
* 0d 短编码,长度
* 06 对象标识符,有一列整数构成,用于确定对象,如算法或属性类型
* 09 短编码,长度
* 2a 86 48 86 f7 0d 01 01 01 rsa
* 05 00 NULL
* 03 big string
* 81 长编码 8d 长度
* 00
* 30 SEQUENCE
* 81 长编码 89 长度
* 02 integer
* 81 长编码 81 长度
* 00 因为后面第一个字节的第一个bit是1,所以加了一个00.如果后面第一个bit不是0,则不加00
* e772...1295
* 02 INTEGER
* 03 短编码,长度
* 01 00 01
* </pre>
*
* @param publicKeyX509 X509格式公钥字符串
* @return 公钥 {@link RSAPublicKey}
* @throws SecureUtilException
*/
public static RSAPublicKey generatePublicKeyFromX509(String publicKeyX509) throws SecureUtilException {
try {
X509EncodedKeySpec spec = new X509EncodedKeySpec(hexString2ByteArr(publicKeyX509));
KeyFactory kf = KeyFactory.getInstance("RSA");
return (RSAPublicKey) kf.generatePublic(spec);
} catch (Exception e) {
SecureUtilException sue = new SecureUtilException("生成公钥发生异常");
sue.initCause(e);
throw sue;
}
}
/**
* 从NET格式公钥生成公钥
*
* @param publicKeyNet NET格式公钥字符串
* @return 公钥 {@link RSAPublicKey}
* @throws SecureUtilException
*/
public static PublicKey generatePublicKeyFromNet(String publicKeyNet) throws SecureUtilException {
try {
BigInteger modulus = new BigInteger(base64Decode(publicKeyNet.substring(
publicKeyNet.indexOf("<Modulus>") + 9, publicKeyNet.indexOf("</Modulus>")).getBytes()));
BigInteger publicExponent = new BigInteger(base64Decode(publicKeyNet.substring(
publicKeyNet.indexOf("<Exponent>") + 10, publicKeyNet.indexOf("</Exponent>")).getBytes()));
return getRsaPublicKey(modulus, publicExponent);
} catch (Exception e) {
SecureUtilException sue = new SecureUtilException("生成公钥发生异常");
sue.initCause(e);
throw sue;
}
}
/**
* 从PEM格式公钥生成公钥
* <p>
* <pre>
* PEM格式为将X509格式公钥进行base64编码
* </pre>
*
* @param publicKeyPEM PEM格式公钥字符串
* @return 公钥 {@link RSAPublicKey}
* @throws SecureUtilException
*/
public static PublicKey generatePublicKeyFromPEM(String publicKeyPEM) throws SecureUtilException {
try {
// 得到X509格式公钥
String publicKeyX509 = byteArr2HexString(base64Decode(publicKeyPEM.getBytes()));
// 得到公钥
return generatePublicKeyFromX509(publicKeyX509);
} catch (Exception e) {
SecureUtilException sue = new SecureUtilException("生成公钥发生异常");
sue.initCause(e);
throw sue;
}
}
/**
* 从SSL格式公钥生成公钥
* <p>
* <pre>
* SSL格式公钥编码格式解析
* 前11字节为固定值 0007ssh-rsa
* 紧接着4个字节表示public exponent所占字节长度
* 得到长度后,从后一字节开始读取该长度字节数组作为public exponent的值
* 再紧接着4个字节也是一个int值,表示modulus所占字节长度
* 再根据长度读取字节数组得到modulus值
* </pre>
*
* @param publicKeySSL SSL格式公钥字符串
* @return 公钥 {@link RSAPublicKey}
* @throws SecureUtilException
*/
public static RSAPublicKey generatePublicKeyFromSSL(String publicKeySSL) throws SecureUtilException {
try {
byte[] bytes = base64Decode(publicKeySSL.getBytes());
// public exponent长度读取起始位置
int startIndex = 7;
// public exponent长度
int len = new BigInteger(Arrays.copyOfRange(bytes, startIndex, startIndex + 4)).intValue();
// public exponent读取起始位置
startIndex = startIndex + 4;
// public exponent
BigInteger publicExponent = new BigInteger(Arrays.copyOfRange(bytes, startIndex, startIndex + len));
// modulus长度读取起始位置
startIndex = startIndex + len;
// modulus长度
len = new BigInteger(Arrays.copyOfRange(bytes, startIndex, startIndex + 4)).intValue();
// modulus读取起始位置
startIndex = startIndex + 4;
// modulus
BigInteger modulus = new BigInteger(Arrays.copyOfRange(bytes, startIndex, startIndex + len));
// 根据模和指数生成公钥
return getRsaPublicKey(modulus, publicExponent);
} catch (Exception e) {
SecureUtilException sue = new SecureUtilException("生成公钥发生异常");
sue.initCause(e);
throw sue;
}
}
/**
* 生成Der格式公钥
*
* @param publicKey {@link RSAPublicKey}
* @return Der格式公钥字符串
* @throws SecureUtilException
*/
public static String getRsaPublicKeyDer(RSAPublicKey publicKey) throws SecureUtilException {
try {
return byteArr2HexString(new org.bouncycastle.asn1.pkcs.RSAPublicKey(publicKey.getModulus(),
publicKey.getPublicExponent()).toASN1Primitive().getEncoded());
} catch (IOException e) {
SecureUtilException sue = new SecureUtilException("生成公钥发生异常");
sue.initCause(e);
throw sue;
}
}
/**
* 生成X509格式公钥
*
* @param publicKey {@link RSAPublicKey}
* @return X509格式公钥字符串
*/
public static String getRsaPublicKeyX509(RSAPublicKey publicKey) {
return byteArr2HexString(publicKey.getEncoded());
}
/**
* 生成.NET格式公钥
*
* @param publicKey {@link RSAPublicKey}
* @return .NET格式公钥字符串
*/
public static String getRsaPublicKeyNet(RSAPublicKey publicKey) {
StringBuilder sb = new StringBuilder();
sb.append("<RSAKeyValue>");
sb.append("<Modulus>").append(base64Encode(publicKey.getModulus().toByteArray()))
.append("</Modulus>");
sb.append("<Exponent>").append(base64Encode(publicKey.getPublicExponent().toByteArray()))
.append("</Exponent>");
sb.append("</RSAKeyValue>");
return sb.toString();
}
/**
* 生成PEM格式公钥
*
* @param publicKey {@link RSAPublicKey}
* @return PEM格式公钥字符串
* @throws SecureUtilException
*/
public static String getRsaPublicKeyPem(RSAPublicKey publicKey) throws SecureUtilException {
StringBuilder sb = new StringBuilder();
sb.append("-----BEGIN PUBLIC KEY-----\n");
sb.append(new String(base64Encode(hexString2ByteArr(getRsaPublicKeyX509(publicKey)))));
sb.append("\n-----END PUBLIC KEY-----");
return sb.toString();
}
/**
* 将X509格式公钥转换为DER格式公钥
*
* @param publicKeyX509 X509格式公钥字符串
* @return DER格式公钥字符串
* @throws SecureUtilException
*/
public static String getRsaPublicKeyDerFromX509(String publicKeyX509) throws SecureUtilException {
try {
ASN1InputStream in = new ASN1InputStream(hexString2ByteArr(publicKeyX509));
SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(in.readObject());
org.bouncycastle.asn1.pkcs.RSAPublicKey publicKey = org.bouncycastle.asn1.pkcs.RSAPublicKey
.getInstance(info.parsePublicKey());
if (in != null) {
in.close();
}
return byteArr2HexString(publicKey.toASN1Primitive().getEncoded());
} catch (Exception e) {
SecureUtilException sue = new SecureUtilException("转换公钥发生异常");
sue.initCause(e);
throw sue;
}
}
/**
* RSA私钥生成
*
*
*
* 从模和指数生成私钥
*
* @param modulus 模
* @param privateExponent 私钥指数
* @return 私钥 {@link RSAPrivateKey}
* @throws SecureUtilException
*/
public static RSAPrivateKey getRsaPrivateKey(BigInteger modulus, BigInteger privateExponent)
throws SecureUtilException {
try {
RSAPrivateKeySpec spec = new RSAPrivateKeySpec(modulus, privateExponent);
KeyFactory kf = KeyFactory.getInstance("RSA");
return (RSAPrivateKey) kf.generatePrivate(spec);
} catch (Exception e) {
SecureUtilException sue = new SecureUtilException("生成私钥发生异常");
sue.initCause(e);
throw sue;
}
}
/**
* 从私钥字符串生成私钥
*
* @param privateKey PKCS#8格式的私钥字符串
* @return 私钥 {@link RSAPrivateKey}
* @throws SecureUtilException
*/
public static PrivateKey generatePrivateKey(String privateKey) throws SecureUtilException {
try {
// 构造PKCS8EncodedKeySpec对象
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey.getBytes());
// 指定的加密算法
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
// 取私钥匙对象
PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
return priKey;
} catch (Exception e) {
SecureUtilException sue = new SecureUtilException("生成私钥发生异常");
sue.initCause(e);
throw sue;
}
}
/**
* base64编码
*
* @param inputByte 字节数组
* @return 字节数组
*/
public static byte[] base64Encode(byte[] inputByte) {
return Base64.encode(inputByte);
}
/**
* base64解码
*
* @param inputByte 字节数组
* @return 字节数组
*/
public static byte[] base64Decode(byte[] inputByte) {
return Base64.decode(inputByte);
}
/**
* 字节数组转换为十六进制字符串
*
* @param bytearr 字节数组
* @return 十六进制字符串
*/
public static String byteArr2HexString(byte[] bytearr) {
if (bytearr == null) {
return "null";
}
StringBuffer sb = new StringBuffer();
for (int k = 0; k < bytearr.length; k++) {
if ((bytearr[k] & 0xFF) < 16) {
sb.append("0");
}
sb.append(Integer.toString(bytearr[k] & 0xFF, 16));
}
return sb.toString();
}
/**
* 十六进制字符串转换为字节数组
*
* @param hexstring 十六进制字符串
* @return 字节数组
*/
public static byte[] hexString2ByteArr(String hexstring) {
if ((hexstring == null) || (hexstring.length() % 2 != 0)) {
return new byte[0];
}
byte[] dest = new byte[hexstring.length() / 2];
for (int i = 0; i < dest.length; i++) {
String val = hexstring.substring(2 * i, 2 * i + 2);
dest[i] = (byte) Integer.parseInt(val, 16);
}
return dest;
}
/**
* 哈希算法,值为{@value}
*/
public final static String ALGORITHM_HASH_MD5 = "MD5";
/**
* 哈希算法,值为{@value}
*/
public final static String ALGORITHM_HASH_SHA256 = "SHA-256";
/**
* 哈希算法,值为{@value}
*/
public final static String ALGORITHM_HASH_SHA1 = "SHA-1";
/**
* 编码格式,值为{@value}
*/
public final static String CHARSET_UTF8 = "UTF-8";
/**
* 编码格式,值为{@value}
*/
public final static String CHARSET_GBK = "GBK";
/**
* 编码格式,值为{@value}
*/
public final static String CHARSET_GB2312 = "GB2312";
/**
* 哈希
*
* @param data 明文数据
* @param algorithm 哈希算法,支持{@link #ALGORITHM_HASH_MD5 MD5},
* {@link #ALGORITHM_HASH_SHA256 SHA-256}和
* {@link #ALGORITHM_HASH_SHA1 SHA-1};也可自定义
* @return 密文数据
* @throws SecureUtilException
*/
public static byte[] hash(byte[] data, String algorithm) throws SecureUtilException {
MessageDigest md = null;
try {
md = MessageDigest.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
SecureUtilException sue = new SecureUtilException("不支持" + algorithm + "算法");
sue.initCause(e);
throw sue;
}
md.update(data);
return md.digest();
}
/**
* 哈希,字符串对字符串
*
* @param data 明文数据,字符串
* @param charset 编码格式,支持{@link #CHARSET_UTF8 UTF-8}, {@link #CHARSET_GBK GBK}和
* {@link #CHARSET_GB2312 GB2312};也可自定义
* @param algorithm 哈希算法,支持{@link #ALGORITHM_HASH_MD5 MD5},
* {@link #ALGORITHM_HASH_SHA256 SHA-256}和
* {@link #ALGORITHM_HASH_SHA1 SHA-1};也可自定义
* @return 如果输入为空,则直接返回;不为空,返回密文数据,十六进制字符串
* @throws SecureUtilException
*/
public static String hashHex(String data, String charset, String algorithm) throws SecureUtilException {
if (StringUtils.isEmpty(data)) {
return data;
}
try {
return byteArr2HexString(hash(data.getBytes(charset), algorithm));
} catch (UnsupportedEncodingException e) {
SecureUtilException sue = new SecureUtilException("不支持" + charset + "编码格式");
sue.initCause(e);
throw sue;
}
}
/**
* 哈希,字符串对字符串
*
* @param data 明文数据,字符串,UTF-8 编码
* @param algorithm 哈希算法,支持{@link #ALGORITHM_HASH_MD5 MD5},
* {@link #ALGORITHM_HASH_SHA256 SHA-256}和
* {@link #ALGORITHM_HASH_SHA1 SHA-1};也可自定义
* @return 如果输入为空,则直接返回;不为空,返回密文数据,十六进制字符串
* @throws SecureUtilException
*/
public static String hashHex(String data, String algorithm) throws SecureUtilException {
return hashHex(data, CHARSET_UTF8, algorithm);
}
/**
* 校验哈希值
*
* @param hashData 密文数据,十六进制字符串
* @param data 明文数据
* @param charset 编码格式,支持{@link #CHARSET_UTF8 UTF-8}, {@link #CHARSET_GBK GBK}和
* {@link #CHARSET_GB2312 GB2312};也可自定义
* @param algorithm 哈希算法,支持{@link #ALGORITHM_HASH_MD5 MD5},
* {@link #ALGORITHM_HASH_SHA256 SHA-256}和
* {@link #ALGORITHM_HASH_SHA1 SHA-1};也可自定义
* @return
* @throws SecureUtilException
*/
public static boolean checkHashHex(String hashData, String data, String charset, String algorithm)
throws SecureUtilException {
return hashData.equals(hashHex(data, charset, algorithm));
}
/**
* 校验哈希值
*
* @param hashData 密文数据,十六进制字符串,UTF-8编码
* @param data 明文数据
* @param algorithm 哈希算法,支持{@link #ALGORITHM_HASH_MD5 MD5},
* {@link #ALGORITHM_HASH_SHA256 SHA-256}和
* {@link #ALGORITHM_HASH_SHA1 SHA-1};也可自定义
* @return
* @throws SecureUtilException
*/
public static boolean checkHashHex(String hashData, String data, String algorithm)
throws SecureUtilException {
return hashData.equals(hashHex(data, algorithm));
}
/**
* 哈希Xor
*
* @param data 明文数据
* @param algorithm 哈希算法,支持{@link #ALGORITHM_HASH_MD5 MD5},
* {@link #ALGORITHM_HASH_SHA256 SHA-256}和
* {@link #ALGORITHM_HASH_SHA1 SHA-1};也可自定义
* @return 密文数据
* @throws SecureUtilException
*/
public static byte[] xorHash(byte[] data, String algorithm) throws SecureUtilException {
int len = data.length;
byte[] descData = new byte[len];
for (int i = 0; i < len; i++) {
descData[len - 1 - i] = data[i];
}
for (int i = 0; i < len; i++) {
data[i] = (byte) (data[i] ^ descData[i]);
}
return hash(data, algorithm);
}
/**
* 哈希Xor
*
* @param data 明文数据
* @param charset 编码格式,支持{@link #CHARSET_UTF8 UTF-8}, {@link #CHARSET_GBK GBK}和
* {@link #CHARSET_GB2312 GB2312};也可自定义
* @param algorithm 哈希算法,支持{@link #ALGORITHM_HASH_MD5 MD5},
* {@link #ALGORITHM_HASH_SHA256 SHA-256}和
* {@link #ALGORITHM_HASH_SHA1 SHA-1};也可自定义
* @return 如果输入为空,则直接返回;不为空,返回密文数据,十六进制字符串
* @throws SecureUtilException
*/
public static String xorHashHex(String data, String charset, String algorithm) throws SecureUtilException {
if (StringUtils.isEmpty(data)) {
return data;
}
try {
return byteArr2HexString(xorHash(data.getBytes(charset), algorithm));
} catch (UnsupportedEncodingException e) {
SecureUtilException sue = new SecureUtilException("不支持" + charset + "编码格式");
sue.initCause(e);
throw sue;
}
}
/**
* 哈希Xor
* <p>
* <pre>
* 默认编码格式为{@link #CHARSET_UTF8 UTF-8}
* </pre>
*
* @param data 明文数据,UTF-8编码
* @param algorithm 哈希算法,支持{@link #ALGORITHM_HASH_MD5 MD5},
* {@link #ALGORITHM_HASH_SHA256 SHA-256}和
* {@link #ALGORITHM_HASH_SHA1 SHA-1};也可自定义
* @return 如果输入为空,则直接返回;不为空,返回密文数据,十六进制字符串
* @throws SecureUtilException
*/
public static String xorHashHex(String data, String algorithm) throws SecureUtilException {
return xorHashHex(data, CHARSET_UTF8, algorithm);
}
/**
* 校验哈希值Xor
*
* @param hashData 密文数据,十六进制字符串
* @param data 明文数据
* @param charset 编码格式,支持{@link #CHARSET_UTF8 UTF-8}, {@link #CHARSET_GBK GBK}和
* {@link #CHARSET_GB2312 GB2312};也可自定义
* @param algorithm 哈希算法,支持{@link #ALGORITHM_HASH_MD5 MD5},
* {@link #ALGORITHM_HASH_SHA256 SHA-256}和
* {@link #ALGORITHM_HASH_SHA1 SHA-1};也可自定义
* @return
* @throws SecureUtilException
*/
public static boolean checkXorHashHex(String hashData, String data, String charset, String algorithm)
throws SecureUtilException {
return hashData.equals(xorHashHex(data, charset, algorithm));
}
/**
* 校验哈希值Xor
* <p>
* <pre>
* 默认编码格式为{@link #CHARSET_UTF8 UTF-8}
* </pre>
*
* @param hashData 密文数据,十六进制字符串
* @param data 明文数据
* @param algorithm 哈希算法,支持{@link #ALGORITHM_HASH_MD5 MD5},
* {@link #ALGORITHM_HASH_SHA256 SHA-256}和
* {@link #ALGORITHM_HASH_SHA1 SHA-1};也可自定义
* @return
* @throws SecureUtilException
*/
public static boolean checkXorHashHex(String hashData, String data, String algorithm) throws SecureUtilException {
return hashData.equals(xorHashHex(data, algorithm));
}
/**
* 将对象转换成map
*
* @param bean
* @return
*/
public static <T> Map<String, String> beanToMap(T bean) {
Map<String, String> map = new HashMap<String, String>();
if (bean != null) {
BeanMap beanMap = BeanMap.create(bean);
for (Object key : beanMap.keySet()) {
map.put(key+"", (String)beanMap.get(key));
}
}
return map;
}
/**
* 获取签名裸数据
*
* @param superDto
*/
public static String getReturnRawData(SuperDto superDto) {
Map<String, String> srcMap = beanToMap(superDto);
List<String> sortKeys = new ArrayList<String>(srcMap.keySet());
Collections.sort(sortKeys);
StringBuffer sb = new StringBuffer();
for (String key : sortKeys) {
if (key.equals("signature") || isEmpty(srcMap.get(key))) {
continue;
}
sb.append(key);
sb.append("=");
sb.append(srcMap.get(key));
sb.append("&");
}
String rawData = sb.toString();
return rawData.substring(0, rawData.length() - 1);
}
public static boolean validate(SuperDto superDto) {
logger.info("========开始验签===========");
System.out.println("result:" + superDto);
try {
String signature = superDto.getSignature();
logger.info("resp signature:{}",signature);
logger.info("========生成rawData===========");
String rawDataStr = getReturnRawData(superDto);
logger.info("rawData:{}", rawDataStr);
logger.info("========生成验签结果===========");
Boolean flag = false;
try {
flag = verify(rawDataStr.getBytes(), hexString2ByteArr(signature), pubKey, ALGORITHM_SHA256WITHRSA);
} catch (Exception e) {
flag = verify(hash(rawDataStr.getBytes(), "SHA-256"), hexString2ByteArr(signature), pubKey, TRANSFORMATION_RSA);
}
logger.info("验签结果:{}", flag);
return flag;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 哈希加密
*
* @param strSrc 需要加密的字符串
* @param encName 需要采用的加密方式,如:SHA-1,SHA-256,SHA-256等等
* @return
*/
public static String Encrypt(String strSrc, String encName) {
MessageDigest md = null;
String strDes = null;
byte[] bt = strSrc.getBytes();
try {
md = MessageDigest.getInstance(encName);
md.update(bt);
strDes = bytes2Hex(md.digest()); // to HexString
System.out.println(strDes);
} catch (NoSuchAlgorithmException e) {
logger.error(e.getMessage());
return null;
}
return strDes;
}
public static String bytes2Hex(byte[] bts) {
String des = "";
String tmp = null;
for (int i = 0; i < bts.length; i++) {
tmp = (Integer.toHexString(bts[i] & 0xFF));
if (tmp.length() == 1) {
des += "0";
}
des += tmp;
}
return des;
}
}