2017-07-11 47 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代碼。經驗教訓,我想:)。