2016-02-25 71 views
1

我正在尝试为我的软件构建更新程序。到目前为止,这不是一项艰巨的任务,但是我想签署文件以防止它们被黑客攻击和修改(因为它可以安装有害软件)以防止造成伤害。如何验证C#中数字签名的XML文档?

我在MSDN和各种博客上发现了一些教程,它们完美地展示了如何签名XML文件。得到这个工作 - 我有一个签名附加到我的文件。

某种程度上没有涉及的事情是:验证如何在不同的计算机上工作?我不明白我应该如何提供必要的数据来验证它。据我所知,我需要私钥才能验证签名(其中包含公钥)。现在我该如何提供那个?如果我只是将它存储在应用程序中,即使加密,也可以轻松抓取它。

我试过的另一种可能的方法是嵌入X509证书。我甚至有一些代码可以生成这样的代码,但是它总是会显示证书来自未知来源。

有没有提示用户安装证书的方式吗?或者更好的是没有安装任何东西?

到目前为止,我还没有发现任何事情。

回答

3

忘记这是XML的事实。

数字签名依赖于密码学的一个简单原理,更具体地说,您有两个密钥(一个公钥和一个私钥)的不对称密码学。

您使用您的私钥签名并将签名的文档交给某人。有人用你的公钥验证签名。公钥 - 如其名称所示 - 是公开的并且可以分发。私钥仅用于签名。公众只用于验证签名。

关于XML,您可以使用digital signature配置文件。您可以签署一个XML文档,这将导致您可以附加到XML的一些二进制内容。您也可以附加公钥。由于公钥是签名内容的一部分,因此您知道它还没有被篡改。此外,您可以将公钥视为PKI的一部分。这可能是你首先选择信任公钥的方式。

签约内容规定:

  • 完整性
  • 不可否认

对于验证,高层次的原理上Wikipedia和许多其他网站解释。您将不得不告诉您的应用在哪里找到验证XML的密钥。更多示例请查看standardization body

最后,MSDN在主题上有大量文章和示例代码。快速谷歌提出了这篇文章:How to: Verify the Digital Signatures of XML Documents

另一个道路的链接...这是一个primer on crypto这是写得很好。它讲述了密钥及其用法。

+0

因此,可以使用**验证用于验证XML文件的数据公钥吗?私钥只是用于签名,对吧? – SharpShade

+0

是的,这是正确的。 –

+0

嗯,那么我可能误解了不对称加密/签名的原理。这很好,那么我认为我可以轻松修改我已经拥有的代码:)谢谢! – SharpShade

1

感谢David Brossard的回答,我找到了解决方案。那么对于那些谁可以跨四处觅食,这里是我的代码(因为它包含了从我的签名工具的东西签名必须修改代码,一点点):

签约

private static int Sign(Options options) 
    { 
     XmlDocument document = new XmlDocument {PreserveWhitespace = false}; 
     try 
     { 
      document.Load(options.File); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine($"Invalid XML file: {0}.", ex.Message); 
      return -3; 
     } 

     XmlElement signature; 
     try 
     { 
      RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048); 
      if (!string.IsNullOrEmpty(options.Key) && File.Exists(options.Key)) 
      { 
       using (StreamReader reader = new StreamReader(options.Key)) 
        rsa.FromXmlString(reader.ReadToEnd()); 
      } 
      else 
      { 
       FileInfo fi = new FileInfo(options.File); 
       if (fi.DirectoryName == null) return -7; 
       string keyFile = Path.Combine(fi.DirectoryName, "signature.key"); 
       using (StreamWriter writer = new StreamWriter(keyFile)) 
        writer.Write(rsa.ToXmlString(true)); 
      } 


      SignedXml signedXml = new SignedXml(document) {SigningKey = rsa}; 
      KeyInfo info = new KeyInfo(); 
      info.AddClause(new RSAKeyValue(rsa)); 
      signedXml.KeyInfo = info; 

      Reference reference = new Reference {Uri = ""}; 

      reference.AddTransform(new XmlDsigEnvelopedSignatureTransform()); 
      reference.AddTransform(new XmlDsigC14NTransform()); 

      signedXml.AddReference(reference); 
      signedXml.ComputeSignature(); 

      signature = signedXml.GetXml(); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine($"Error signing XML file: {0}.", ex.Message); 
      return -4; 
     } 

     try 
     { 
      if (document.DocumentElement == null) 
      { 
       Console.WriteLine("Document has no document element."); 
       return -6; 
      } 
      document.DocumentElement.AppendChild(document.ImportNode(signature, true)); 
      document.Save(options.File); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine($"Error saving signed XML file: {0}.", ex.Message); 
      return -5; 
     } 

     return 0; 
    } 

验证

public static bool Verify(XmlDocument document) 
    { 
     if (document == null) throw new ArgumentNullException(nameof(document), "XML document is null."); 

     SignedXml signed = new SignedXml(document); 
     XmlNodeList list = document.GetElementsByTagName("Signature"); 
     if (list == null) 
      throw new CryptographicException($"The XML document has no signature."); 
     if (list.Count > 1) 
      throw new CryptographicException($"The XML document has more than one signature."); 

     signed.LoadXml((XmlElement)list[0]); 

     RSA rsa = null; 
     foreach (KeyInfoClause clause in signed.KeyInfo) 
     { 
      RSAKeyValue value = clause as RSAKeyValue; 
      if (value == null) continue; 
      RSAKeyValue key = value; 
      rsa = key.Key; 
     } 

     return rsa != null && signed.CheckSignature(rsa); 
    } 
+0

你介意看看类似的问题,请stackoverflow.com/questions/42440634/xml-signature-element-is-not-declared –