CFCA证书工具类
jar:com.cfca.pkibase-1.0.jar
|
import java.io.UnsupportedEncodingException; import java.security.Security; import org.bouncycastle.jce.provider.BouncyCastleProvider; import com.cfca.util.pki.PKIException; import com.cfca.util.pki.api.CertUtil; import com.cfca.util.pki.api.KeyUtil; import com.cfca.util.pki.api.SignatureUtil; import com.cfca.util.pki.cert.X509Cert; import com.cfca.util.pki.cipher.JCrypto; 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 + "]的证书!"); } } } |
CFCA证书工具类的更多相关文章
- HttpClient4.5 SSL访问工具类
要从网上找一个HttpClient SSL访问工具类太难了,原因是HttpClient版本太多了,稍有差别就不能用,最后笔者干脆自己封装了一个访问HTTPS并绕过证书工具类. 主要是基于新版本Http ...
- 我的Android进阶之旅------>Android关于HttpsURLConnection一个忽略Https证书是否正确的Https请求工具类
下面是一个Android HttpsURLConnection忽略Https证书是否正确的Https请求工具类,不需要验证服务器端证书是否正确,也不需要验证服务器证书中的域名是否有效. (PS:建议下 ...
- 带SSL证书的httpclient 远程接口工具类
package com.iups.wx.util; import java.io.IOException; import java.io.UnsupportedEncodingException; i ...
- java http工具类和HttpUrlConnection上传文件分析
利用java中的HttpUrlConnection上传文件,我们其实只要知道Http协议上传文件的标准格式.那么就可以用任何一门语言来模拟浏览器上传文件.下面有几篇文章从http协议入手介绍了java ...
- 微信https请求工具类
工作中用到的微信https请求工具类. package com.gxgrh.wechat.tools; import com.gxgrh.wechat.wechatapi.service.System ...
- HttpClient 4.5.x 工具类设计与实现
最近,业务需要在java服务端发起http请求,需要实现"GET","POST","PUT"等基本方法.于是想以 "HttpCli ...
- Net处理html页面元素工具类(HtmlAgilityPack.dll)的使用
现在,在不少应用场合中都希望做到数据抓取,特别是基于网页部分的抓取.其实网页抓取的过程实际上是通过编程的方法,去抓取不同网站网页后,再进行 分析筛选的过程.比如,有的比较购物网站,会同时去抓取不同购物 ...
- 基于HttpClient 4.3的可訪问自签名HTTPS网站的新版工具类
本文出处:http://blog.csdn.net/chaijunkun/article/details/40145685,转载请注明.因为本人不定期会整理相关博文,会对相应内容作出完好.因此强烈建议 ...
- java中模拟http(https)请求的工具类
在java中,特别是java web中,我们经常需要碰到的一个场景是我们需要从服务端去发送http请求,获取到数据,而不是直接从浏览器输入请求网址获得相应.比如我们想访问微信接口,获取其返回信息. 在 ...
随机推荐
- Python,while循环小例子--猜拳游戏(三局二胜)
Python,while循环小例子--猜拳游戏(三局二胜) import random all_choice = ['石头', '剪刀', '布'] prompt = '''(0)石头 (1)剪刀 ( ...
- Linux访问控制列表(Access Control List,简称ACL)
Linux访问控制列表(Access Control List,简称ACL) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.ACL概述 ACL:Access Control L ...
- Zabbix 完整的监控流程
目录 1.Zabbix的监控历程概念 1.1 基本概念 1.2 流程图 2.创建主机并加入主机组 3.添加新加主机的应用集(aplication) 4.添加监控项(item) 5.告警触发器配置(Tr ...
- Kotlin属性引用详解
继续来学习Kotlin反射相关的,这次主要是跟反射属性相关的东东. 属性引用(Property Reference): 属性引用的用法与函数(方法)引用的用法是完全一致,都是通过::形式来引用的.下面 ...
- steam相关插件
批量激活key:https://greasyfork.org/zh-CN/scripts/32718-steamredeemkeys 批量卖卡:https://github.com/Nuklon/St ...
- javascript Object and new object() object --构造函数
- MySQL中去重字段完全相同的数据
思路:创建一个临时表,在原有的表结构基础上增加一列编号,再进行去除重复的记录 本例子是在对表 main_body_sz 进行去重 创建一个临时表 create table main_body_sz_a ...
- Markdwon入门2
插入表情 这里是指广义的表情包,包括表情.物体.动物等. :+1: :smile: :s :scream: :kissing_heart: :yum: :cry: :blush: :frog: :co ...
- 转发: JS中的call()和apply()方法和区别 --小白变色记
一.方法定义: apply:调用一个对象的一个方法,用另一个对象替换当前对象.例如:B.apply(A, arguments);即A对象应用B对象的方法. call:调用一个对象的一个方法,用另一个对 ...
- KM模板 最大权匹配(广搜版) Luogu P1559 运动员最佳匹配问题
KM板题: #include <bits/stdc++.h> using namespace std; inline void read(int &num) { char ch; ...