1、DigitalSign类

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.Signature;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; /**
* 证书加解密/签名/验签类
*/
public class DigitalSign { private static DigitalSign single=null; /** 编码 格式*/
private static String encoding = "UTF-8";
/** 算法 */
private String arithmetic = "SHA1withRSA"; /**私钥缓存**/
private ConcurrentHashMap<String, RSAPrivateCrtKey> map = new ConcurrentHashMap<String, RSAPrivateCrtKey>(); private DigitalSign(String encoding){
} private DigitalSign(){ } /**
* 初始化 实例
*/
public static synchronized void init() {
if (single == null) {
single = new DigitalSign(encoding);
}
} /**
* 初始化 实例
*/
public static synchronized void init(String charset) {
if (single == null) {
single = new DigitalSign();
encoding = charset;
}
} //静态工厂方法
public static DigitalSign getInstance() {
if (single == null) {
init(); //为空的时候同步实例
}
return single;
} //静态工厂方法
public static DigitalSign getInstance(String charset) {
if (single == null) {
init(charset); //为空的时候同步实例
}
return single;
} /**
* 私钥签名
* @param tobeSigned
* @param priKeyPath classpath 下路径
* @param password
* @return
* @throws CryptException
*/
public String SignMsgByRelativePath(final String tobeSigned, final String priKeyPath, final String password) throws CryptException {
RSAPrivateCrtKey priKey = getPriKeyByRelativePath(priKeyPath, password);
return sign(priKey, tobeSigned);
} /**
* 私钥签名
* @param tobeSigned
* @param priKeyStream 私钥文件流
* @param password
* @return
* @throws CryptException
*/
public String SignMsgByInputStream(String tobeSigned,InputStream priKeyStream,String password) throws CryptException{
RSAPrivateCrtKey priKey = getPriKeyByInputStream(priKeyStream, password);
return sign(priKey, tobeSigned);
} /**
* 私钥签名
* @param tobeSigned
* @param priKeyPath 私钥绝对路径
* @param password
* @return
* @throws CryptException
*/
public String signMsgByAbsolutePath(String tobeSigned,String priKeyPath,String password) throws CryptException{
RSAPrivateCrtKey priKey = map.get(priKeyPath);
if(priKey == null){
priKey = getPriKeyByAbsolutePath(priKeyPath, password);
}
return sign(priKey, tobeSigned);
} /**
* 私钥签名
* @param tobeSigned
* @param priKeyPath 私钥绝对路径
* @param password
* @return
* @throws CryptException
*/
public String signMsgByAbsolutePath(Map<String, Object> tobeSigned,String priKeyPath,String password) throws CryptException{
RSAPrivateCrtKey priKey = map.get(priKeyPath);
if(priKey == null){
priKey = getPriKeyByAbsolutePath(priKeyPath, password);
}
return sign(priKey, tobeSigned);
} /**
* 公钥验签
* @param tobeVerfied
* @param plainText
* @param pubKey 文件输入流
* @return
* @throws CryptException
*/
public boolean verifyMsgByInputSteam(String tobeVerfied,String plainText,InputStream pubKey) throws CryptException{
//获取公钥
RSAPublicKey pubkey = getPubKeyByInputSteam(pubKey);
return verify(pubkey, tobeVerfied, plainText);
} /**
* 通过公钥验签
* @param tobeVerified
* @param plainText
* @param pubkeyPath 公钥绝对路径
* @return
* @throws CryptException
*/
public boolean verifyMsgByAbsolutePath(String tobeVerified,String plainText,String pubkeyPath) throws CryptException{
RSAPublicKey pubkey = getPubKeyByAbsolutePath(pubkeyPath);
return verify(pubkey, tobeVerified, plainText);
} /**
* 通过公钥验签
* @param tobeVerified
* @param map
* @param pubkeyPath 公钥绝对路径
* @return
* @throws CryptException
*/
public boolean verifyMsgByAbsolutePath(String tobeVerified,Map<String, Object> map,String pubkeyPath) throws CryptException{
RSAPublicKey pubkey = getPubKeyByAbsolutePath(pubkeyPath);
return verify(pubkey, tobeVerified, map);
} /**
* 公钥验签
* @param tobeVerfied
* @param plainText
* @param CertFile 文件classpath下路径
* @return
* @throws CryptException
*/
public boolean verifyMsgByRelativePath(String tobeVerfied, String plainText, String CertFile) throws CryptException {
RSAPublicKey pubkey = getPubKeyByRelativePath(CertFile);
return verify(pubkey, tobeVerfied, plainText);
} /**
* 使用公钥对数据加密
* @param TobeEncryptMsg 待加密的明文字符串
* @param certFile 公钥路径[相对地址 classpath下]
* @return 加密后的字符串
* @throws CryptException 错误信息
*/
public String encryptMsg(String TobeEncryptMsg, String certFile) throws CryptException {
//获取公钥
RSAPublicKey pubKey = getPubKeyByRelativePath(certFile);
Cipher instance;
try {
instance = Cipher.getInstance(pubKey.getAlgorithm());
instance.init(Cipher.ENCRYPT_MODE, pubKey);
String encryMsg = Base64.encodeBase64String(instance.doFinal(Base64.encodeBase64(TobeEncryptMsg.getBytes(encoding))));
return encryMsg;
} catch (Exception e) {
throw new CryptException("加密失败",e);
}
} /**
* 私钥解密
* @param TobeDecodeMsg 待解密的加密字符串
* @param priFile 私钥路径[相对路径 classpath下]
* @param passWord 私钥密码
* @return 解密后的明文字符串
* @throws CryptException 错误信息
*/
public String decodeMsg(String TobeDecodeMsg, String priFile,
String passWord) throws CryptException{
RSAPrivateCrtKey priKey = getPriKeyByRelativePath(priFile, passWord);
Cipher instance;
try {
instance = Cipher.getInstance(priKey.getAlgorithm());
instance.init(Cipher.DECRYPT_MODE, priKey);
String string = new String(Base64.decodeBase64(instance.doFinal(Base64.decodeBase64(TobeDecodeMsg))), encoding);
return string;
} catch (Exception e) {
throw new CryptException("解密失败",e);
}
} /**
* 获取私钥 文件流
* @param keyfileStream
* @param password
* @return
* @throws CryptException
*/
private RSAPrivateCrtKey getPriKeyByInputStream(InputStream keyfileStream,String password) throws CryptException{
return getPriKey(keyfileStream, password);
} /**
* 通过文件绝对路径加载私钥
* @param priKeyPath 绝对路径
* @param password
* @return
* @throws CryptException
*/
private RSAPrivateCrtKey getPriKeyByAbsolutePath(String priKeyPath,String password) throws CryptException{
FileInputStream file;
try {
file = new FileInputStream(priKeyPath);
} catch (FileNotFoundException e) {
throw new CryptException("秘钥路径不正确",e);
}
RSAPrivateCrtKey priKey = getPriKey(file, password);
map.put(priKeyPath, priKey);
return priKey;
} /**
* 获取私钥 [classpath]
* @param KeyFile
* @param passWord
* @return
*/
private RSAPrivateCrtKey getPriKeyByRelativePath(String KeyFile,String passWord) throws CryptException{
//获取项目 相对路径
ClassLoader cl = DigitalSign.class.getClassLoader();
InputStream fiKeyFile = cl.getResourceAsStream(KeyFile);
return getPriKey(fiKeyFile, passWord);
} /**
* 获取公钥 [文件输入流]
* @param pubKey
* @return
* @throws CryptException
*/
private RSAPublicKey getPubKeyByInputSteam(InputStream pubKey) throws CryptException{
return getPublicKey(pubKey);
} /**
* 获取公钥 [classpath下]
* @param CertFile
* @return
*/
private RSAPublicKey getPubKeyByRelativePath(String CertFile) throws CryptException{
//读取公钥文件
ClassLoader cl = DigitalSign.class.getClassLoader();
InputStream certfile = cl.getResourceAsStream(CertFile);
//获取公钥
return getPublicKey(certfile);
} /**
* 获取公钥 通过绝对路径
* @param pubKeyPath
* @return
* @throws CryptException
*/
private RSAPublicKey getPubKeyByAbsolutePath(String pubKeyPath) throws CryptException{
try{
FileInputStream pubKey = new FileInputStream(pubKeyPath);
return getPublicKey(pubKey);
}catch(Exception e){
throw new CryptException("文件读取失败",e);
}
} /**
* 获取公钥
* @param pubKey 公钥流
* @return
* @throws CryptException
*/
private RSAPublicKey getPublicKey(InputStream pubKey) throws CryptException{
X509Certificate x509cert = null;
try {
//实例化 x509
CertificateFactory cf = CertificateFactory.getInstance("X.509");
x509cert = (X509Certificate) cf.generateCertificate(pubKey);
} catch (CertificateException e) {
if (pubKey != null){
try {
pubKey.close();
} catch (IOException e1) {
throw new CryptException("文件流关闭异常",e1);
}
}
throw new CryptException("初始化公钥异常",e);
}
//读取公钥
RSAPublicKey pubkey = (RSAPublicKey) x509cert.getPublicKey();
return pubkey;
} /**
* 获取私钥
* @param priKey
* @param keyPassword
* @return
* @throws CryptException
*/
private RSAPrivateCrtKey getPriKey(InputStream priKey,String keyPassword) throws CryptException{
String keyAlias = null;
RSAPrivateCrtKey prikey = null;
try {
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(priKey, keyPassword.toCharArray()); Enumeration<?> myEnum = ks.aliases();
while (myEnum.hasMoreElements()) {
keyAlias = (String) myEnum.nextElement();
if (ks.isKeyEntry(keyAlias)) {
prikey = (RSAPrivateCrtKey) ks.getKey(keyAlias, keyPassword.toCharArray());
break;
}
}
} catch (Exception e) {
if (priKey != null){
try {
priKey.close();
} catch (IOException e1) {
throw new CryptException("流关闭异常",e1);
}
}
throw new CryptException("加载私钥失败",e);
} if(prikey == null){
throw new CryptException("私钥不存在");
} return prikey;
} /**
* 签名
* @param priKey 私钥
* @param tobeSigned 待签字符串
* @return 签名结果
* @throws CryptException
*/
private String sign(RSAPrivateCrtKey priKey,String tobeSigned) throws CryptException{
try {
Signature sign = Signature.getInstance(arithmetic);
sign.initSign(priKey);
sign.update(tobeSigned.getBytes(encoding));
byte signed[] = sign.sign();
// byte sign_asc[] = new byte[signed.length * 2];
// Hex2Ascii(signed.length, signed, sign_asc); // return new String(signed,encoding);
return Base64.encodeBase64String(signed).replaceAll("\\+", "%2B");
} catch (Exception e) {
throw new CryptException("签名失败",e);
}
} /**
* 签名
* @param priKey 私钥
* @param map 待签字符串
* @return 签名结果
* @throws CryptException
*/
private String sign(RSAPrivateCrtKey priKey,Map<String, Object> map) throws CryptException{
try {
String tobeSigned = appendMap(map);
Signature sign = Signature.getInstance(arithmetic);
sign.initSign(priKey);
sign.update(tobeSigned.getBytes(encoding));
byte signed[] = sign.sign();
// byte sign_asc[] = new byte[signed.length * 2];
// Hex2Ascii(signed.length, signed, sign_asc); // return new String(signed,encoding);
return Base64.encodeBase64String(signed).replaceAll("\\+", "%2B");
} catch (Exception e) {
throw new CryptException("签名失败",e);
}
} /**
* 连接参数
* @param map
* @return
*/
private static String appendMap(Map<String, Object> map){
Set<String> keySet = map.keySet();
StringBuilder sb = new StringBuilder();
for (String mapKey : keySet){
String value = (String)map.get(mapKey);
sb.append(mapKey).append("=").append(value).append("&");
}
return sb.toString();
} /**
* 验证签名
* @param pubkey 公钥
* @param tobeVerfied 已签名字符串
* @param plainText 待校验字符串
* @return true || false
* @throws CryptException
*/
private boolean verify(RSAPublicKey pubkey,String tobeVerfied,String plainText) throws CryptException{
try {
Signature verify = Signature.getInstance(arithmetic);
verify.initVerify(pubkey);
// byte signeddata[] = new byte[tobeVerfied.length() / 2];
// Ascii2Hex(tobeVerfied.length(), tobeVerfied.getBytes(encoding), signeddata);
verify.update(plainText.getBytes(encoding)); return verify.verify(Base64.decodeBase64(tobeVerfied.replaceAll("%2B", "\\+")));
} catch (Exception e) {
throw new CryptException("验签失败",e);
}
} /**
* 验证签名
* @param pubkey 公钥
* @param tobeVerfied 已经签名的map
* @param map 待校验的map
* @return true || false
* @throws CryptException
*/
private boolean verify(RSAPublicKey pubkey,String tobeVerfied,Map<String, Object> map) throws CryptException{
try {
String plainText = appendMap(map);
Signature verify = Signature.getInstance(arithmetic);
verify.initVerify(pubkey);
// byte signeddata[] = new byte[tobeVerfied.length() / 2];
// Ascii2Hex(tobeVerfied.length(), tobeVerfied.getBytes(encoding), signeddata);
verify.update(plainText.getBytes(encoding)); return verify.verify(Base64.decodeBase64(tobeVerfied.replaceAll("%2B", "\\+")));
} catch (Exception e) {
throw new CryptException("验签失败",e);
}
}
}

2、CryptException异常类


/**
* 密钥异常类
*/
public class CryptException extends Exception{ private static final long serialVersionUID = 2843021655596315128L; public CryptException(String message){
super(message);
} public CryptException(String message, Throwable cause) {
super(message, cause);
} public CryptException(Throwable cause) {
super(cause);
}
}

3、加签示例

Map<String, String> map = new TreeMap<String, String>();
//....省略map put值...
String sign = DigitalSign.getInstance().signMsgByAbsolutePath(map, path,
password);
map.put("sign", sign);

4、验签示例

map.remove("sign");
DigitalSign digitalSign = DigitalSign.getInstance();
boolean result = digitalSign.verifyMsgByAbsolutePath(sign, params, merchCertPath);

RSA签名和验签Util的更多相关文章

  1. Delphi RSA签名与验签【支持SHA1WithRSA(RSA1)、SHA256WithRSA(RSA2)和MD5WithRSA签名与验签】

    作者QQ:(648437169) 点击下载➨ RSA签名与验签 [delphi RSA签名与验签]支持3种方式签名与验签(SHA1WithRSA(RSA1).SHA256WithRSA(RSA2)和M ...

  2. erlang的RSA签名与验签

    1.RSA介绍 RSA是目前最有影响力的公钥加密算法,该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对 其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥,即公钥,而 ...

  3. .Net C# RSA签名和验签

    帮助类 using System; using System.Text; using System.IO; using System.Security.Cryptography; namespace ...

  4. java/php/c#版rsa签名以及验签实现

    本文为转载,请转载请注明地址: 原文地址为        http://xw-z1985.iteye.com/blog/1837376 在开放平台领域,需要给isv提供sdk,签名是Sdk中需要提供的 ...

  5. .NET Core RSA 签名和验签(密钥为 16 进制编码)

    使用 OpenSSL 生成公私钥对,命令: $ openssl genrsa -out rsa_1024_priv.pem $ openssl pkcs8 -topk8 -inform PEM -in ...

  6. .Net C# RSA签名和验签重写

    namespace com._80community.unittest.CUP { /// <summary> /// CUP Client /// </summary> pu ...

  7. RSA签名、验签、加密、解密

    最近在做一个项目,与一个支付渠道进行连接进行充值,为了安全,每个接口访问时,都要先登陆(调用登陆接口),拿到一个sessionKey,后续业务接口内容用它来进行3DES加密处理.而登陆需要用到RSA进 ...

  8. RSA后台签名前台验签的应用(前台采用jsrsasign库)

    写在前面 安全测试需要, 为防止后台响应数据返给前台过程中被篡改前台再拿被篡改后的数据进行接下来的操作影响正常业务, 决定采用RSA对响应数据进行签名和验签, 于是有了这篇<RSA后台签名前台验 ...

  9. RSA/RSA2 进行签名和验签

    package com.byttersoft.hibernate.erp.szmy.util; import java.io.ByteArrayInputStream; import java.io. ...

随机推荐

  1. k8s日志收集方案

    k8s日志收集方案 三种收集方案的优缺点: 下面我们就实践第二种日志收集方案: 一.安装ELK 下面直接采用yum的方式安装ELK(源码包安装参考:https://www.cnblogs.com/De ...

  2. 啥?客户叫在DataGridView的左上角添加CheckBox?

    效果图是这样的,如何把CheckBox放到左上角是最重要的. 添加方法 InitColumnInfo() 方法,代码如下. private void InitColumnInfo() { ; Data ...

  3. Java工程师修炼之路(校招总结)

    Java工程师修炼之路(校招总结) 前言 在下本是跨专业渣考研的985渣硕一枚,经历研究生两年的学习积累,有幸于2019秋季招聘中拿到几个公司的研发岗offer,包括百度,阿里,腾讯,今日头条,网易, ...

  4. 海思Hi3559A/CV100 DDR4驱动配置手册

    Hi3559AV100 DDR4 驱动配置说明 1.1 Hi3559AV100 DDR4 CLK/AC 驱动配置方法 寄存器地址 DDR PHY0:0x1206d0bc DDR PHY1:0x1206 ...

  5. 一次apk打开时报内存溢出错误,故写下内存溢出的各种原因和解决方法

    原转载:https://blog.csdn.net/cp_panda_5/article/details/79613870 正文内容: 对于JVM的内存写过的文章已经有点多了,而且有点烂了,不过说那么 ...

  6. CVE-2019-0686|Microsoft Exchange特权提升漏洞补丁已发布

    Microsoft Exchange Server中存在一个特权提升漏洞.成功利用此漏洞的攻击者可以获得与Exchange服务器的任何其他用户相同的权限.这可能允许攻击者执行诸如访问其他用户的邮箱之类 ...

  7. mapbox.gl源码解析——基本架构与数据渲染流程

    加载地图 Mapbox GL JS是一个JavaScript库,使用WebGL渲染交互式矢量瓦片地图和栅格瓦片地图.WebGL渲染意味着高性能,MapboxGL能够渲染大量的地图要素,拥有流畅的交互以 ...

  8. markdown用法

    Markdown 语法的目标是成为一种适用于网络的书写语言.不在 Markdown 涵盖范围之内的标签,都可以直接在文档里面用 HTML 撰写.不需要额外标注,只要直接加标签就可以了. 一.常用部分 ...

  9. Oracle11g创建表空间、创建用户、角色授权、导入导出表以及中文字符乱码问题

    [转载]原文地址:https://www.cnblogs.com/bjh1117/p/6605037.html 前提:本机已经安装了Oracle11g数据库. 需求:使用PL SQL数据库连接工具操作 ...

  10. 经典排序算法 — C#版本(中)

    归并排序比较适合大规模得数据排序,借鉴了分治思想. 归并排序原理 自古以来,分久必合合久必分. 我们可以这样理解归并排序,分-分到不能分为止,然后合并. 使用递归将问题一点一点分解,最后进行合并. 分 ...