2017-07-11 51 views
2

我想通过使用自签名X.509证书使用SHA256签名XML。我在#1启发了许多文章,并使用此代码:如何正确使用SHA256&X.509签名XML?

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。

与问候, 迈克尔

+0

您写的代码会生成签名,但不会将其放入文档(是否预先签名?)。您错过了对'GetXml()'的调用并将该节点插入到文档中。 – bartonjs

+0

谢谢,这帮助我解决了我的问题。实际上,我忘了将已签名的XML-Node添加到我的xml文件中。来自上面的“错误”签名的xml部分来自另一个意外执行的代码片段。所以我有两个错误合并在一起。 :) – MichaelXanadu

回答

1

当你成功调用signedXml.ComputeSignature(),只是不计算,不插入签名元素插入您在构造函数中传递文档(XmlDocument的正是文件GetXml()“ s节点将父对)。

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

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