2012-08-01 141 views
7

estoy usando el método siguiente para firmar documentos XML:La firma de un documento XML utilizando RSA-SHA256 tema método de firma

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; 
    } 

una excepción de tipo System.Security.Cryptography.CryptographicException se lanza cuando se trata de calcular la firma con el mensaje de error Algoritmo inválido especificado. ¿Algunas ideas?

Máquina: Windows Server 2008 R2

.Net Framework: 4.0.

IDE: Visual Studio 2010.

+4

resolví este problema (gracias Phillip) de la siguiente manera: /* añadir las siguientes líneas de código después de 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)); /* asignar la nueva clave al firmante SigningKey */ metadataSigner.SigningKey = clave; – UncleZen

+0

thx UncleZen que lo arregló pero cspParams.KeyContainerName = "XML_DISG_RSA_KEY" no es necesario, también funciona sin él. – BitSchupser

Respuesta

2

Muchas gracias por este blog. En realidad resolvió mi problema. Por cierto, si el certificado se carga desde el archivo, debe ser exportable: X509Certificate2 x509Key = new X509Certificate2 ("xxxxx.pfx", "123", X509KeyStorageFlags.Exportable);

+0

Esto no responde a la pregunta –

+4

Eso no responde la pregunta, pero después de implementar la solución de UncleZen obtendría el error "Clave no válida para usar en el estado especificado" si la clave no se marcó como exportable. – BitSchupser

1

La respuesta de @minhj menciona algún blog, pero el enlace no está allí.

Sin embargo, agregar la clase mencionada here y registrarla solucionó el problema. Parece que debe registrarse solo una vez por dominio de la aplicación.

Cuestiones relacionadas