2012-08-01 333 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并注册它解决了问题。似乎它应该只在每个应用程序域中注册一次。