2012-08-01 331 views
7

我使用下面的方法來簽署XML文檔的XML文檔:簽名使用RSA-SHA256簽名方法問題

public static XmlDocument SignDocument(XmlDocument doc) 
    { 
     string signatureCanonicalizationMethod = "http://www.w3.org/2001/10/xml-exc-c14n#"; 
     string signatureMethod = @"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"; 
     string digestMethod = @"http://www.w3.org/2001/04/xmlenc#sha256"; 

     string signatureReferenceURI = "#_73e63a41-156d-4fda-a26c-8d79dcade713"; 

     CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), signatureMethod); 

     var signingCertificate = GetCertificate(); 

     SignedXml signer = new SignedXml(doc); 
     signer.SigningKey = signingCertificate.PrivateKey; 
     signer.KeyInfo = new KeyInfo(); 
     signer.KeyInfo.AddClause(new KeyInfoX509Data(signingCertificate)); 

     signer.SignedInfo.CanonicalizationMethod = signatureCanonicalizationMethod; 
     signer.SignedInfo.SignatureMethod = signatureMethod; 

     XmlDsigEnvelopedSignatureTransform envelopeTransform = new XmlDsigEnvelopedSignatureTransform(); 
     XmlDsigExcC14NTransform cn14Transform = new XmlDsigExcC14NTransform(); 

     Reference signatureReference = new Reference(); 
     signatureReference.Uri = signatureReferenceURI; 
     signatureReference.AddTransform(envelopeTransform); 
     signatureReference.AddTransform(cn14Transform); 
     signatureReference.DigestMethod = digestMethod; 

     signer.AddReference(signatureReference); 

     signer.ComputeSignature(); 
     XmlElement signatureElement = signer.GetXml(); 

     doc.DocumentElement.AppendChild(signer.GetXml()); 

     return doc; 
    } 


     private static X509Certificate2 GetCertificate() 
    { 

     X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine); 
     store.Open(OpenFlags.ReadOnly); 
     X509Certificate2 card = null; 
     foreach (X509Certificate2 cert in store.Certificates) 
     { 
      if (!cert.HasPrivateKey) continue; 

      if (cert.Thumbprint.Equals("a_certain_thumb_print", StringComparison.OrdinalIgnoreCase)) 
      { 
       card = cert; 
       break; 
      } 
     } 
     store.Close(); 

     return card; 
    } 

試圖計算時類型System.Security.Cryptography.CryptographicException的異常被拋出帶錯誤消息的簽名指定的算法無效。有任何想法嗎?

機器:Windows Server 2008 R2

.Net Framework:4.0。

IDE:Visual Studio 2010.

+4

實現我解決這個問題(感謝菲利普)如下: /*添加的代碼後VAR signingCertificate = GetCertificate以下行(); */ CspParameters cspParams = new CspParameters(24); cspParams.KeyContainerName =「XML_DISG_RSA_KEY」; RSACryptoServiceProvider key = new RSACryptoServiceProvider(cspParams); key.FromXmlString(signingCertificate.PrivateKey.ToXmlString(true)); /*將新密鑰分配給簽署者的SigningKey */ metadataSigner.SigningKey = key; – UncleZen 2012-08-03 18:00:50

+0

thx UncleZen修復了它,但cspParams.KeyContainerName =「XML_DISG_RSA_KEY」不是必需的,它在沒有它的情況下也起作用。 – BitSchupser 2013-10-07 11:20:53

回答

2

非常感謝這篇博客。它實際上解決了我的問題。 順便說一下,如果從文件加載證書,它應該是可導出的: X509Certificate2 x509Key = new X509Certificate2(「xxxxx.pfx」,「123」,X509KeyStorageFlags.Exportable);

+0

這不回答問題 – 2013-06-16 04:04:08

+4

這並不回答問題,但在實施UncleZen的解決方案後,如果密鑰未被標記爲可導出,則會出現錯誤「密鑰在指定狀態下無效」。 – BitSchupser 2013-10-07 12:23:28

1

@minhj的回覆提到了一些博客,但鏈接不存在。

但是,添加提到的類here並註冊它解決了問題。似乎它應該只在每個應用程序域中註冊一次。