Какая правильная XML исключительная канонизация? - PullRequest
1 голос
/ 04 февраля 2010

Я использую xmlseclibs , чтобы попытаться подписать документ SOAP, но, похоже, он не может канонизировать вещи одинаково в зависимости от того, подписываю я или проверяю.

Я приведу вам пример. Это XML, который я пытаюсь подписать:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" MajorVersion="1" MinorVersion="1" IssueInstant="2010-02-04T15:27:43Z" ResponseID="pfxe85313e6-e688-299a-df06-30f55e24f65a">
<samlp:Status>
<samlp:StatusCode Value="samlp:Requester"/>
</samlp:Status>
</samlp:Response>
</soapenv:Body>
</soapenv:Envelope>

Я получил некоторый код, работающий на PHP, чтобы подписать его, используя комбинацию сертификатов открытого ключа и закрытого ключа, и это, похоже, сработало. Он добавил элемент <ds:Signature> со всем необходимым, и выглядел великолепно. Но затем я протестировал его, сразу же попытавшись проверить его после подписания, снова с помощью xmlseclibs (и сертификата открытого ключа), но проверка не удалась. Таким образом, одна и та же библиотека кода выполняет как подпись, так и проверку, но по каким-то причинам эти два процесса не согласуются.

Я добавил некоторый отладочный код в xmlseclibs, чтобы выяснить, что он делает, и я понял, что причина, по которой ключ подписи и ключ валидации различаются, заключается в том, что он канонизирует вещи по-разному в двух ситуациях , Когда я говорю ему подписать элемент <samlp:Response>, это каноническая форма, которую он подписывает (я добавил здесь новые строки для удобства чтения):

<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" IssueInstant="2010-02-04T15:27:43Z" MajorVersion="1" MinorVersion="1" ResponseID="pfxe85313e6-e688-299a-df06-30f55e24f65a" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
<samlp:Status>
<samlp:StatusCode Value="samlp:Requester">
</samlp:StatusCode>
</samlp:Status>
</samlp:Response>

Однако, когда дело доходит до проверки подписи, это каноническая форма, которую он вычисляет для проверки (опять же, я добавил новые строки здесь):

<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" IssueInstant="2010-02-04T15:27:43Z" MajorVersion="1" MinorVersion="1" ResponseID="pfxe85313e6-e688-299a-df06-30f55e24f65a">
<samlp:Status>
<samlp:StatusCode Value="samlp:Requester">
</samlp:StatusCode>
</samlp:Status>
</samlp:Response>

Итак, как вы можете видеть, в этой версии атрибут xmlns:saml отсутствует в элементе <samlp:Response>, а в первом - нет. (Обратите внимание, что это отличается от атрибута xmlns:samlp, который включен в оба.) Это довольно ясно похоже на ошибку в xmlseclibs, но, тем не менее, я бы с удовольствием ее исправил, если бы знал, какая каноническая форма была правильный. Должен ли этот атрибут быть исключен путем исключительной канонизации? Или это должно быть включено? Какая является правильной эксклюзивной канонической формой?

Ответы [ 2 ]

3 голосов
/ 04 февраля 2010

Не правильная каноническая форма!

XML подписи имеет объявление пространства имен, которое следует после атрибутов, не относящихся к пространству имен, что нарушает правило порядка документов:

Узлы пространства имен имеют меньший порядок документов, чем узлы атрибутов.

В проверочном XML полностью отсутствует узел пространства имен saml. Каноникализация не удаляет узлы пространства имен только потому, что нет дочернего контента, который ссылается на них. Он удаляет только избыточные узлы пространства имен (т. Е. Пространства имен, которые уже действовали на родительском объекте).

Я не знаю достаточно о xmlseclibs, чтобы сказать, почему это происходит, но это определенно неправильно в обоих случаях. FWIW функция c14n в моем DOM здесь говорит:

<samlp:Response xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" IssueInstant="2010-02-04T15:27:43Z" MajorVersion="1" MinorVersion="1" ResponseID="pfxe85313e6-e688-299a-df06-30f55e24f65a">
<samlp:Status>
<samlp:StatusCode Value="samlp:Requester"></samlp:StatusCode>
</samlp:Status>
</samlp:Response>

eta: я только что посмотрел на xmlseclibs.php в SVN, и это не легко исправить, поскольку его нынешний подход в корне ошибочен. Он пытается создать «канонизированный» DOM, а затем сериализует его с простым старым saveXML(). Поскольку существуют правила сериализации C14N для порядка атрибутов и экранирования символов, которым saveXML не обещает следовать, это никак не сработает.

2 голосов
/ 04 февраля 2010

Вы неправильно создаете документ DOM и пытаетесь использовать недопустимое дерево в памяти. Либо сериализуйте и используйте сериализованный результат, либо правильно создайте объявления пространства имен в дереве, прежде чем пытаться подписать. См. Сообщение об ошибке для получения дополнительной информации: http://code.google.com/p/xmlseclibs/issues/detail?id=6

...