1

Peoples,

I have been through the posts here and the example code for handling digital signatures when using JAXB and am running into an issue with what I believe is the introduction of namespaces to the "SignedInfo" element by JAXB marshalling.

I have defined an XSD that will be used by multiple applications implemented in different programming languages. I compile the XSD to JAXB annotated classes for use by my implementation (Jersey JAX-RS and JAX-WS). The flow I currently have is the following:

  1. JAXB object is created with appropriate data or delivered from a remote application.
  2. Marshall JAXB to DOM for signing as described by Blaise Doughan.
  3. Sign DOM using private key creating Enveloped signature.
  4. Unmarshall DOM to JAXB for use in JAX-RS/WS messaging.

I was forced to add an "xsd:any" element at the end of my parent element in my XSD definition for the DOM to JAXB unmarshalling to work, otherwise the embedded "Signature" element was dropped. I also made the JAXBContext aware of the xmldsig namespace.

The following sequence of steps works: JAXB -> DOM -> Sign -> Validate

So I know the signing is working properly. However, the following sequence fails validation: JAXB -> DOM -> Sign -> JAXB -> DOM ->Validate

After some testing and reading my guess is that the modification of the "SignedInfo" by the JABX Marshaller is causing the issue as it is adding namespace prefixes to all the xmlsig elements.

Here is the DOM generated XML (abbreviated):

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
        <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
        <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
        <Reference URI="">
            <Transforms>
                <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512"/>
            <DigestValue>...</DigestValue>
        </Reference>
    </SignedInfo>
    <SignatureValue>...</SignatureValue>
    <KeyInfo>
        <X509Data>
            <X509SubjectName>...</X509SubjectName>
            <X509Certificate>...</X509Certificate>
        </X509Data>
    </KeyInfo>
</Signature>

And here is the element after being marshalled from JAXB (ns2 is defined in the parent element):

<ns2:Signature>
    <ns2:SignedInfo>
        <ns2:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
        <ns2:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
        <ns2:Reference URI="">
            <ns2:Transforms>
                <ns2:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
            </ns2:Transforms>
            <ns2:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512"/>
            <ns2:DigestValue>...</ns2:DigestValue>
        </ns2:Reference>
    </ns2:SignedInfo>
    <ns2:SignatureValue>...</ns2:SignatureValue>
    <ns2:KeyInfo>
        <ns2:X509Data>
            <ns2:X509SubjectName>...</ns2:X509SubjectName>
            <ns2:X509Certificate>...</ns2:X509Certificate>
        </ns2:X509Data>
    </ns2:KeyInfo>
</ns2:Signature>

Am I correct in my assumption that this is the reason for the validation failure?

Is there a way to leave the "Signature" element untouched when using JAXB?

Is there a CanonicalizationMethod that will ignore any namespace prefixes in the calculations?

Also, if the namespace prefix in the signed XML is to change would this also fail validation (for example, from ns1 to abc)? I am wondering if as other applications serialize/deserialize the XML and perhaps change the namespace prefix would the digital signature be invalidated?

Thank you for any help!

John

Community
  • 1
  • 1
Hacksaw
  • 69
  • 1
  • 13
  • I have solved this issue with this approach: http://stackoverflow.com/a/42988447/1527542 – Gauss Mar 24 '17 at 17:25

2 Answers2

0

I spent many hours today trying to find a way to customize JAXB to solve this problem.

Technically, the XML gererated by JAXB is correct, but there are some servers that expects the namespace to be together with its element and without prefixes (Signature, in our case).

The only solution i found was to replace the namespace prefix manually:

xml = xml.replace(" xmlns:ns2=\"http://www.w3.org/2000/09/xmldsig#\"", "");
xml = xml.replace("<ns2:Signature>",
        "<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\">");
xml = xml.replace("ns2:", "");

Before

<nfeProc versao="3.10" xmlns="http://www.portalfiscal.inf.br/nfe" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#">
...
<ns2:Signature>
<ns2:SignedInfo>
<ns2:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>

After:

<nfeProc versao="3.10" xmlns="http://www.portalfiscal.inf.br/nfe">
...
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
  • I had thought about doing similar so thank you for validating this approach. I ended up cheating. See below for what I did. – Hacksaw Apr 05 '16 at 15:35
0

I ended up cheating and instead of including the Signature element directly in my XML, I gzip'ed then mime encoded the Signature and included it in a string element. I also did the same for the document I was signing since namespace manipulation was occurring on it as well. This resulted in an outer XML document containing naming and meta-data about the included inner (mime encoded) XML document and (mime encoded) digital Signature. I used DOM serialization of the inner document and Signature before mime encoding to preserve the namespaces, and then let JAXB handle serialization of the outer document with included mime contents. Works like a charm and using gzip before mime really reduced my document sizes. Only down side is you can no longer view the inner XML documents until you decode them.

Hacksaw
  • 69
  • 1
  • 13