I'm working on a SAML gateway using Ruby/Rails and I'm attempting to write some code that validates the xml digital signature of the incoming SAML response against the x509 cert of the originating service.
My problem: the signature depends on a canonicalized version of the XML that is hashed and then signed and I'm having trouble finding a ruby lib/gem that will canonicalize XML per the spec. I found a super old gem on rubyforge that is a mess but I'd be more interested if something like nokogiri supported this kind of functionality (from the nokogiri docs, it doesn't).
I've googled extensively but thought I'd ask around here to see if anyone has any good insights before I go and try to write my own version or rework the existing c14n-r library.
Give these two gems a shot:
http://rubygems.org/gems/coupa-libxml-ruby
http://rubygems.org/gems/xmlsec-ruby
I wrote them for a SAML project. The first patches libxml-ruby to add a binding for the canonicalize function in the base C library.
The latter is ruby binding for xmlsec. Right now all that works is signature verification, which was all I needed for the project, but it sounds like it'd fit your needs too.
I'd recommend going with xmlsec because trying to write your own XML signature verification code is an exercise in futility. Just wait til you have to deal with multiple enveloped signatures, embedded certificates, gah. Let xmlsec handle that crap.
After looking around some more I've found that nokogiri has put c14n support on the todo list for the next release. Don't know more than that-- but it appears that no widely used XML library supports c14n as of June 2010. I'll close this out since nothing really popped up.
I have a ruby/rails Service Provider and a .NET (ComponentSoft) IDP
this worked for me ( I had no issues with the canonicalized version of the XML):
received_certificate = XPath.first(response_document,"//samlp:Response//Signature//KeyInfo//X509Data//X509Certificate").text
def self.verify_signature(received_certificate, idp_certificate_path)
certificate ||= OpenSSL::X509::Certificate.new(File.read(idp_certificate_path))
cert_decoded = Base64.decode64(received_certificate)
cert = OpenSSL::X509::Certificate.new(cert_decoded)
certificate.verify(cert.public_key)
end
The xmlcanonicalizer gem seems to be the most up-to-date ruby canonicaliser available:
https://github.com/andrewferk/xmlcanonicalizer
It does have a bug however, that makes it useless at canonicalising some XML trees. Some kind person has submitted a patch but it hasn't been applied yet:
https://github.com/andrewferk/xmlcanonicalizer/pull/1
This patched gem plus ruby-saml does the trick (plus more, if you're trying to implement SAML SSO:
https://github.com/onelogin/ruby-saml
Hope that helps someone save the 3 days I wasted trying to get things to work! :)
had problems with xmlcanonicalizer.
xmlstarlet worked for me:
`echo "#{xml_str}" | xmlstarlet c14n`
Probably a little late and not really ideal, but this fork uses XMLStarlet via command line for canonicalization.
来源:https://stackoverflow.com/questions/3038757/canonicalizing-xml-in-ruby