• SHA1WithRSA签名 规范化标准签名


    #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

  • 相关阅读:
    NOI2013
    【FINAL】NOI
    【jsoi】第一季 [略]精简题解
    浏览器缓存机制--小总结
    UC和QQ两个主流浏览器 * 点击触发微信分享到朋友圈或发送给朋友的功能(转载)
    webpack加载postcss,以及autoprefixer的loader
    HTTP协议中的短轮询、长轮询、长连接和短连接,看到一篇文章有感
    webpack2.0 css文件引入错误解决及图片输出在根目录配置问题
    webpack+vue 我的视角(持续更新)
    手机端图像编辑上传-cropper
  • 原文地址:https://www.cnblogs.com/xinwuhen/p/5420640.html
Copyright © 2020-2023  润新知