jar:com.cfca.pkibase-1.0.jarhtml
import java.io.UnsupportedEncodingException;java import java.security.Security;api
import org.bouncycastle.jce.provider.BouncyCastleProvider;數組 import com.cfca.util.pki.PKIException;session import com.cfca.util.pki.api.CertUtil;ide import com.cfca.util.pki.api.KeyUtil;工具 import com.cfca.util.pki.api.SignatureUtil;編碼 import com.cfca.util.pki.cert.X509Cert;spa import com.cfca.util.pki.cipher.JCrypto;htm import com.cfca.util.pki.cipher.JKey; import com.cfca.util.pki.cipher.Session; import com.cfca.util.pki.extension.SelfDefExtension;
/** * <pre> * CFCA證書工具類 * help:http://www.360doc.com/content/13/0831/06/11482448_311087429.shtml * @version:1.0 * </pre> */ public class CFCACertSignUtils {
private static Session session = null; private static final String ALGORITHM = SignatureUtil.SHA1_RSA; public static final String DEFAULT_CHARSET = "UTF-8"; public static String lock = "LOCK"; public static final String YEEPAY_IDENTITY = "OU=ra.yeepay.com"; public static final String CERT_EXT_INFO = new String("1.2.86.1");
static { try { Security.addProvider(new BouncyCastleProvider()); } catch (Exception e) { e.printStackTrace(); } }
private synchronized static void init() { if (session != null) { return; } try { JCrypto jcrypto = JCrypto.getInstance(); jcrypto.initialize(JCrypto.JSOFT_LIB, null); session = jcrypto.openSession(JCrypto.JSOFT_LIB);
} catch (Exception e) { e.printStackTrace(); } }
/** * 獲取證書的私鑰對象信息 * * @param certPath * CFCA pfx格式證書文件路徑 * @param certPswd * CFCA證書密碼 * @return */ public static JKey getPrivaeKey(String certPath, String certPswd) throws PKIException { return KeyUtil.getPriKey(certPath, certPswd); }
/** * 獲取證書的公鑰對象信息 * * @param certPath * CFCA pfx格式證書文件路徑 * @param certPswd * CFCA證書密碼 * @return */ public static X509Cert getPublicKey(String certPath, String certPswd) throws PKIException { return CertUtil.getCert(certPath, certPswd); }
/** * CFCA非分離式PKCS#7簽名--驗籤須要對應非分離式驗籤方法verifySignMessageP7 * * @param sourceMessage * 源消息 * @param privateKey * 私鑰 * @param publicKey * 公鑰 * @return */ public static String sign(String sourceMessage, JKey privateKey, X509Cert[] publicKey, String charset) { if (session == null) { init(); } try { String yphs = Digest.hmacSign(sourceMessage, charset); SignatureUtil signUtil = new SignatureUtil(); byte[] input = null; if (charset == null) { input = yphs.getBytes(); } else { input = yphs.getBytes(charset); } // 對消息簽名 byte[] b64SignData; b64SignData = signUtil.p7SignMessage(true, input, ALGORITHM, privateKey, publicKey, session); String signMessage = new String(b64SignData, DEFAULT_CHARSET); return signMessage; } catch (Exception e) { throw new RuntimeException("簽名失敗!", e); } }
/** * <pre> * 驗證簽名的合法性 驗證商戶的CFCA非分離式PKCS#7簽名 (驗證簽名信息的完整性和不可抵賴性) * * @param sourceMessage * 商戶原始交易數據 * @param signMessage * CFCA簽名結果(Base64編碼)以UTF-8編碼成的字符串 * @param customerNo * 客戶號(驗證當前證書是不是授予該客戶的證書) * @return X509Cert[] 驗籤經過後返回簽名證書的公鑰信息 * @throws UnsupportedEncodingException * @throws PKIException * </pre> */ public static boolean verifySign(String sourceMessage, String signMessage, String customerNo) { if (customerNo == null) { throw new IllegalArgumentException("當前業務客戶號未指定"); } if (session == null) { init(); } try {
SignatureUtil signUtil = new SignatureUtil(); // 對原始交易數據作hash摘要 String digestMsg = Digest.hmacSign(sourceMessage, DEFAULT_CHARSET); byte signData[] = signMessage.getBytes(DEFAULT_CHARSET);// 再以UTF-8編碼方式解碼成字節數組
boolean verify = signUtil.p7VerifySignMessage(signData, session);// 1.驗證簽名的不可抵賴性
if (verify) {// 簽名 // 得到簽名中的證書 X509Cert x509Certs = signUtil.getSigerCert()[0];
// 得到簽名數據中的原文 byte[] srcData = signUtil.getSignedContent();// 原始hash值的BASE64編碼 String reverseHashMessage = new String(srcData, DEFAULT_CHARSET);
// 證書全部者身份校驗 identityVerify(customerNo, x509Certs);
if (reverseHashMessage.equals(digestMsg)) {// 2.原始數據獲得的摘要和驗籤獲得的原始摘要作比較驗證數據的完整性 return true; } else { throw new RuntimeException("消息摘要信息不一致,信息可能被篡改!"); } } else { throw new RuntimeException("驗籤失敗"); } } catch (Exception e) { throw new RuntimeException(e); } }
// 證書全部者身份校驗 private static void identityVerify(String customerNo, X509Cert x509Certs) throws PKIException { String certDN = x509Certs.getSubject();
boolean isValidecertDN = false; String certDNItems[] = certDN.split(","); for (String item : certDNItems) { if (item.equals(YEEPAY_IDENTITY)) { isValidecertDN = true; } }
if (!isValidecertDN) { throw new RuntimeException("不是yeepay頒發的CFCA證書"); }
String extension = null; SelfDefExtension extensionInfo = x509Certs .getSelfDefExtension(CERT_EXT_INFO); if (extensionInfo == null) { throw new RuntimeException("證書擴展信息未指定,沒法識別客戶身份信息"); } extension = extensionInfo.getExtensionValue(); if (extension == null) { throw new RuntimeException("證書擴展信息未指定,沒法識別客戶身份信息"); }
if (!customerNo.equals(extension)) { throw new RuntimeException("當前證書不是頒發給客戶[" + customerNo + "]的證書!"); } } } |