我需要了解什么关于XML签名才能使SAML正常工作?

19

在工作中,我们有一个Web应用程序,需要使用经过SAML验证的单点登录与另一家公司的Web应用程序进行接口。我们的Web应用程序是用PHP编写的,显然,另一家公司选择的语言并不重要。尽管如此,我需要编写一个简单的API,让这个其他公司可以向其中发送带有SAML请求的SOAP请求,并生成一个SAML响应返回。我之所以从头开始编写它,有三个原因:1)即使我想要使用SAML交互的选项似乎也不多,2)它限制了添加另一个第三方组件所需的开销,以及3)从头开始创建通常会让我对事物有更好的理解,如果需要的话,也会让我更有能力适应它。

无论如何,我对SAML、SOAP和XML标准都相当陌生,所以我只能边学边做。我已经基本完成了我们的目的的API,唯一的例外是,另一家公司已经指定我们的响应将需要使用证书进行数字签名(我们接收到的请求同样也会被数字签名)。因此,我一直在努力弄清楚如何处理/生成XML签名,但老实说,W3C规范并不是易读的。

OASIS安全标记语言(SAML)V1.1的声明和协议的第5.4.8节文件中(我一直在使用这个文件,因为另一家公司说他们将使用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>
那么我该如何生成像这样的东西?如果我收到像这样的东西,该如何验证它?还有人能给出一个基本的概念概述吗?这里的标签是什么?似乎在主要的和中都有两个标签,每个都包含自己的、和(并且各自不同)。这些是如何生成的?你能为此提供任何帮助吗?教程或代码示例将更加感激!但现在,如果你能给我一点方向,那就是我真正想要的。目前,所有这些对我来说似乎仍然是一个大黑盒子。

顺便说一下,如果有帮助的话,在SAML 1.1规范的其他地方指出,SAML实现应仅使用“独占规范化”方法(Excl-C14N),并且应仅使用“包含的转换”。我仍然不完全确定这是什么意思。

3个回答

35

如果您对XML非常熟悉,那么处理XML签名并不是太困难,但是有很多细节必须完全正确才能正常工作。因此,在这种情况下,我可能不会尝试编写自己的实现(我曾经部分实现过一次,但那是为了不同的特殊目的,而且它也不是完整的实现)。

无论如何,我对SAML不是很了解,但我了解XML和XML签名,因此也许我可以通过回答您的问题来帮助您。

Signature元素指的是已经在其SignedInfo子元素中数字签名的XML文档的特定部分。该元素的Reference子元素(我认为可以有许多Reference元素在形成要签名的字节时连接起来,但我不再确定)通过URI属性指向内容。 Transform元素描述了在对所引用的内容进行哈希之前执行的变换; 您需要查看规范以确定如何定义变换算法。 DigestMethod元素给出应用于这些变换算法的结果字节的哈希算法(请注意,其中一个始终是将XML转换为字节的规范化),而DigestValue则给出该摘要算法的结果。

实际签名在SignatureValue元素中,通过应用CanonicalizationMethod元素的规范化来生成字节,然后使用SignatureMethod对这些字节进行签名。 KeyInfo元素告诉您如何找到要使用的密钥。

规范化(Canonicalization)指的是将XML文档转换为字节的一种方法,以便“等效”的XML文档产生相同的字节序列。数字签名需要这样做,因为算法处理的是字节,而XML可能通过许多中间人,这些中间人可能会破坏原始字节但会保留等价性。不同的规范化方法适用于不同的情况:如果从文档中提取元素并放置到其他文档中,则需要使用排他规范化来去除不需要的命名空间定义,但在其他情况下这可能不起作用,因此需要使用包容规范化,以保留所有受控的命名空间。

这只是基础知识。如何生成XML签名有许多不同的选项,如果您想实现有效的验证器,您需要考虑所有选项。由于您对XML总体上还不熟悉,我建议您使用已经存在的东西。实现规范是一个有趣的学习经历,但如果已经有实现,则通常是浪费时间。

W3C的文档介绍了签名。


当您在签名信息元素的规范化方法元素中指定了规范化算法时,为什么还需要在转换元素中再次指定它? - Ashwin
1
@Ashwin:SignedInfo中的CanonicalizationMethod是应用于SignedInfo元素的,转换中的任何规范化都应用于所引用的内容,因此它们适用于不同的事物,这就是为什么你需要两者的原因。另外,签名内容不需要是XML,因此规范化不一定适用。 - JaakkoK
谢谢您的回复 :) 我还有一个困惑的地方。我需要在转换元素中使用XSLT。但是没有Java中如何使用它的示例。如果可能的话,您能否提供一段示例代码或指向一个在Java中使用XSLT进行XML签名的链接。 - Ashwin
@Ashwin:我并没有真正使用过XML签名,所以我不知道如何做。而且,那已经离这个问题有点远了;也许你应该提一个新的问题? - JaakkoK

2
SimpleSAML中的xmlseclibs.php文件中有一个示例。它依赖于openssl模块来执行加密操作。我会诚实地使用该库或者桥接到Java/Tomcat,因为可能会出现需要调试的交互问题。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接