DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
View Events Video Library
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Integrating PostgreSQL Databases with ANF: Join this workshop to learn how to create a PostgreSQL server using Instaclustr’s managed service

Mobile Database Essentials: Assess data needs, storage requirements, and more when leveraging databases for cloud and edge applications.

Monitoring and Observability for LLMs: Datadog and Google Cloud discuss how to achieve optimal AI model performance.

Automated Testing: The latest on architecture, TDD, and the benefits of AI and low-code tools.

Related

  • Automate Migration Assessment With XML Linter
  • Validate XML Request Against XML Schema in Mule 4
  • How To Get the Comments From a DOCX Document in Java
  • Exploring Hazelcast With Spring Boot

Trending

  • Software Verification and Validation With Simple Examples
  • Build a Serverless App Fast With Zipper: Write TypeScript, Offload Everything Else
  • GenAI-Infused ChatGPT: A Guide To Effective Prompt Engineering
  • A Guide to Data-Driven Design and Architecture
  1. DZone
  2. Coding
  3. Languages
  4. XML Digital Signatures and JAXB: The Less DOMinant Approach

XML Digital Signatures and JAXB: The Less DOMinant Approach

Working with the XML Digital Signature Standard should be a straight-forward affair, but if you're using JAXB instead of DOM, what can you do? This article details my journey of trying to get these two technologies to play nicely together.

Duncan Brown user avatar by
Duncan Brown
·
Apr. 06, 16 · Tutorial
Like (4)
Save
Tweet
Share
19.20K Views

Join the DZone community and get the full member experience.

Join For Free
(NOTE: The final version of the code can be found here. Feel free to make use of it if you need to!)

I recently had the opportunity to deal with the legacy XML Digital Signature Standard from our good friends over at the W3C as part of a project I'm working on that requires sending signed XML (SOAP) documents over the wire.

This project also entails assembling an involved SOAP message that has a very large schema, which was provided to me by the receiving party. One look at said schema and I knew I was not about to spend my time using straight DOM manipulation to create these documents, so I turned to my old friend, JAXB, given that Java was the platform being used.

No problem, right?

Wrong.

Why wrong? Because the usual examples of the XML DSig library in Java make use of DOM libraries, which I was looking to avoid. Figures. Not to mention that the location of the signature was a non-standard location; at least, non-standard as far as the DSig libraries were concerned. The signature block had to be contained within the SOAP Header element, within a SOAP Security element, as opposed to being enveloped or enveloping with the signed document itself.

(Side note: If anyone knows how to customize the above, I'm all ears.)

In my specific case, only the SOAP Body element needed to be signed.

This article details my journey in trying to get this all to work.

First Pass: Manual Signature Generation

Assembling the body of the document and the overall SOAP message was a piece of cake using JAXB. JAXB's Maven plugin made it easy to generate all of the classes I needed to create the document. And given that I had the DSig spec handy, I figured it would just be a matter of following some instructions to sign the document.

Boy was I wrong.

The biggest issue with this approach was validating the hashes for the digest and the signature. While I did have a sample valid signed document, there was no way to systematically determine what any discrepancies were, other than following a "trial and error" method.  

That "method" quickly wore thin.

The spec, while detailed, does not exactly make it easy to follow and comprehend unambiguously—Should the digest include the starting and ending elements, before canonicalization? Etc.

Having had enough of this approach, it was time to move on to the second one.

Second Pass: Integrate the Standard Java XML DSig Library

I wondered if there was a way to combine the JAXB approach with the standard XML DSig library without needing to use the DOM.

So I set forth and tried to make this idea happen.

I figured out that I could marshal my SOAP envelope (generated by JAXB) into a DOMResult, so I would only need to briefly work with the DOM in order to accomplish my goals.

Awesome, I can handle that!

And then, like on the bridge of the Starship Enterprise, red alerts went off.

(Or at least my JUnit test bar turned red. Close enough.)

Since I had a self-signed certificate, I had been loading it in via an InputStream in a typical fashion, and then handing it off to the DSig library to deal with it.

As it turns out, I encountered an extremely weird exception; namely, that as the library was attempting to transform the certificate data into an X509Data element, it was throwing a ClassCastException. Looking into it after digging around online for the source and confirming by decompiling the class in question, I discovered that, for some very odd (and still-unexplained at the time of writing) reason, what I had passed in was not being detected as being a descendent of X509Certificate, when it very clearly was. In fact, after copying the offending code into my own project and running it there, the exception was never hit.

So it seemed to me that whatever the code throwing the exception was expecting, it had to somehow be getting an actual X509Certificate and not some descendent.

To side-step this issue, I acquiesced to Oracle's example code and loaded the certificate/key pair thusly.

The big catch was that I had to now convert my certificate/key into a JKS-formatted keystore. That part actually wasn't so bad after I did some digging online.

With this fix, my digest hash was now passing.  

Courtesy: frinkiac.com

(Courtesy: frinkiac.com)

But I was faced with a few new challenges.  

Image title

(Courtesy: frinkiac.com)

Third Pass: Fixing Bugs and Outputting the Result

With the signed document, I still had to get the DOM-based result into the original SOAP envelope, which, as you will recall, is a JAXB-based structure.

After puzzling over this for a short while, I tried the following steps:

  1. Transform the appropriate portion of the DOM (i.e. the one containing the Signature) into an OutputStream.

  2. Pipe the OutputStream from above into an InputStream.

  3. Unmarshal the InputStream from above into a JAXB-based Signature class.

  4. Insert the Signature class from above into the appropriate place in the original SOAP envelope.

Turns out this worked out just fine!

As for bugs, I'll just list them off here to save some time:

  • Unable to find internal reference. It is possible to reference a specific section within your original XML document that is to be signed, via XPath or even using the "id" attribute. When using the latter, it seems that JAXB does not preserve the fact that an "id" attribute has a specific meaning with the DOM during marshaling. This can be solved with the following code:

// replace the first line below with the path to the element within the document you wish to refer to
Element el = (Element)doc.getFirstChild().getFirstChild().getNextSibling();
el.setIdAttribute("id", true);
  • RSA Signature Did Not Verify. This can be a pain, but assuming your certificate/key pair is setup and verified, it is more than likely an issue of the signed block not matching what actually appears in your submitted document. In my case, because I had to move the signed document out of the DOM and back into my JAXB structure, JAXB, by default, includes the namespace prefixes as part of the element names when marshaling, whereas the DOM object, by default, does not. By editing the appropriate package-info.java file (protip: Keep your DSig namespace in its own package), I was able to suppress the namespace prefix and voila!

With these issues solved, I finally had a working implementation!

Conclusion

Working with this spec wasn't easy, but really only because I had chosen to use JAXB instead of a more traditional DOM-based approach.

I didn't find a lot of help online specifically detailing how to work with the DSig library and JAXB—at least none that helped me get to where I had to go.

I hope this article helps out some other souls who encounter this situation. Good luck!

XML

Opinions expressed by DZone contributors are their own.

Related

  • Automate Migration Assessment With XML Linter
  • Validate XML Request Against XML Schema in Mule 4
  • How To Get the Comments From a DOCX Document in Java
  • Exploring Hazelcast With Spring Boot

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: