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请求,获取到数据,而不是直接从浏览器输入请求网址获得相应.比如我们想访问微信接口,获取其返回信息. 在 ...
随机推荐
- HTML&CSS基础-标签的属性
HTML&CSS基础-标签的属性 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.html源代码 <!-- html 根标签,一个页面中有且只有一个根标签,网页中的 ...
- 在Windows下/Linux下安装jdk版本
到官网https://www.oracle.com/technetwork/java/javase/downloads/index.html选择适合自己的版本, 目前我做测试和开发主要用的是jdk 8 ...
- linux用户的问题
最近在开发的时候遇到一个问题: 我在某个项目下的某个文件夹内写了一个可以单独run的A.py文件,这个文件里面的代码可以调用kubernetes的python接口来请求kubernetes上的信息(比 ...
- ZOJ - 3265: Strange Game (优化 二分图匹配)
pro:有一个长度为N的数组a[i],要求选择k[i]>0,使得b[i]=a[i]^k[i]%M中出现的不同数最多.N<=200, M<=1e9: sol:a^x%p的个数的有限的, ...
- git提交项目到已有库
借鉴地址:https://blog.csdn.net/jerryhanjj/article/details/72777618 Git global setup git config --global ...
- vscode——常用插件记录
前言 本人vscode中使用的插件列表,记录下. 列表 Auto Rename Tag 自动重命名成对的超文本标记语言/可扩展标记语言 background-cover 为vscode设置背景图片 C ...
- Dubbo源码分析:Serialization
背景 顺序化逻缉处理! 类图 获取Serialization对象时序图 序列化
- Spark Partition
分区的意义 Spark RDD 是一种分布式的数据集,由于数据量很大,因此它被切分成不同分区并存储在各个Worker节点的内存中.从而当我们对RDD进行操作时,实际上是对每个分区中的数据并行操作.Sp ...
- Task 使用方法
Task的使用方法 1. 调用无参数.无返回值方法 private void button1_Click(object sender, EventArgs e) { Task task = new T ...
- LeetCode 1049. Last Stone Weight II
原题链接在这里:https://leetcode.com/problems/last-stone-weight-ii/ 题目: We have a collection of rocks, each ...