【问题标题】:How to sign XML with SHA256 & X.509 correctly?如何正确使用 SHA256 和 X.509 签署 XML?
【发布时间】:2017-07-11 10:04:11
【问题描述】:

我想使用自签名 X.509 证书使用 SHA256 对 XML 进行签名。 Stackoverflow 中的许多文章启发了我,并使用了以下代码:

X509Certificate2 cert = new X509Certificate2();
X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
foreach (X509Certificate2 cert2 in store.Certificates)
{
    if (cert2.Subject == "CN=TestCerificate")
    {
        cert = cert2;
        break;
    }
}

store.Close();

CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
var exportedKeyMaterial = cert.PrivateKey.ToXmlString(true);
var key = new RSACryptoServiceProvider(new CspParameters(24));
key.PersistKeyInCsp = false;
key.FromXmlString(exportedKeyMaterial);

XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
doc.Load("test.xml");

SignedXml signedXml = new SignedXml(doc);
signedXml.SigningKey = key;
signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";

Reference reference = new Reference();
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
reference.AddTransform(new XmlDsigExcC14NTransform());
reference.Uri = "";
reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256"; 
signedXml.AddReference(reference);

KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new KeyInfoX509Data(cert));
signedXml.KeyInfo = keyInfo;
signedXml.ComputeSignature();

doc.Save("testSig.xml");

之后,生成的“testSig.xml”的签名 XML 部分如下所示:

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
      <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1" />
      <Reference URI="">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
        <DigestValue>ghOEPeYtAUs5Kb8VMOCIS3f2wIY=</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>HANI0GrICbyc5tlmvtU9cB7txdxtuY4uDsntp5XVzaRQbts76ff3Qg==</SignatureValue>
  </Signature>

如您所见,XML 表示“SHA1”用于对 XML 进行签名(请参阅节点“SignatureMethod”和“DigestMethod”)。但我希望,必须在这些节点中说明 SHA256-URL。这个假设正确吗?如果是,有人知道如何解决这个问题吗?我使用 C# 4.6.0。

谨此致以最诚挚的问候, 迈克尔

【问题讨论】:

  • 您编写的代码会构建签名,但不会将其放入文档中(它是预签名的吗?)。您错过了对 GetXml() 的调用并将该节点插入到文档中。
  • 谢谢,这帮助我解决了我的问题。事实上,我忘记将签名的 XML 节点添加到我的 xml 文件中。上面的“错误”签名的 xml 部分来自另一个意外执行的代码 sn-p。所以我有两个错误合并在一起。 :)

标签: c# xml x509 sha256 xml-signature


【解决方案1】:

虽然您成功调用了仅执行计算的 signedXml.ComputeSignature(),但它不会将签名元素插入到文档中(您在构造函数中传递的 XmlDocument 正是文档 GetXml() 的节点的父级)。

您需要调用signedXml.GetXml()(在ComputeSignature 之后)以获取计算出的ds:Signature 元素,然后将其插入到您的文档中。

您的文档中已经有一个签名节点这一事实令人困惑。我的第一个想法是test.xml 已经有这个签名,但是你的评论说它只是来自其他地方的一些糟糕的代码。经验教训,我猜:)。

【讨论】:

    猜你喜欢
    • 2013-01-01
    • 2017-11-28
    • 1970-01-01
    • 2018-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-15
    相关资源
    最近更新 更多