На работе у нас есть веб-приложение, которое нам нужно будет связать с веб-приложением другой компании, используя Single Sign On, подтвержденный SAML. Наши веб-приложения написаны на PHP, и, очевидно, не имеет значения, какой язык выбрать другой компании. Тем не менее, мне нужно было написать простой API, который эта другая компания может отправлять SOAP-запросы с запросами SAML и генерировать ответ SAML. Я писал это с нуля по трем причинам: 1) на самом деле не существует много вариантов взаимодействия SAML, написанных на PHP, даже если бы я этого хотел, 2) он ограничивал накладные расходы, связанные с добавлением третьего -партийный компонент и 3) создание вещей с нуля, как правило, оставляет меня с гораздо более глубоким пониманием и делает меня гораздо более способным приспособить вещь в будущем, если это необходимо.
В любом случае, я довольно новичок в стандартах SAML, SOAP и XML в целом, поэтому я как бы учусь, когда я ухожу. У меня API API очень много для наших целей, за исключением того, что другая компания указала, что наш ответ должен быть подписан на цифровой основе сертификатом (и полученный нами запрос будет аналогичным образом подписан в цифровой форме). Поэтому я пытался выяснить, как обрабатывать / генерировать XML-подписи, но, честно говоря, все это немного запутывает, поскольку спецификации W3C не совсем точно читают.
Раздел 5.4.8 утверждений и протокола для документа OAPIS Markup Language (SAML) V1.1 (документ, который я ушел, поскольку другая компания заявила, что они будут использовать v1.1), включает пример подписанный ответ, содержащий подписанное утверждение, которое я собираюсь включить сюда для ссылки:
<Response IssueInstant="2003-04-17T00:46:02Z" MajorVersion="1" MinorVersion="1" Recipient="www.opensaml.org" ResponseID="_c7055387-af61-4fce-8b98-e2927324b306" xmlns="urn:oasis:names:tc:SAML:1.0:protocol" xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> <ds:Reference URI="#_c7055387-af61-4fce-8b98-e2927324b306"> <ds:Transforms> <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"> <InclusiveNamespaces PrefixList="#default saml samlp ds xsd xsi" xmlns="http://www.w3.org/2001/10/xml-exc-c14n#"/> </ds:Transform> </ds:Transforms> <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> <ds:DigestValue>TCDVSuG6grhyHbzhQFWFzGrxIPE=</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue>x/GyPbzmFEe85pGD3c1aXG4Vspb9V9jGCjwcRCKrtwPS6vdVNCcY5rHaFPYWkf+5EIYcPzx+pX1h43SmwviCqXRjRtMANWbHLhWAptaK1ywS7gFgsD01qjyen3CP+m3Dw6vKhaq1ed10BYyrIzb4KkHO4ahNyBVXbJwqv5pUaE4=</ds:SignatureValue> <ds:KeyInfo> <ds:X509Data> <ds:X509Certificate>MIICyjCCAjOgAwIBAgICAnUwDQYJKoZIhvcNAQEEBQAwgakxCzAJBgNVBAYTA1VT ... 8I3bsbmRAUg4UP9hH6ABVq4KQKMknxu1xQxLhpR1y1GPdiowMNTrEG8cCx3w/w==</ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </ds:Signature> <Status><StatusCode Value="samlp:Success"/></Status> <Assertion AssertionID="_a75adf55-01d7-40cc-929f-dbd8372ebdfc" IssueInstant="2003-04-17T00:46:02Z" Issuer="www.opensaml.org" MajorVersion="1" MinorVersion="1" xmlns="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Conditions NotBefore="2003-04-17T00:46:02Z" NotOnOrAfter="2003-04-17T00:51:02Z"> <AudienceRestrictionCondition> <Audience>http://www.opensaml.org</Audience> </AudienceRestrictionCondition> </Conditions> <AuthenticationStatement AuthenticationInstant="2003-04-17T00:46:00Z" AuthenticationMethod="urn:oasis:names:tc:SAML:1.0:am:password"> <Subject> <NameIdentifier Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">scott@example.org</NameIdentifier> <SubjectConfirmation> <ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</ConfirmationMethod> </SubjectConfirmation> </Subject> <SubjectLocality IPAddress="127.0.0.1"/> </AuthenticationStatement> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> <ds:Reference URI="#_a75adf55-01d7-40cc-929f-dbd8372ebdfc"> <ds:Transforms> <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"> <InclusiveNamespaces PrefixList="#default saml samlp ds xsd xsi" xmlns="http://www.w3.org/2001/10/xml-exc-c14n#"/> </ds:Transform> </ds:Transforms> <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> <ds:DigestValue>Kclet6XcaOgOWXM4gty6/UNdviI=</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue>hq4zk+ZknjggCQgZm7ea8fI79gJEsRy3E8LHDpYXWQIgZpkJN9CMLG8ENR4Nrw+n7iyzixBvKXX8P53BTCT4VghPBWhFTSt9tHWu/AtJfOTh6qaAsNdeCyG86jmtp3TDMWuL/cBUj2OtBZOQMFn7jQ9YB7k1Iz3RqVL+wNmeWI4=</ds:SignatureValue> <ds:KeyInfo> <ds:X509Data> <ds:X509Certificate>MIICyjCCAjOgAwIBAgICAnUwDQYJKoZIhvcNAQEEBQAwgakxCzAJBgNVBAYTA1VT ... 8I3bsbmRAUg4UP9hH6ABVq4KQKMknxu1xQxLhpR1y1GPdiowMNTrEG8cCx3w/w==</ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </ds:Signature> </Assertion> </Response>
Итак, как мне сгенерировать что-то вроде этого? И если я получу что-то вроде этого, как его проверить? Кроме того, может ли кто-нибудь предложить только базовый концептуальный обзор того, что теги <ds:Signature>
здесь? Кажется, есть два <ds:Signature>
, один в основном <Response>
и один в <Assertion>
, каждый из которых содержит свои собственные <ds:DigestValue>
, <ds:SignatureValue>
и <ds:X509Certificate>
( и каждый отдельный). Как они генерируются? Любой свет, который вы можете пролить на это, будет высоко оценен. Учебники или примеры кода будут еще более оценены! Но на данный момент, если вы можете просто привести меня на правильный путь, это все, о чем я действительно прошу. Прямо сейчас все это по-прежнему кажется большим черным ящиком для меня.
Кстати, если это помогает, в других разделах спецификации SAML 1.1 говорится, что реализация SAML должна использовать только метод «Исключительная канонизация» (Excl-C14N) и должна использовать только «огибаемое преобразование». Я все еще не совсем уверен, что это значит.
Обработка XML-подписи на самом деле не слишком сложна, если вы хорошо знакомы с XML, но есть много деталей, которые должны быть абсолютно правильными или что-то не работает, поэтому я, вероятно, не стал бы писать собственную реализацию в этом (я реализовал его частично один раз, но это было для другого и специального назначения, и в любом случае это была не полная реализация).
Во всяком случае, я мало что знаю о SAML, но я знаю о XML и подписях XML, поэтому, возможно, я смогу немного помочь вам, постаравшись ответить на ваши вопросы.
Элемент Signature
ссылается на конкретный фрагмент документа XML, который был подписан цифровой подписью в дочернем элементе SignedInfo
. Детский элемент Reference
из этого (я думаю, что может быть много элементов Reference
которые объединяются при формировании байтов, которые будут подписаны, но я не помню точно) указывает на контент через атрибут URI
. Элементы Transform
описывают преобразования, выполняемые на упомянутом контенте, до их хэширования; вам нужно будет изучить спецификации, чтобы выяснить, как определяются алгоритмы преобразования. Элемент DigestMethod
дает алгоритму хеширования применяться к байтам, которые являются результатом этих алгоритмов преобразования (обратите внимание, что одна из них всегда является канонизацией, которая преобразует XML в байты), а DigestValue
дает результат этого алгоритма дайджеста.
Фактическая подпись находится в элементе SignatureValue
и создается путем применения CanonicalizationMethod
элемента CanonicalizationMethod
для создания байтов и последующей подписи этих байтов с помощью SignatureMethod
. Элемент KeyInfo
указывает вам, как найти ключ для использования.
Канонизация, которая появляется несколько раз выше, является просто способом преобразования XML-документа в байты, так что «эквивалентные» XML-документы производят одну и ту же последовательность байтов. Это требуется в цифровой подписи, потому что алгоритмы работают над байтами и XML могут проходить через несколько посредников, которые, вероятно, нарушают исходные байты, но сохраняют эквивалентность. И разные методы канонизации необходимы для разных ситуаций: если элементы извлекаются из документов и помещаются в другие, вам нужна эксклюзивная канонизация, которая удаляет ненужные определения пространства имен, но в других случаях это может работать некорректно, поэтому вам нужна инклюзивная канонизация, которая сохраняет все пространственные пространства имен.
Это всего лишь основы. Существует множество различных опций для создания XML-подписи, и если вы хотите реализовать рабочий верификатор, вам необходимо рассмотреть все из них. Поскольку вы новичок в XML в целом, я просто повторю свой совет по использованию того, что уже существует. Это интересный учебный опыт для реализации спецификации, но часто это пустая трата времени, если реализации уже доступны.
В SimpleSAML есть пример в xmlseclibs.php . Он использует модуль openssl для выполнения криптографии.
Я бы честно использовал этот lib или bridge для java / tomcat, просто потому, что могут возникнуть проблемы с interop, которые необходимо будет отлаживать,
Вы можете взглянуть на эту Java-библиотеку, чтобы подписать пример запроса SAML https://github.com/jrowny/java-saml
Чтобы проверить подпись, вам необходимо установить аддон SAML-трассировщика https://addons.mozilla.org/en-US/firefox/addon/saml-tracer/
Вы можете использовать инструмент https://www.samltool.com/validate_logout_req.php для валидации или подписи запроса https://www.samltool.com/sign_logout_req.php