2011-03-31 21 views
9

El problema se produce cuando firmo documentos XML que contienen los prefijos de espacio de nombres y las referencias del espacio de nombres y luego lo valido. La validación siempre falla (devuelve falso) en este caso. Cuando elimino los prefijos del espacio de nombres y las referencias del espacio de nombres del XML, la firma y la validación funcionan bien.Problema con el espacio de nombres personalizado con SignedXml

¿Me podría ayudar?

Aquí está mi código:

clase hereda de SignedXml

namespace Xmldsig 
{ 
    using System; 
    using System.Security.Cryptography; 
    using System.Security.Cryptography.Xml; 
    using System.Xml; 

    public sealed class SignaturePropertiesSignedXml : SignedXml 
    { 
     private XmlDocument doc; 
     private XmlElement signaturePropertiesRoot; 
     private XmlElement qualifyingPropertiesRoot; 

     private string signaturePropertiesId; 

     public SignaturePropertiesSignedXml(XmlDocument doc) 
      : base(doc) 
     { 
      return; 
     } 

     public SignaturePropertiesSignedXml(XmlDocument doc, string signatureId, string propertiesId) 
      : base(doc) 
     { 
      this.signaturePropertiesId = propertiesId; 
      this.doc = null; 
      this.signaturePropertiesRoot = null; 
      if (string.IsNullOrEmpty(signatureId)) 
      { 
       throw new ArgumentException("signatureId cannot be empty", "signatureId"); 
      } 
      if (string.IsNullOrEmpty(propertiesId)) 
      { 
       throw new ArgumentException("propertiesId cannot be empty", "propertiesId"); 
      } 

      this.doc = doc; 
      base.Signature.Id = signatureId; 

      this.qualifyingPropertiesRoot = doc.CreateElement("QualifyingProperties", "http://www.w3.org/2000/09/xmldsig#"); 
      this.qualifyingPropertiesRoot.SetAttribute("Target", "#" + signatureId); 

      this.signaturePropertiesRoot = doc.CreateElement("SignedProperties", "http://www.w3.org/2000/09/xmldsig#"); 
      this.signaturePropertiesRoot.SetAttribute("Id", propertiesId); 


      qualifyingPropertiesRoot.AppendChild(signaturePropertiesRoot); 
      DataObject dataObject = new DataObject 
      { 
       Data = qualifyingPropertiesRoot.SelectNodes("."), 
       Id = "idObject" 
      }; 
      AddObject(dataObject); 


     } 

     public void AddProperty(XmlElement content) 
     { 
      if (content == null) 
      { 
       throw new ArgumentNullException("content"); 
      } 

      XmlElement newChild = this.doc.CreateElement("SignedSignatureProperties", "http://www.w3.org/2000/09/xmldsig#"); 

      newChild.AppendChild(content); 
      this.signaturePropertiesRoot.AppendChild(newChild); 
     } 

     public override XmlElement GetIdElement(XmlDocument doc, string id) 
     { 
      if (String.Compare(id, signaturePropertiesId, StringComparison.OrdinalIgnoreCase) == 0) 
       return this.signaturePropertiesRoot;    

      if (String.Compare(id, this.KeyInfo.Id, StringComparison.OrdinalIgnoreCase) == 0) 
       return this.KeyInfo.GetXml(); 

      return base.GetIdElement(doc, id); 
     } 
    } 
} 

La clase que la firma XML

namespace Xmldsig 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.ComponentModel; 
    using System.Data; 
    using System.Linq; 
    using System.Text; 
    using System.Windows.Forms; 
    using System.Xml; 
    using System.IO; 
    using System.Security.Cryptography; 
    using System.Security.Cryptography.Xml; 
    using System.Security.Cryptography.X509Certificates; 
    using Security.Cryptography; 
    using System.Security.Principal; 
    using System.Collections; 

    public class VerifyResult 
    { 
     public string Timestamp { get; set; } 
     public X509Certificate2 SigningCertificate { get; set; } 
    } 

    public class XmldsigClass 
    { 
     public static XmlDocument SignDocument(XmlDocument doc, string RefUri) 
     { 
      string idSignProperties = "idSignedProperties"; 
      SignaturePropertiesSignedXml signer = new SignaturePropertiesSignedXml(doc, "Uzb_sig_v001", idSignProperties); 

      X509Certificate2 cert = GetCertificate(); 

      RSA key = (RSACryptoServiceProvider)cert.PrivateKey; 
      signer.SigningKey = key; 
      signer.SignedInfo.CanonicalizationMethod = "http://www.w3.org/2001/10/xml-exc-c14n#"; 
      signer.SignedInfo.SignatureMethod = @"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"; 

      // create a timestamp property 
      XmlElement timestamp = doc.CreateElement("SigningTime", SignedXml.XmlDsigNamespaceUrl); 
      timestamp.InnerText = DateTimeToCanonicalRepresentation(); 
      signer.AddProperty(timestamp); 


      var certificateKeyInfo = new KeyInfo(); 
      certificateKeyInfo.Id = "idKeyInfo"; 
      certificateKeyInfo.AddClause(new KeyInfoX509Data(cert)); 
      signer.KeyInfo = certificateKeyInfo; 

      Reference reference = new Reference(RefUri); 
      reference.DigestMethod = @"http://www.w3.org/2001/04/xmlenc#sha256"; 
      reference.AddTransform(new XmlDsigEnvelopedSignatureTransform()); 
      signer.AddReference(reference); 


      Reference propertiesRefki = new Reference(); 
      propertiesRefki.Uri = "#idKeyInfo"; 
      propertiesRefki.DigestMethod = @"http://www.w3.org/2001/04/xmlenc#sha256"; 
      signer.AddReference(propertiesRefki); 

      Reference reference2 = new Reference(); 
      reference2.Uri = "#" + idSignProperties; 
      reference2.DigestMethod = @"http://www.w3.org/2001/04/xmlenc#sha256"; 
      signer.AddReference(reference2); 


      signer.ComputeSignature();    

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

      return doc; 
     } 


     public static bool CheckSignature(XmlDocument xmlDoc) 
     { 
      SignedXml signedXml = new SignedXml(xmlDoc); 
      XmlNodeList elementsByTagName = xmlDoc.GetElementsByTagName("Signature"); 
      signedXml.LoadXml((XmlElement)elementsByTagName[0]); 
      bool sigCheck = signedXml.CheckSignature(); 

      return sigCheck; 
     } 

     private static X509Certificate2 GetCertificate() 
     { 

      X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser); 
      store.Open(OpenFlags.ReadOnly); 
      X509Certificate2 card = null; 
      foreach (X509Certificate2 cert in store.Certificates) 
      { 
       if (!cert.HasPrivateKey) continue; 
       AsymmetricAlgorithm aa = cert.PrivateKey; 
       ICspAsymmetricAlgorithm caa = aa as ICspAsymmetricAlgorithm; 
       if (caa == null) continue; 
       if (caa.CspKeyContainerInfo.HardwareDevice) 
       { 
        card = cert; 
        break; 
       } 
      } 
      store.Close(); 

      return card; 
     } 

     private static string DateTimeToCanonicalRepresentation() 
     { 
      var ahora = DateTime.Now.ToUniversalTime(); 
      return ahora.Year.ToString("0000") + "-" + ahora.Month.ToString("00") + 
        "-" + ahora.Day.ToString("00") + 
        "T" + ahora.Hour.ToString("00") + ":" + 
        ahora.Minute.ToString("00") + ":" + ahora.Second.ToString("00") + 
        "Z"; 
     } 
    }  
} 

Y aquí estoy llamando método de firma

 XmlDocument xmlDoc = new XmlDocument(); 
     xmlDoc.PreserveWhitespace = true; 
     if (openFileDialog1.ShowDialog() == DialogResult.OK) 
     { 
      xmlDoc.Load(openFileDialog1.FileName); 

      XmlDocument resxml = Xmldsig.XmldsigClass.SignDocument(xmlDoc, "#Uzb_doc_v001"); 


      var name = openFileDialog1.FileName + ".xml"; 
      xmlDoc.Save(name); 

      var bytes = System.IO.File.ReadAllBytes(name); 
      System.IO.File.WriteAllBytes(name, bytes.Skip(3).ToArray()); 
      MessageBox.Show("Signed"); 
     } 

Y para la verificación

 XmlDocument xmlDoc = new XmlDocument(); 
     xmlDoc.PreserveWhitespace = true; 
     if (openFileDialog1.ShowDialog() == DialogResult.OK) 
     { 
      xmlDoc.Load(openFileDialog1.FileName); 

      bool b = Xmldsig.XmldsigClass.CheckSignature(xmlDoc); 

      MessageBox.Show(b.ToString()); 
     } 

Aquí está mi XML firmado

<?xml version="1.0" encoding="utf-8" standalone="no"?> 
<uz:CreditcardEnveloppe xmlns:uz="http://aaaa.com/CreditcardEnveloppe/transport" Id="Uzb_doc_v001" Version="1.0"> 
    <uz:creditcard> 
    <uz:number>19834209</uz:number> 
    <uz:expiry>02/02/2002</uz:expiry> 
    </uz:creditcard> 
    <Signature Id="sig_v001" xmlns="http://www.w3.org/2000/09/xmldsig#"> 
    <SignedInfo> 
     <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> 
     <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /> 
     <Reference URI="#Uzb_doc_v001"> 
     <Transforms> 
      <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /> 
     </Transforms> 
     <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> 
     <DigestValue>RnpNXyhxQcjr/SWqVlWY31S1xpj2opZhlsT4d1iyBKI=</DigestValue> 
     </Reference> 
     <Reference URI="#idKeyInfo"> 
     <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> 
     <DigestValue>O0Z2BU5ODwgOZOhpFvkcSaO/jmWFykBwnxMUD5a5SwM=</DigestValue> 
     </Reference> 
     <Reference URI="#idSignedProperties"> 
     <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> 
     <DigestValue>UVjk8Jkq0Y6OxFqiB4q/4vqli/KJT5pYEPzlNTkfIhY=</DigestValue> 
     </Reference> 
    </SignedInfo> 
    <SignatureValue>prOZXn..</SignatureValue> 
    <KeyInfo Id="idKeyInfo"> 
     <X509Data> 
     <X509Certificate>MIIE7TCCA9WgAwIBAgISESBS...</X509Certificate> 
     </X509Data> 
    </KeyInfo> 
    <Object Id="idObject"> 
     <QualifyingProperties Target="#sig_v001"> 
     <SignedProperties Id="idSignedProperties"> 
      <SignedSignatureProperties> 
      <SigningTime>2011-03-30T06:01:48Z</SigningTime> 
      </SignedSignatureProperties> 
     </SignedProperties> 
     </QualifyingProperties> 
    </Object> 
    </Signature> 
</uz:CreditcardEnveloppe> 

Gracias de antemano!

+1

¿Puede proporcionar todo el contenido de las etiquetas '' SignatureValue' X509Certificate' y, por lo que puede probarlo? –

+0

Relacionados: http://stackoverflow.com/questions/381517/net-signed-xml-prefix –

Respuesta

2

Agregar XmlDsigExcC14NTransform a todas sus referencias calificantes resuelve el problema. Creo que hay algo mal en .NET Framework que causa este problema.

reference2.AddTransform(new XmlDsigExcC14NTransform());

+3

Para mí, eso agregó un par de nodos al XML pero no agregó los prefijos del espacio de nombres 'ds:'. Quizás he malentendido tu respuesta; un poco más de código sería útil. –

Cuestiones relacionadas