2011-03-31 6 views
9

네임 스페이스 접두사 및 네임 스페이스 참조가 포함 된 XML 문서에 서명하고 유효성을 검사 할 때 문제가 발생합니다. 이 경우 유효성 검사는 항상 (false를 반환)을 실패합니다. XML에서 네임 스페이스 접두사와 네임 스페이스 참조를 제거하면 서명 및 유효성 검사가 올바르게 작동합니다.SignedXml에서 사용자 지정 네임 스페이스 문제

도와 주시겠습니까? 여기

내 코드입니다 : 내가 서명 방법을 호출하고있어 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"; 
     } 
    }  
} 

그리고 서명

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

클래스 SignedXml

에서

상속 클래스

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

그리고 검증

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

은 여기 내 서명 XML

<?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> 

당신을 사전에 감사이야!

+1

당신은'X509Certificate'와'SignatureValue' 태그의 전체 내용을 제공 할 수 있습니다, 그래서 우리는 그것을 테스트 할 수 있습니까? –

+0

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

답변

2

모든 유효한 참조에 XmlDsigExcC14NTransform을 추가하면 문제가 해결됩니다. 이 문제를 일으키는 .NET Framework에는 문제가 있다고 생각합니다.

reference2.AddTransform(new XmlDsigExcC14NTransform());

+3

나를 위해, 그 노드에 XML을 추가했지만 원하는'ds :'네임 스페이스 접두사를 추가하지 않았습니다. 아마도 나는 당신의 대답을 오해했습니다. 조금 더 많은 코드가 도움이 될 것입니다. –