#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. move.js运动插件

    move.js 运动插件是一款针对元素动画效果的插件.可以运用此插件制作出各类元素效果. 插件GitHub地址:https://github.com/visionmedia/move.js 下面整理学 ...

  2. 正确配置 debian squeeze apt 源

    本想在 Debian Squeeze 上安装一些依赖,没想到刚执行 apt-get update ,就出现这样的错误信息. W: GPG error: http://mirrors.163.com s ...

  3. Streamr助你掌控自己的数据(3)——教你在Streamr市场上发布数据

    博客说明 所有刊发内容均可转载但是需要注明出处. 教你在Streamr市场上发布数据 本系列文档主要介绍怎么通过Streamr管理自己的DATA,整个系列包括三篇教程文档,分别是:教你5分钟上传数据至 ...

  4. 第十一次ScrumMeeting博客

    第十一次ScrumMeeting博客 本次会议于11月29日(三)22时整在3公寓725房间召开,持续30分钟. 与会人员:刘畅.辛德泰张安澜.赵奕.方科栋. 1. 每个人的工作(有Issue的内容和 ...

  5. Linux 做网关

    首先创建两张路由表,只需要添加到相应的文件中即可,Linux一共支持255个路由表,rt_tables文件中默认已经存在了三张路由表,分别是:   255  local   254  main   2 ...

  6. 苏宁笔试:UML类图中的关系

    1. 依赖 2. 关联 3. 聚合 4. 组合 5. 泛化 6. 实现

  7. WebService有什么用?

    入门之前先简单介绍下WCF.在用WebService做开发时,很多人都不知道WCF和WebService之间的关系.实际上WCF包含了WebService,这是一个很强悍的通信技术应用框架.微软把.N ...

  8. 提交内容到版本库:git commit

  9. 图论 Kruskal算法 并查集

    #include<iostream> #include<cstring> #include<string> #include<cstdio> #incl ...

  10. Android界面设计适配不同屏幕的尺寸和密度解读

    Android是运行在各种提供不同的屏幕尺寸和密度的设备.Android系统提供跨设备的统一开发环境和处理大部分的工作,以调整每个应用程序的用户界面,以在其上显示的画面. 同时,该系统提供了API,允 ...