.NET使用PFX文件签名XML文档

一个人如果下决心要成为什么样的人,或者下决心要做成什么样的事,那么,意志或者说动机的驱动力会使他心想事成,如愿以偿。


Program.cs代码:

class Program
    {
        static void Main(string[] args)
        {
            #region 1 - 加载XML文档
            var xmlDoc = new XmlDocument();
            xmlDoc.Load(XmlFile);
            #endregion

            #region 2 - 读取证书文件
            var fs = new FileStream(CertificateFile, FileMode.Open);
            var certBytes = new byte[fs.Length];
            fs.Read(certBytes, 0, (Int32)fs.Length);
            fs.Close();
            var cert = new X509Certificate2(certBytes);
            #endregion

            #region 3 - 签署xml文档
            string signedXmlData = GetSignedXml(xmlDoc, cert);
            #endregion

            #region 4 - 根据证书验证签名的xml
            bool isValid = Validate(signedXmlData, CertificateFile);
            System.Console.WriteLine("Signed data validated: {0}", isValid);
            #endregion

            Console.ReadKey();
        }

        //公钥加密技术12号标准(Public Key Cryptography Standards #12,PKCS#12)为存储和传输用户或服务器私钥、公钥和证书指定了一个可移植的格式。
        public static string CertificateFile { get { return string.Format("{0}\\{1}\\{2}", Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Data", "certificate.pfx"); } }
        public static string XmlFile { get { return string.Format("{0}\\{1}\\{2}", Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Data", "sample.xml"); } }
        public static string GetSignedXml(XmlDocument xmlDocument, X509Certificate2 certificate)
        {
            var signedXml = new SignedXml(xmlDocument);
            signedXml.SigningKey = certificate.PrivateKey;

            //添加签名引用,uri为空,因此整个文档都被签名。
            var reference = new Reference();
            reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
            reference.AddTransform(new XmlDsigExcC14NTransform());
            reference.Uri = "";
            signedXml.AddReference(reference);


            // 添加证书作为密钥信息,因为这样,具有公钥的证书将被添加到签名部分。
            var keyInfo = new KeyInfo();
            keyInfo.AddClause(new KeyInfoX509Data(certificate));
            signedXml.KeyInfo = keyInfo;

            //生成签名
            signedXml.ComputeSignature();

            //将签名附加在xml文档的末尾
            xmlDocument.DocumentElement.AppendChild(signedXml.GetXml());

            //获取包含签名节点的XML
            return xmlDocument.InnerXml;
        }

        public static bool Validate(string signedXmlData, string certPath)
        {
            bool validSender;
            try
            {
                var assertion = new XmlDocument { PreserveWhitespace = true };
                assertion.LoadXml(signedXmlData);

                // 使用命名空间管理器来避免最糟糕的xpath
                var ns = new XmlNamespaceManager(assertion.NameTable);
                ns.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);

                // 获取XML的签名节点
                XmlNode signNode = assertion.SelectSingleNode("/ImportantData/ds:Signature", ns);

                // 加载XML签名
                var signedXml = new SignedXml(assertion.DocumentElement);
                signedXml.LoadXml(signNode as XmlElement);

                //检查密钥和签名匹配
                var cert = new X509Certificate2(certPath);
                if (!signedXml.CheckSignature(cert, true))
                {
                    throw new SecurityException("Signature check failed.");
                }
                else
                {
                    validSender = true;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return validSender;
        }
    }

Sample.xml

<?xml version="1.0" encoding="utf-8" ?>
<ImportantData>
  <EmployeeId>13232</EmployeeId>
  <Password>ilikeworld</Password>
</ImportantData>

运行结果如图:

这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值