2009-12-01 106 views
4

我正在嘗試在C#.NET 3.5中使用私有的RSA簽署一個XML文件,該密鑰由OpenSSL生成。如何在.NET中用RSA密鑰簽名XML文件?

這裏是我是如何進行的:我使用奇爾卡特框架(www.example-code.com/csharp/cert_usePrivateKeyFromPEM.asp)

用我的XML轉換的關鍵RSA密鑰從PEM格式爲XML格式,我現在我可以使用自己的.NET函數了,我更喜歡它。所以我使用了MSDN中描述的方法。

所以,到最後,我的源代碼如下所示:

RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(); 

//Load the private key from xml file 
XmlDocument xmlPrivateKey = new XmlDocument(); 
xmlPrivateKey.Load("PrivateKey.xml"); 
rsaProvider.FromXmlString(xmlPrivateKey.InnerXml); 

// Create a SignedXml object. 
SignedXml signedXml = new SignedXml(Doc); 

// Add the key to the SignedXml document. 
signedXml.SigningKey = Key; 

// Create a reference to be signed. 
Reference reference = new Reference(); 
reference.Uri = ""; 

// Add an enveloped transformation to the reference. 
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform(); 
reference.AddTransform(env); 

// Add the reference to the SignedXml object. 
signedXml.AddReference(reference); 

// Compute the signature. 
signedXml.ComputeSignature(); 

// Get the XML representation of the signature and save 
// it to an XmlElement object. 
XmlElement xmlDigitalSignature = signedXml.GetXml(); 

// Append the element to the XML document. 
Doc.DocumentElement.AppendChild(Doc.ImportNode(xmlDigitalSignature, true)); 

的簽名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#rsa-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>qoGPSbe4oR9e2XKN6MzP+7XlXYI=</DigestValue> 
    </Reference> 
</SignedInfo> 
<SignatureValue>iPQ6IET400CXfchWJcP22p2gK6RpEc9mkSgfoA94fL5UM6+AB5+IO6BbjsNt31q6MB8hR6lAIcnjzHzc5SeXvFP8Py2bqHTYJvcSA6KcKCQl1LiDNt12UwWiKpSkus2p0LdAeeZJNy9aDxjC/blUaZEr4uPFt0kGCD7h1NQM2SY=</SignatureValue> 

的問題是,當我嘗試驗證使用xmlsec在這個網址簽名:http://www.aleksey.com/xmlsec/xmldsig-verifier.html。我收到一條消息,告訴我簽名是無效的。

我一直在尋找我的代碼中的錯誤幾天,我找不到。我開始認爲從PEM到XML文件的轉換可能是問題,但我不知道如何測試。此外,我沒有找到任何其他方式轉換爲鍵或在.NET中直接使用PEM文件。

有沒有人設法在.NET中獲得有效簽名?

回答

2

是的,我設法做到了。 我認爲問題在於您的參考。 uri應該指向簽名所針對的元素的id。無論如何,請檢查下面的代碼,希望它指向正確的方向。

/克勞斯

/// <summary> 
    /// Signs an XmlDocument with an xml signature using the signing certificate given as argument to the method. 
    /// </summary> 
    /// <param name="doc">The XmlDocument to be signed</param> 
    /// <param name="id">The is of the topmost element in the xmldocument</param> 
    /// <param name="cert">The certificate used to sign the document</param> 
    public static void SignDocument(XmlDocument doc, string id, X509Certificate2 cert) 
    { 
     SignedXml signedXml = new SignedXml(doc); 
     signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl; 
     signedXml.SigningKey = cert.PrivateKey; 

     // Retrieve the value of the "ID" attribute on the root assertion element. 
     Reference reference = new Reference("#" + id); 

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

     signedXml.AddReference(reference); 

     // Include the public key of the certificate in the assertion. 
     signedXml.KeyInfo = new KeyInfo(); 
     signedXml.KeyInfo.AddClause(new KeyInfoX509Data(cert, X509IncludeOption.WholeChain)); 

     signedXml.ComputeSignature(); 
     // Append the computed signature. The signature must be placed as the sibling of the Issuer element. 
     XmlNodeList nodes = doc.DocumentElement.GetElementsByTagName("Issuer", Saml20Constants.ASSERTION); 
     // doc.DocumentElement.InsertAfter(doc.ImportNode(signedXml.GetXml(), true), nodes[0]);    
     nodes[0].ParentNode.InsertAfter(doc.ImportNode(signedXml.GetXml(), true), nodes[0]); 
    } 
+1

隨着「」你隱招牌所有的XML的,如果你用一個id你只籤部分:PreserveWhitespace加載XML文檔進行簽名

一個很好的例子可以在這裏找到之前= FALSE 它。 – 2009-12-01 10:06:20

+0

我必須做的簽名必須遵循規則「只有看到的東西應該簽名」。我以爲我必須簽署整個文件,但我可能錯了......我會盡力改變參考文獻的Uri。希望它完全可以做到這一點。 – 2009-12-01 10:26:12

+0

你如何設置頂部元素的ID? 我試過這個: //創建一個數據對象來保存要簽名的數據。 DataObject dataObject = new DataObject(); dataObject.Data = Doc.ChildNodes; dataObject.Id =「MyObjectId」; //將數據對象添加到簽名中。 signedXml.AddObject(dataObject); //將密鑰添加到SignedXml文檔。 signedXml.SigningKey = Key; //創建一個要簽名的引用。 Reference reference = new Reference(「#MyObjectId」); 但我得到一個例外... – 2009-12-01 10:45:53

1

在我看來,您註冊在XML中everrything:reference.Uri = "";

Purhaps你,當你將其插入文檔中或在錯誤插入破壞簽名辦法。

還要注意命名空間和空白,其中一些還被簽名,這可能會導致在處理簽名文檔時出現問題。

1

嘗試更換

dataObject.Data = Doc.ChildNodes; 

與此:

dataObject.Data = Doc.GetElementsByTagName("YourRootNodeNameHere"); 
1

今天我有同樣的問題,我的一個同事懷疑,這是可能是因爲.NET XML C14變換沒有按」 t遵循在xmlsec中實現的XML標準。我會嘗試自己做轉換,並讓你知道這是否是真正的問題。

+0

那麼,這是同樣的問題?請在這種情況下擴大您的答案。 – 2015-01-20 08:29:18