BizTalk Utilities CV ,   Jobs ,   Code library
 
Go to the front page to continue learning about XML or select below:

Contents

ReBlogger Contents

Previous posts in .NET XML, System.XML

 
 
Page 13471 of 19640

XAdES Interop with XML-DSIG as implemented by the .NET Framework

Blogger : Softwaremaker (WSE)
All posts : All posts by Softwaremaker (WSE)
Category : .NET XML, System.XML
Blogged date : 2006 Feb 08

What a way to start off a new category on my blog called "Interoperability".
I recently came across an interesting post in the forums that goes something like this:

[QUOTE]


Currently I'm working with Visual Studio 2003 in order to generate xmldsig signature. I'm using the class signedxml  to create the xmldsig signature and I get somthing like this:

  [Signature xmlns="http://www.w3.org/2000/09/xmldsig#"]
    [SignedInfo]
      [CanonicalizationMethod
Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /]
............
  [/Signature]

But I need the signature to be in a namespace that should be identified by
the dsig prefix:

[dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"]
[dsig:SignedInfo]
.....
[/dsig:Signature]


I really didnt think anything of this. At first glance, I thought the problem lies not in the code BUT the processor / validator that was used to read this.

The dsig or any prefix, for that matter, doesn't indicate whether they 2 use different namespaces. Check
the [default] namespaces and compare.

Strictly speaking -

  • [ds:Signature xmlns:ds="urn:softwaremaker.net-foo.bar" /]
  • [dsig:Signature xmlns:dsig="urn:softwaremaker.net-foo.bar" /]
  • [Signature xmlns="urn:softwaremaker.net-foo/bar /]

are isomorphically the same. If the end processor / validator reads it and treats differently, I believe that it should be a design flaw at the other end as it is really poor design to rely on namespace prefix.

If you look at the _XML-DSIG_ Specifications, Section 1.3 states that:

This namespace is also used as the prefix for algorithm identifiers used by this specification. While applications MUST support XML and XML namespaces, the use of internal entities [XML] or our "dsig" XML namespace prefix and defaulting/scoping conventions are OPTIONAL; we use these facilities to provide compact and readable examples.

Therefore, it is NOT necessarily to have a prefix to it as long as it points to the same namespace.

However, I spoke too fast. Further explanations by the other party has made me put my thinking cap on. He provided 2 reasons being:

  1. Compatibility with our existing signer.
  2. We are planning to extend the signature to _XAdES_ format. In that case the prefix is mandatory.

I am surprised [which kinda shows how much I know, or dont know ???]. I spent some minutes digging into the _XAdES_ specifications and true enough, it declares:


The XML schema definition in clause 5 Qualifying properties syntax defines the prefix "ds" for all the XML elements already defined in [XMLDSIG], and states that the default namespace is the one defined for the present document. In consequence, in the examples of this clause, the elements already defined in [XMLDSIG] appear with the prefix "ds", whereas the new XML elements defined in the present document appear without prefix.

                              XMLDSIG 
                                   |
<ds:Signature ID?>- - - - - - - - -+- - - - -+
  <ds:SignedInfo>                  |         |
    <ds:CanonicalizationMethod/>   |         |
    <ds:SignatureMethod/>          |         |
    (<ds:Reference URI? >          |         |
      (<ds:Transforms>)?           |         |
      <ds:DigestMethod>            |         |
      <ds:DigestValue>             |         |
    </ds:Reference>)+              |         |
  </ds:SignedInfo>                 |         |
  <ds:SignatureValue>              |         |
  (<ds:KeyInfo>)?- - - - - - - - - +         |
                                             |
  <ds:Object>                                |
                                             |
    <QualifyingProperties>                   |
                                             |
      <SignedProperties>                     |
                                             |
        <SignedSignatureProperties>          |
          (SigningTime)                      |
          (SigningCertificate)               |
          (SignaturePolicyIdentifier)        |
          (SignatureProductionPlace)?        |
          (SignerRole)?                      |
        </SignedSignatureProperties>         |
                                             |
        <SignedDataObjectProperties>         |
          (DataObjectFormat)*                |
          (CommitmentTypeIndication)*        |
          (AllDataObjectsTimeStamp)*         |
          (IndividualDataObjectsTimeStamp)*  |
        </SignedDataObjectProperties>        |
                                             |
      </SignedProperties>                    |
                                             |
      <UnsignedProperties>                   |
                                             |
        <UnsignedSignatureProperties>        |
          (CounterSignature)*                |
        </UnsignedSignatureProperties>       |
                                             |
      </UnsignedProperties>                  |
                                             |
    </QualifyingProperties>                  |
                                             |
  </ds:Object>                               |
                                             |
</ds:Signature>- - - - - - - - - - - - - - - +
                                             |
                                          XAdES
                       
Readers must take into account that the XAdES forms build up on the[XMLDSIG] by adding new XML elements containing qualifying information within the shown [XMLDSIG]ds:Object element, according to the rules defined in the present document. This ds:Object element will act as a bag for the whole set of qualifying properties defined in the present document, conveniently grouped.


So, there are 2 questions to answer here:

  1. Is there a way to handle the Digital Signature prefix in the SignedXML Class in .NET Framework 1.1
  2. If so - How ? If not - How ?

I decided to spend some time on this and after much disassembling some of the System.Security.Crytography.XML binaries, I found out to my dismay that the answer to Question [1] is NO. This is because the constants and the URIs of the XML Digital Signature functions in the System.Security.Crytography.XML space are found in the XMLSignature class and that class is declared as an internal class i-frown.

Therefore, the answer to Question [2] would be to build our own customized Digital Signature stack. This may actually sound harder than it is. Truth is:- With Reflector and work done behind the MONO-Project and published on Koders.com, I hacked a workaround in a few hours time. That actually means that I didnt really do much testing on it and so I disclaim myself from any liabilities, including, but not limited to, mistakes, injuries, deaths, etc caused if you choose to use it.

You would use this assembly just like you would with System.Security.Cryptography.Xml. The namespace would be Softwaremaker.NET.Security.Cryptography.Xml.PfDsigInterop.

Do take note that I ONLY implemented the XML Digital Signature here.


Imports System
Imports System.IO
Imports System.Security.Cryptography
Imports System.Xml
Imports System.text
Imports Mono.Xml
Imports System.Text.UTF8Encoding
Imports Softwaremaker.NET.Security.Cryptography.Xml.PfDsigInterop

myRSA = New RSACryptoServiceProvider
myRSA.FromXmlString("...")

Dim doc As XmlDocument = New XmlDocument
doc.PreserveWhitespace = False
doc.Load(New XmlTextReader("..."))

Dim mySignedXML As SignedXml = New SignedXml(doc)
mySignedXML.SigningKey = myRSA

' Create a data object to hold the data to sign.
Dim dataObject As New DataObject
dataObject.Data = doc.ChildNodes
dataObject.Id = "someSWMId"

' Add the data object to the signature.
mySignedXML.AddObject(dataObject)

Dim ref As New Reference
ref.Uri = "#someSWMId"
mySignedXML.AddReference(ref)

mySignedXML.ComputeSignature()

Dim xmldg As XmlElement = mySignedXML.GetXml
' Append the element to the XML document.
doc.DocumentElement.AppendChild(doc.ImportNode(xmldg, True))

' Save the signed XML document to a file
Dim xmltw As New XmlTextWriter("...", New UTF8Encoding(False))
doc.WriteTo(xmltw)
xmltw.Close()

To verify the signed XML, we would just have to use back the System.Security.Cryptography.Xml found in the .NET Framework. At least, the .NET stack got the design of the namespaces and the prefixes right.


' Create a new XML document.
Dim xmlDocument As New XmlDocument

' Load the passedXML file into the document.
xmlDocument.Load("...")

' Create a new original SignedXml object and pass it the XML document class.
Dim signedXml As New System.Security.Cryptography.Xml.SignedXml

' Find the "Signature" node and create a new XmlNodeList object.
Dim xmlnsmgr As New XmlNamespaceManager(xmlDocument.NameTable)
xmlnsmgr.AddNamespace("SWM", "http://www.w3.org/2000/09/xmldsig#")

Dim nodeList As XmlNodeList = xmlDocument.SelectNodes("//SWM:Signature", xmlnsmgr)
signedXml.LoadXml(CType(nodeList(0), XmlElement))

myRSA = New RSACryptoServiceProvider
myRSA.FromXmlString("...")

Return signedXml.CheckSignature(a)

You can download my [prefixed-XMLDSIG] custom assembly here. Do let me know if you have any comments or feedback. Enjoy !!!


Read comments or post a reply to : XAdES Interop with XML-DSIG as implemented by the .NET Framework
Page 13471 of 19640

Newest posts
 

    Email TopXML