Blog Home  Sign In RSS 2.0 Atom 1.0 CDF  

  def Softwaremaker() :
         return "William Tay", "<Challenging Conventions />"

  knownType_Serialize, about = Softwaremaker()
 

 Wednesday, February 08, 2006
« Datasets in Distributed Systems Design, ... | Main | See Dick Shoot »

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-Digital Signature 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 XML Advanced Electronic Signatures (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 XML Advanced Electronic Signatures (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 .

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 has ONLY implemented the XML Digital Signature in this assembly.


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(myRSA)

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

[AUTHOR UPDATE]:


I have spoken to a few experts [on the standards body] about this and it seems that the concensus is that the prefix is NOT needed at all.

The XAdES specifications did not EXPLICITLY state that the prefix is needed so I don't see how the conclusions are drawn that prefixes are fixed. Maybe I am missing something.

It looked to me like all the spec was saying was that the *examples* used those prefixes.

It strikes me as surprising that any specification worth its salt would specify a *fixed prefix*. It would have been too restrictive and not something that many vendors would agree and abide.

I have advised the other party to check with the other parties/vendors for this. In the meantime, I will pull this assembly offline until I get better clarifications.


 

Wednesday, February 08, 2006 1:18:02 PM (Malay Peninsula Standard Time, UTC+08:00)  #    Disclaimer  Comments [12]
  • Blog reactions