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请求,获取到数据,而不是直接从浏览器输入请求网址获得相应.比如我们想访问微信接口,获取其返回信息. 在 ...
随机推荐
- Linux IO 概念(1)
基础概念 文件描述fd 文件描述符(file description),用于表述指向文件引用的抽象话题概念 文件描述符在形式上是一个非负整数,实际上它是一个索引值,指向内核为每一个进程所维护的该进程打 ...
- wget详解
wget命令用来从指定的URL下载文件.wget非常稳定,它在带宽很窄的情况下和不稳定网络中有很强的适应性,如果是由于网络的原因下载失败,wget会不断的尝试,直到整个文件下载完毕.如果是服务器打断下 ...
- 百度语音合成api/sdk及demo
1.流程 1)换取token 用Api Key 和 SecretKey.访问https://openapi.baidu.com/oauth/2.0/token 换取 token // appKey = ...
- [LeetCode] 0200. Number of Islands 岛屿的个数
题目 Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is su ...
- python测试开发django-rest-framework-60.使用token登录(authentication之TokenAuthentication)
前言 现在很多接口项目在登录的时候返回一个token,登录后的拿着这个token去访问访问登录之后的请求. 本篇使用djangorestframework框架写一个登陆的接口,登录成功后返回token ...
- 独角兽估值30亿美金,我们聊聊RPA是什么
https://www.jianshu.com/p/397ecd238ffc 缩短法定工作时间,已成国际劳动立法趋势,全球政府都曾面对这样的议题,过往企业IT也在思考这件事,开发出更好的软件系统帮助员 ...
- STM32L4R9使用HAL库调试IIC注意事项
STM32使用Cubemx生成的代码中,用到IIC的驱动,但是始终不能读写,因此使用逻辑分析仪,发现原本地址为0x58的写成了0x20,因此肯定是地址错了.因此,总结如下: 1.需要逻辑分析仪分析II ...
- python的信号管理
if __name__ == '__main__': # Make it possible to exit application with ctrl+c on console signal.sign ...
- area标签的使用,图片中某一个部分可以点击跳转,太阳系中点击某个行星查看具体信息
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- springcloud(二)
springcloud路由网关 一.什么是网关 Zuul的主要功能是路由转发和过滤器.路由功能是微服务的一部分,比如/api/user转发到到user服务,/api/shop转发到到shop服务.zu ...