Канонизация XML в Ruby

Я работаю над шлюзом SAML с использованием Ruby/Rails, и я пытаюсь написать код, который проверяет цифровую подпись xml входящего ответа SAML на сертификат x509 исходной службы.

Моя проблема: подпись зависит от канонизированной версии XML, которая хэшируется, а затем подписана, и мне трудно найти рубиновый lib/gem, который будет канонизировать XML в спецификация. Я нашел супер старый драгоценный камень на rubyforge, который является беспорядком, но мне было бы интересно, если что-то вроде nokogiri поддерживает такую ​​функциональность (от nokogiri docs, это не так).

Я много раз искал Google, но думал, что попрошу здесь посмотреть, есть ли у кого-нибудь хорошие идеи, прежде чем я пойду, и попытаюсь написать свою собственную версию или переработать существующую библиотеку c14n-r.

Ответ 1

Дайте этим двум камням выстрел:

http://rubygems.org/gems/coupa-libxml-ruby

http://rubygems.org/gems/xmlsec-ruby

Я написал их для проекта SAML. Первые исправления libxml-ruby добавят привязку для функции canonicalize в базовой библиотеке C.

Последний является ruby ​​binding для xmlsec. Прямо сейчас все, что работает, - это проверка подписи, которая была всем, что мне нужно для проекта, но похоже, что это тоже соответствовало вашим потребностям.

Я бы порекомендовал идти с xmlsec, потому что попытка написать собственный код проверки подписи XML - это бесполезное упражнение. Подождите, пока вам не придется иметь дело с несколькими окутанными сигнатурами, встроенными сертификатами, gah. Пусть xmlsec справится с этим дерьмом.

Ответ 2

Оглянувшись еще немного, я обнаружил, что nokogiri добавила поддержку c14n в список todo для следующей версии. Не знаю больше этого, но, похоже, что с июня 2010 года ни одна широко используемая библиотека XML не поддерживает c14n. Я закрою это, потому что ничего не появилось.

Ответ 3

У меня есть провайдер услуг Ruby/rails и IDP (ComponentSoft) IDP

это сработало для меня (у меня не было проблем с канонизацией версии 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

Ответ 4

Вероятно, немного поздно и не совсем идеально, но этот вилка использует XMLStarlet через командную строку для канонизации.

Ответ 5

Кажется, что камень xmlcanonicalizer является самым современным руниновым канонизатором:

https://github.com/andrewferk/xmlcanonicalizer

У этого есть ошибка, которая делает это бесполезным при канонизации некоторых деревьев XML. Какой-то человек подал патч, но он еще не был применен:

https://github.com/andrewferk/xmlcanonicalizer/pull/1

Этот исправленный жемчуг плюс ruby-saml делает трюк (плюс больше, если вы пытаетесь реализовать SAML SSO:

https://github.com/onelogin/ruby-saml

Надеюсь, что кто-то поможет сохранить 3 дня, которые я потратил впустую, пытаясь заставить все работать!:)

Ответ 6

возникли проблемы с xmlcanonicalizer.

xmlstarlet работал у меня:

`echo "#{xml_str}" | xmlstarlet c14n`