#region CerRsaSignature 根据私钥签名
/// <summary>
/// 根据私钥串签名
/// </summary>
/// <param name="plainText">待签名的明文</param>
/// <param name="prikeyPath">私钥证书路径</param>
/// <param name="prikeyPassword">私钥证书密码</param>
/// <param name="urid">签名uri</param>
/// <returns></returns>
public static ReturnValue CerRsaSignature(string prikeyPath, string prikeyPassword, string plainText,string urid)
{
ReturnValue retValue = new ReturnValue();
try
{
X509Certificate2 x509_Cer1 = new X509Certificate2(prikeyPath, prikeyPassword, X509KeyStorageFlags.Exportable);
string key = x509_Cer1.PrivateKey.ToXmlString(true);
ReturnValue signValue = CreateSign(plainText, urid, key);
//签名失败
if (signValue.HasError)
{
retValue.HasError = true;
retValue.Message = "签名失败";
return retValue;
}
retValue.HasError = signValue.HasError;
retValue.Message = signValue.Message;
return retValue;
}
catch (Exception ex)
{
retValue.HasError = true;
retValue.Message = "签名异常" + ex.Message;
log.WarnFormat("创建签名失败,签名数据:{0},错误原因:{1}", plainText, ex);
return retValue;
}
}

/// <summary>
/// 根据私钥证书XML串创建签名
/// </summary>
/// <param name="privateKey">私钥证书XML串</param>
/// <param name="plainText">待签名的明文</param>
/// <param name="urid">签名uri</param>
/// <returns></returns>
public static ReturnValue CerRsaSignature(string privateKey, string plainText, string urid)
{
ReturnValue retValue = new ReturnValue();
try
{
ReturnValue signValue = CreateSign(plainText, urid, privateKey);
//签名失败
if (signValue.HasError)
{
retValue.HasError = true;
retValue.Message = "签名失败";
return retValue;
}
retValue.HasError = signValue.HasError;
retValue.Message = signValue.Message;
return retValue;
}
catch (Exception ex)
{
retValue.HasError = true;
retValue.Message = "签名异常" + ex.Message;
log.WarnFormat("创建签名失败,签名数据:{0},错误原因:{1}", plainText, ex);
return retValue;
}
}

/// <summary>
/// 创建签名
/// </summary>
/// <param name="plainText"></param>
/// <param name="urid"></param>
/// <param name="key"></param>
/// <returns></returns>
private static ReturnValue CreateSign(string plainText, string urid, string key)
{
XmlDocument doc = new XmlDocument();
////创建CspParameters 对象并将私钥放入密钥容器中
//CspParameters cspParams = new CspParameters();
//cspParams.KeyContainerName = key;

// 创建一个新的RSA签名密钥并将其保存在容器。
RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider();
rsaKey.FromXmlString(key);
// 创建一个新的XML文档。
XmlDocument xmlDoc = new XmlDocument();

//将plainText加载到XmlDocument对象中。
xmlDoc.PreserveWhitespace = true;
xmlDoc.LoadXml(plainText);
// XML文档签名。
ReturnValue signValue = SignXml(xmlDoc, rsaKey, urid);
return signValue;
}

/// <summary>
/// 计算签名
/// </summary>
/// <param name="xmlDoc"></param>
/// <param name="Key"></param>
/// <param name="urid"></param>
/// <returns></returns>
private static ReturnValue SignXml(XmlDocument xmlDoc, RSA Key,string urid)
{
ReturnValue retValue = new ReturnValue();
//检查参数。
if (xmlDoc == null)
{
retValue.HasError = true;
retValue.Message = "签名XML为空";
return retValue;
}
if (Key == null)
{
retValue.HasError = true;
retValue.Message = "签名Key为空";
return retValue;
}
try
{

// 创建一个signedxml对象
SignedXml signedXml = new SignedXml(xmlDoc);
//添加添加到SignedXml的密钥
signedXml.SigningKey = Key;

////指定标准化:http://www.w3.org/TR/2001/REC-xml-c14n-20010315
//signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigC14NTransformUrl;

////指定签名方法:rsa-sha1
//signedXml.SignedInfo.SignatureMethod = SignedXml.XmlDsigRSASHA1Url;
string uri = "#" + urid;
// 创建一个引用来签名
Reference reference = new Reference();
reference.Uri = uri;
//指定Signature标签与原xml报文的组装方式:enveloped
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(env);
// 添加到SignedXml对象添加参考。
signedXml.AddReference(reference);
// 计算签名
signedXml.ComputeSignature();
// 得到签名的XML表示形式
XmlElement xmlDigitalSignature = signedXml.GetXml();
//xmlDigitalSignature.Prefix = "ds";
//SetPrefix("ds", xmlDigitalSignature);
//添加元素的XML文档。
xmlDoc.DocumentElement.LastChild.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
//把签名加入到文档中
//xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
//获取SignatureValue标签的值,然后每76个字节增加一个换行
string signatureValue = xmlDoc.GetElementsByTagName("SignatureValue").Item(0).InnerText;

//设置xml文档中的SignatureValue标签的值
xmlDoc.GetElementsByTagName("SignatureValue").Item(0).InnerText = splitPer76AddLineBreak(signatureValue);
retValue.HasError = false;
retValue.Message = xmlDoc.OuterXml;
return retValue;

}
catch (Exception ex)
{
log.WarnFormat("创建签名失败,签名原文:{0},签名私钥:{1},错误原因:{2}", xmlDoc.InnerXml, Key.ToXmlString(true), ex.Message);
retValue.HasError = true;
retValue.Message = "创建签名异常";
return retValue;
}

}

#endregion

/// <summary>
/// 私有方法
/// </summary>
/// <param name="prefix"></param>
/// <param name="node"></param>
private static void SetPrefix(String prefix, XmlNode node)
{
foreach (XmlNode n in node.ChildNodes)
{
SetPrefix(prefix, n);
n.Prefix = prefix;
}
}

/// <summary>
/// 对数据每76个字节增加一个换行符
/// </summary>
/// <param name="message">待添加换行符的数据</param>
/// <returns>添加换行符后的数据</returns>
private static string splitPer76AddLineBreak(string message)
{

//存储带有换行符的结果
StringBuilder sb = new StringBuilder();

//循环次数
int count = 0;

if (message.Length % 76 == 0)
{
count = message.Length / 76;
}
else
{
count = message.Length / 76 + 1;
}

//截取字符串之后,还剩下没有截取的长度
int length = message.Length;

for (int i = 0; i < count; i++)
{

//待截取的长度大于76时,增加换行符
if (length > 76)
{
sb.AppendLine(message.Substring(i * 76, 76));
}
else
{//不大于76,说明是最后一段
sb.Append(message.Substring(i * 76));
break;
}
length = message.Length - ((i + 1) * 76);
}

return sb.ToString();

}

#region 验签方法
/// <summary>
/// 根据公钥对返回数据进行验签
/// </summary>
/// <param name="pubKeyPath">公钥路径</param>
/// <param name="data">需要验签的数据</param>
/// <returns></returns>
public static ReturnValue VerifyXmlDoc(string pubKeyPath, string data)
{
ReturnValue retValue = new ReturnValue();
//创建XML对象
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.PreserveWhitespace = true;
try
{
//将数据加载到XML对象中
xmlDoc.LoadXml(data);
//读取公钥串
X509Certificate2 x509_Cer2 = new X509Certificate2(pubKeyPath);
string publicKey = x509_Cer2.PublicKey.Key.ToXmlString(false);
bool verify = VerifyXML(xmlDoc, publicKey);
if (verify)
{
retValue.HasError = false;
retValue.Message = "验签成功";
}
else
{
retValue.HasError = true;
retValue.Message = "验签失败";
}
return retValue;
}
catch (Exception ex)
{
log.WarnFormat("验签异常:{0},银行返回数据:{1}", ex.Message, data);
retValue.HasError = true;
retValue.Message = "验签异常:" + ex.Message;
return retValue;
}

}
/// <summary>
/// 根据公钥证书XML串验证签名
/// </summary>
/// <param name="publicKey"></param>
/// <param name="xmlDoc"></param>
/// <returns></returns>
public static ReturnValue VerifyXmlDoc(string publicKey, XmlDocument xmlDoc)
{
ReturnValue retValue = new ReturnValue();
try
{
bool verify = VerifyXML(xmlDoc, publicKey);
if (verify)
{
retValue.HasError = false;
retValue.Message = "验签成功";
}
else
{
retValue.HasError = true;
retValue.Message = "验签失败";
}
return retValue;
}
catch (Exception ex)
{
log.WarnFormat("验签异常:{0},银行返回数据:{1}", ex.Message, xmlDoc);
retValue.HasError = true;
retValue.Message = "验签异常:" + ex.Message;
return retValue;
}
}
/// <summary>
/// 验证XmlDocument
/// </summary>
/// <param name="xmlDoc"></param>
/// <param name="pubilcKey"></param>
/// <returns></returns>
private static bool VerifyXML(XmlDocument xmlDoc, string pubilcKey)
{
//创建加密服务提供者对象

RSACryptoServiceProvider csp = new RSACryptoServiceProvider();

//由通过 XML 字符串重新构造加密服务提供者对象

csp.FromXmlString(pubilcKey);

//创建XML签名对象

SignedXml sxml = new SignedXml(xmlDoc);

//得到签名元素的节点

XmlNode dsig = xmlDoc.GetElementsByTagName("Signature",

SignedXml.XmlDsigNamespaceUrl)[0];

sxml.LoadXml((XmlElement)dsig);

//验证签名是否正确,并且返回结果

bool verify = sxml.CheckSignature(csp);
return verify;
}
#endregion

SHA1WithRSA签名 规范化标准签名的更多相关文章

  1. Android签名机制之---签名过程详解

    http://www.2cto.com/kf/201512/455388.html 一.前言 又是过了好长时间,没写文章的双手都有点难受了.今天是圣诞节,还是得上班.因为前几天有一个之前的同事,在申请 ...

  2. iOS使用Security.framework进行RSA 加密解密签名和验证签名

    iOS 上 Security.framework为我们提供了安全方面相关的api: Security框架提供的RSA在iOS上使用的一些小结 支持的RSA keySize 大小有:512,768,10 ...

  3. 为App签名(为apk签名)

    为App签名(为apk签名) 原文地址 这篇文章是Android开发人员的必备知识,是我特别为大家整理和总结的,不求完美,但是有用. 1.签名的意义 为了保证每个应用程序开发商合法ID,防止部分开放商 ...

  4. Android 签名(7)签名常见问题,debug签名和release签名的区别等

    一般在安装时提示出错:INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES 1) 两个应用,名字相同,签名不同 2) 升级时前一版本签名,后一版本没签名 3) ...

  5. 解决postman环境切换,自动获取api签名时间及签名

    postman调试api接口时,常遇到两个问题: 1.环境分为开发环境,测试环境,正式环境,如何只写一个接口,通过切换postman环境来实现不同环境的接口调用? 2. api接口请求时往往会添加,来 ...

  6. openssl生成签名与验证签名

    继上一篇RSA对传输信息进行加密解密,再写个生成签名和验证签名. 一般,安全考虑,比如接入支付平台时,请求方和接收方要互相验证是否是你,就用签名来看. 签名方式一般两种,对称加密和非对称加密.对称加密 ...

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

    先说下RSA概率: 公钥和私钥是通过本地openssl软件生成. 正常: 公钥加密=>私钥解密: 私钥签名=>公钥校验签名 最近做一个项目,对方用java公钥去校验签名,这边java的De ...

  8. Mac App Store应用签名和pkg签名(必须签名后才能销售)

    App签名 只有用苹果颁发的证书签名的应用才能在App Store上进行销售,所以我们开发的应用必须打上签名. 签名有两种方式,一是使用Xcode,在配置里面设置签名,编译出来的app就有了签名:二是 ...

  9. Mac App Store应用签名和pkg签名,查看签名

    App签名 只有用苹果颁发的证书签名的应用才能在App Store上进行销售,所以我们开发的应用必须打上签名. 签名有两种方式,一是使用Xcode,在配置里面设置签名,编译出来的app就有了签名:二是 ...

随机推荐

  1. NAT概念解释(不完全版,但不会搞错...)

    NAT在计算器网络中,网络地址转换(Network Address Translation,缩写为NAT),也叫做网络掩蔽或者IP掩蔽(IP masquerading)是一种IP数据包在通过路由器或防 ...

  2. Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第3节: recycler的使用和创建

    Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第三节: recycler的使用和创建   这一小节开始学习recycler相关的知识, recycler是n ...

  3. NodeJS http模块

    Node.js提供了http模块,用于搭建HTTP服务端和客户端. 创建Web服务器 /** * node-http 服务端 */ let http = require('http'); let ur ...

  4. 安装macOS Sierra后怎么找回“任何来源”选项

    安装macOS Sierra后,会发现系统偏好设置的“安全与隐私”中默认已经去除了允许“任何来源”App的选项,无法运行一些第三方应用(提示xx.app已经损坏).如果需要恢复允许“任何来源”的选项, ...

  5. 【quickhybrid】Android端的项目实现

    前言 前文中就有提到,Hybrid模式的核心就是在原生,而本文就以此项目的Android部分为例介绍Android部分的实现. 提示,由于各种各样的原因,本项目中的Android容器确保核心交互以及部 ...

  6. Thunder-Final冲刺中间产物-2017秋-软件工程第十二次作业

    Thunder-Final发布中间产物(WBS&PSP) WBS: 分解方式:按照「爱阅」阅读器的实施过程分解 使用工具:visio 2013 PSP: PSP 预期时间 Planning 计 ...

  7. 实验三:敏捷开发与XP实践

    Java实验三报告 一.   实验内容 (一)敏捷开发与XP 内容:1.敏捷开发(Agile Development)是一种以人为核心.迭代.循序渐进的开发方法. 2.极限编程(eXtreme Pro ...

  8. Task 6.1 校友聊之NABCD模型分析

    我们团队开发的一款软件是“校友聊”--一个在局域网内免流量进行文字.语音.视频聊天的软件.下面将对此进行NABCD的模型分析. N(Need需求):现如今,随着网络的迅速普及,手机和电脑已经成为每个大 ...

  9. 编写了几个Java类,但是一直运行某一个class,这种是因为:main方法写错

    编写了几个Java类,但是一直运行某一个class,这种是因为:main方法写错

  10. 关于mybatis的思考(2)——mybatis映射文件的深入理解

    1.配置文件 mybatis进行持久化操作是以SqlSessionFactory对象为基础的,这个对象是整个数据库映射关系经过编译后的内存镜像. InputStream inputStream = R ...