#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. 九九乘法表的python复习

    九九开始的复习 这周复习之前的学的知识关于range函数,gormat函数,print的使用总结一下 从一个小例子开始,开始我的回顾吧, 大家都是从那个九九乘法表开始的数学之旅,从一一得一,开始了我们 ...

  2. Python 3 利用 Dlib 实现摄像头实时人脸检测和平铺显示

    1. 引言 在某些场景下,我们不仅需要进行实时人脸检测追踪,还要进行再加工:这里进行摄像头实时人脸检测,并对于实时检测的人脸进行初步提取: 单个/多个人脸检测,并依次在摄像头窗口,实时平铺显示检测到的 ...

  3. Redis源码阅读(一)事件机制

    Redis源码阅读(一)事件机制 Redis作为一款NoSQL非关系内存数据库,具有很高的读写性能,且原生支持的数据类型丰富,被广泛的作为缓存.分布式数据库.消息队列等应用.此外Redis还有许多高可 ...

  4. CentOS 7 安装图形化界面及 Xshell 连接

    CentOS 比较适合用作服务器的系统,之前用过 CentOS 6,但是在配置 Nginx 的时候,发现很多语句版本7的系统都进行了更新,而且网上针对版本7的例子会更多一下,遂将系统换成版本7. 下载 ...

  5. [转载]GB2312简体中文编码表

    编码表源地址:http://www.knowsky.com/resource/gb2312tbl.htm编码在线查询:http://www.qqxiuzi.cn/bianma/zifuji.phpGB ...

  6. 3.控制hive map reduce个数

    参考: https://blog.csdn.net/wuliusir/article/details/45010129 https://blog.csdn.net/zhong_han_jun/arti ...

  7. oracle和mysql对时间与字符串的转换

    1,oracle to_date(#{item.value},'YYYY-MM-DD hh24-mi-ss') to_char(CRERATE_TIME,'YYYY-MM-DD hh24-mi-ss' ...

  8. OO的第一次死亡

    久仰OO大名,总是想着提前做点准备,其实到头来还是什么准备都没有做,所以这学期就是从零开始的面向对象生活,也因此遇到了很多的问题. 第一次作业——多项式加减 第一次作业历来是较为简单的,但是对于面向对 ...

  9. JAVA第二次试验

    北京电子科技学院(BESTI) 实     验    报     告 课程:Java程序设计 班级:1352  姓名:潘俊洋  学号:20135230 成绩:             指导教师:娄嘉鹏 ...

  10. android随机运算器开发小结1

    想到第一天自己写了一个简单的四则运算程序的情景:我便想起了引起我们不断迭代开发的程序背景是:二柱子接受老师安排的给孩子出题的任务,每次需要给孩子设置出题任务,生成相应的小学运算题目,所以我们面对的需求 ...