所需jar:bouncycastle.jar
設定檔cert.properties
cert_path=E://test.p12cert_pwd=123456
CertUtil.java代碼如下
package test.test;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;import java.security.KeyStore;import java.security.PrivateKey;import java.security.PublicKey;import java.security.Security;import java.security.Signature;import java.security.cert.Certificate;import java.security.cert.X509Certificate;import java.util.Enumeration;import java.util.Iterator;import java.util.LinkedHashMap;import java.util.Map;import java.util.Properties;import javax.crypto.Cipher;import org.apache.log4j.Logger;import org.bouncycastle.jce.provider.BouncyCastleProvider;/** * 類名: CertUtil * 描述: p12認證工具類 * 版本: V1.0 * modify 2017年4月3日 上午09:06:37 * copyright. */public class CertUtil { private static Logger logger = Logger.getLogger(CertUtil.class); private static KeyStore keyStore; private static String CERT_PATH; private static String CERT_PWD; private final static String KEY_STORE_TYPE = "PKCS12"; static { Properties prop = new Properties(); try { prop.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("test/test/cert.properties")); } catch (Exception e) { logger.error("fail to read cert.properties..."); } CERT_PATH = prop.getProperty("cert_path"); CERT_PWD = prop.getProperty("cert_pwd"); if(keyStore == null){ try { keyStore = initKeyStore(); } catch (Exception e) { logger.error("fail to init keystore..."); } } } /** * 方法: getPrivateKey * 描述: 擷取私密金鑰 * @return */ public static PrivateKey getPrivateKey() throws Exception { return (PrivateKey) keyStore.getKey(getAlias(), CertUtil.CERT_PWD.toCharArray()); } /** * 方法: getPublicKey * 描述: 擷取公開金鑰 * @return */ public static PublicKey getPublicKey() throws Exception { return getCertificate().getPublicKey(); } /** * 方法: getAlias * 描述: 擷取第一個別名 * @return */ public static String getAlias() throws Exception { Enumeration<String> aliases = keyStore.aliases(); if(aliases.hasMoreElements()){ return aliases.nextElement(); } return null; } /** * 方法: initKeyStore * 描述: 擷取密鑰庫 * @return */ public static KeyStore initKeyStore() throws Exception { Security.addProvider(new BouncyCastleProvider()); KeyStore ks = KeyStore.getInstance(CertUtil.KEY_STORE_TYPE); //絕對路徑 InputStream is = new FileInputStream(new File(CertUtil.CERT_PATH)); //相對路徑 //InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(CertUtil.CERT_PATH); ks.load(is, CertUtil.CERT_PWD.toCharArray()); is.close(); return ks; } /** * 方法: getCertificate * 描述: 擷取認證 * @return */ public static Certificate getCertificate() throws Exception { return keyStore.getCertificate(getAlias()); } /** * 方法: getCipher * 描述: 擷取Cipher * @param isPublic 是否公開金鑰模式 * @param mode 加密/解密 * @return */ public static Cipher getCipher(boolean isPublic, int mode) throws Exception { Cipher cipher = null; if(isPublic){ PublicKey publicKey = getPublicKey(); cipher = Cipher.getInstance(publicKey.getAlgorithm()); cipher.init(mode, publicKey); }else{ PrivateKey privateKey = getPrivateKey(); cipher = Cipher.getInstance(privateKey.getAlgorithm()); cipher.init(mode, privateKey); } return cipher; } /** * 方法: bytesToStrHex * 描述: 數群組轉換成16進位字串 * @param bytes 源數組 * @return String */ public static final String bytesToStrHex(byte[] bytes) { StringBuffer sb = new StringBuffer(bytes.length); String sTemp; for (int i = 0; i < bytes.length; i++) { sTemp = Integer.toHexString(0xFF & bytes[i]); if (sTemp.length() < 2) sb.append(0); sb.append(sTemp.toUpperCase()); } return sb.toString(); } /** * 方法: hexStrToBytes * 描述: 將16進位字串還原為位元組數組 * @param str 16進位字串 * @return byte[] */ private static final byte[] hexStrToBytes(String str) { byte[] bytes; bytes = new byte[str.length() / 2]; for (int i = 0; i < bytes.length; i++) { bytes[i] = (byte) Integer.parseInt(str.substring(2 * i, 2 * i + 2), 16); } return bytes; } /*==========================================簽名================================================*/ /** * 方法: sign * 描述: 數位簽章並轉換進位 * @param requestMap 來源資料 * @return */ public static String sign(Map<String, String> requestMap) throws Exception { //把請求參數拼接成功字串:value1value2value3... StringBuffer sourceData = new StringBuffer(); for (Iterator<Map.Entry<String, String>> iter = requestMap.entrySet().iterator(); iter.hasNext();) { Map.Entry<String, String> entry = iter.next(); sourceData.append(entry.getValue()); } byte[] bytes = sign(sourceData.toString().getBytes()); return bytesToStrHex(bytes); } /** * 方法: sign * 描述: 數位簽章 * @param byteData 源位元組 * @return */ public static byte[] sign(byte[] byteData) throws Exception { PrivateKey privateKey = getPrivateKey(); X509Certificate x509Certificate= (X509Certificate) getCertificate(); Signature signature = Signature.getInstance(x509Certificate.getSigAlgName()); signature.initSign(privateKey); signature.update(byteData); return signature.sign(); } /** * 方法: verify * 描述: 進位轉換並驗簽 * @param signStr 簽名字串 * @param requestMap 來源資料 * @return */ public static boolean verify(String signStr, Map<String, String> requestMap) throws Exception { byte[] signData = hexStrToBytes(signStr); StringBuffer sourceData = new StringBuffer(); for (Iterator<Map.Entry<String, String>> iter = requestMap.entrySet().iterator(); iter.hasNext();) { Map.Entry<String, String> entry = iter.next(); sourceData.append(entry.getValue()); } return verify(sourceData.toString().getBytes(), signData); } /** * 方法: verify * 描述: 認證所含公開金鑰校正簽名 * @param sourceData 源位元組 * @param signData 簽名位元組 * @return */ public static boolean verify(byte[] sourceData,byte[] signData) throws Exception { X509Certificate x509Certificate = (X509Certificate) getCertificate(); Signature signature = Signature.getInstance(x509Certificate.getSigAlgName()); signature.initVerify(x509Certificate); signature.update(sourceData); return signature.verify(signData); } /*==========================================加密=======================================*/ /** * 方法: encrypt * 描述: 加密並轉換進位 * @param requestMap 來源資料 * @param isPubEncrypt 是否使用公開金鑰加密 * @return */ public static String encrypt(Map<String, String> requestMap, boolean isPubEncrypt) throws Exception { //把請求參數拼接成功字串:value1value2value3... StringBuffer sourceData = new StringBuffer(); for (Iterator<Map.Entry<String, String>> iter = requestMap.entrySet().iterator(); iter.hasNext();) { Map.Entry<String, String> entry = iter.next(); sourceData.append(entry.getValue()); } byte[] encryptData = encrypt(sourceData.toString().getBytes(), isPubEncrypt); return bytesToStrHex(encryptData); } /** * 方法: encrypt * 描述: 加密 * @param encryptData 待加密位元組 * @param isPubEncrypt 是否使用公開金鑰加密 * @return */ public static byte[] encrypt(byte[] encryptData, boolean isPubEncrypt) throws Exception { Cipher cipher = getCipher(isPubEncrypt, Cipher.ENCRYPT_MODE); return cipher.doFinal(encryptData); } /** * 方法: decrypt * 描述: 轉換進位並解密 * @param decryptStr 加密字串 * @param isPubDecrypt 是否使用公開金鑰解密 * @return */ public static String decrypt(String decryptStr, boolean isPubDecrypt) throws Exception { byte[] decryptData = hexStrToBytes(decryptStr); return new String(decrypt(decryptData, isPubDecrypt)); } /** * 方法: decrypt * 描述: 解密 * @param decryptData 加密位元組 * @param isPubDecrypt 是否使用公開金鑰解密 * @return */ public static byte[] decrypt(byte[] decryptData, boolean isPubDecrypt) throws Exception { Cipher cipher = getCipher(isPubDecrypt, Cipher.DECRYPT_MODE); return cipher.doFinal(decryptData); } public static void main(String[] args) throws Exception { Map<String, String> requestMap = new LinkedHashMap<>(); requestMap.put("batchno", "17005846899643554"); requestMap.put("amount", "100005"); requestMap.put("uapcode", "152516"); System.out.println("請求資料:"+ requestMap.toString()); String signStr = CertUtil.sign(requestMap); System.out.println("簽名資料:" + signStr); System.out.println("驗簽結果:" + CertUtil.verify(signStr, requestMap)); String priEncryptStr = CertUtil.encrypt(requestMap, false); System.out.println("私密金鑰加密" + priEncryptStr); System.out.println("公開金鑰解密" + CertUtil.decrypt(priEncryptStr, true)); String pubEncryptStr = CertUtil.encrypt(requestMap, true); System.out.println("公開金鑰加密" + pubEncryptStr); System.out.println("私密金鑰解密" + CertUtil.decrypt(pubEncryptStr, false)); }}
結果如下