Что мне нужно знать о подписях XML для работы SAML?

На работе у нас есть веб-приложение, которое нам нужно будет связать с другим веб-приложением компании, используя 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">[email protected]</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 должна использовать только метод "Exclusive Canonicalization" (Excl-C14N) и должна использовать только "огибаемое преобразование". Я все еще не совсем уверен, что это значит.

Ответы

Ответ 1

Обработка XML-подписи не слишком сложна, если вы хорошо знакомы с XML, но есть много деталей, которые должны быть абсолютно правильными или что-то не работает, поэтому я, вероятно, не стал бы писать собственные (я реализовал его частично один раз, но это было для другого и специального назначения, и в любом случае это была не полная реализация).

В любом случае, я мало что знаю о SAML, но я знаю о XML и XML-подписях, поэтому, возможно, я смогу немного помочь вам, поставив ответ на ваши вопросы.

Элемент

A Signature относится к определенному фрагменту документа XML, который был подписан цифровой подписью в дочернем элементе SignedInfo. Детский элемент Reference этого (я думаю, что может быть много элементов Reference, которые объединяются при формировании байтов, которые будут подписаны, но я не помню точно) указывает на контент с помощью атрибута URI. Элементы Transform описывают преобразования, выполняемые на упомянутом контенте до их хэширования; вам нужно будет изучить спецификации, чтобы выяснить, как определяются алгоритмы преобразования. Элемент DigestMethod дает алгоритм хеширования применяться к байтам, являющимся результатом этих алгоритмов преобразования (обратите внимание, что одна из них всегда является канонизацией, которая преобразует XML в байты), а DigestValue дает результат этого алгоритма дайджеста.

Фактическая подпись находится в элементе SignatureValue и создается путем применения канонификации элемента CanonicalizationMethod для создания байтов и последующей подписи этих байтов с помощью SignatureMethod. Элемент KeyInfo указывает вам, как найти используемый ключ.

Canonicalization, которая появляется несколько раз выше, является просто способом преобразования XML-документа в байты, так что "эквивалентные" XML-документы создают одну и ту же последовательность байтов. Это требуется в цифровой подписи, потому что алгоритмы работают над байтами и XML могут проходить через несколько посредников, которые, вероятно, нарушают исходные байты, но сохраняют эквивалентность. И разные методы канонизации необходимы для разных ситуаций: если элементы извлекаются из документов и помещаются в другие, вам нужна эксклюзивная канонизация, которая удаляет ненужные определения пространства имен, но в других случаях это может работать некорректно, поэтому вам нужна инклюзивная канонизация, которая сохраняет все пространственные пространства имен.

Это всего лишь основы. Существует множество различных опций для создания XML-подписи, и если вы хотите реализовать рабочий верификатор, вам необходимо рассмотреть все из них. Поскольку вы новичок в XML в целом, я просто повторю свой совет по использованию того, что уже существует. Это интересный опыт обучения для реализации спецификации, но часто это пустая трата времени, если реализации уже доступны.

Ответ 2

Вот пример в xmlseclibs.php в SimpleSAML. Он использует модуль openssl для выполнения криптографии.

Я бы честно использовал этот lib или bridge для java/tomcat, просто потому, что могут возникнуть проблемы взаимодействия, которые необходимо будет отлаживать,

Ответ 3