Have you ever had the need to verify the signature of an XML document? Yes? Then I have bad news for you - the library you used to accomplish that task is sabotaging your work!
Doing all that cryptography is hard, and that's why you're offloading it to a library. It's a wise move! Sadly, that library is not helping you.
Just look at its documentation! The examples span across tens of lines, and the README (hopefully) mentions at least a couple of things like this:
"If you want to be sure that the data you're consuming has been signed, don't forget to call the method that validates the reference."
"If you want to be sure that the data you're consuming has been signed, don't forget to make sure that the node you're consuming equals the referenced node."
"If you want to be sure that the data you're consuming has been signed, don't forget to call the method that validates the signature."
"If you want to be sure that the data you're consuming has been signed, don't use the method we for some reason provide and which reads the public key from the payload."
"If you want to be sure that the data you're consuming has been signed, make sure your XPath queries are not reaching nodes that were removed in the canonicalization phase just before the digest was calculated."
Whoa! 😱 What?! 🤯
If you're like me when I first stumbled upon XML signatures years ago, you may be asking yourself questions along the lines of:
"Isn't checking the signature enough? Why do I have to additionally check the validity some reference?"
"How do I compare some node to the referenced node?"
"What does reference even mean in this context?"
"So you're giving me some method and then telling me it's not safe to call it?"
"Canonica... What? What digest? Where? What should I do with it? Why do I even have to think about it myself?! Wasn't this library supposed to help me?"
Not only are the examples convoluted, but they're incomplete and can make your app vulnerable!
You. Deserve. Better!
You don’t have to simply accept the fact that the library you’re using is working against you.
Just imagine how much easier your life as a developer would be if you could simply write:
node = getTheOnlySignedNodeOrNull(xml, publicKey)
Imagine node being either null or an XML node that's for sure entirely signed with the given public key.
Imagine not worrying anymore about things like:
- Are both the reference and signature validated?
- Is this what was referenced?
- Is this part of the signed node actually signed, or is this something that's been stripped in the canonicalization phase?
- Is the public key trusted, or was it supplied by the attacker?
It'd be so much easier! So much safer!
And if you needed to read a couple of signed nodes, you could simply call:
nodesArray = getSignedNodes(xml, publicKey)
I know, your library doesn't like look like that. But you can do something to fix it, even if you’re not a security expert yourself! If it’s on GitHub, simply open an issue describing the problem and propose adding the safer API described above. Feel free to link to this blog post.
You don’t have to invest too much time to get the discussion going. And once people are talking about it, someone will implement the fix. Maybe it will even be you!
Let’s make the internet more secure!