113

我必须为我公司的网站(作为依赖方)使用 SAML 实施 SSO。一个重要的部分是签名的验证。以下是我们的合作伙伴公司(声明方)的示例 SAML 的签名部分:

<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
 <ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
  <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
  <ds:Reference URI="#_2152811999472b94a0e9644dbc932cc3" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
   <ds:Transforms xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
    <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
     <ec:InclusiveNamespaces PrefixList="ds saml samlp xs" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
    </ds:Transform>
   </ds:Transforms>
   <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
   <ds:DigestValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">bW1Os7+WykqRt5h0mdv9o3ZF0JI=</ds:DigestValue>
  </ds:Reference>
 </ds:SignedInfo>
 <ds:SignatureValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
cgrAN4T/UmobhrkkTi3miiRfbo0Z7aakSZjXuTWlZlu9jDptxPNbOFw8ZbYKZYyuW544wQqgqpnG
gr5GBWILSngURjf2N45/GDv7HMrv/NRMsRMrgVfFsKbcAovQdLAs24O0Q9CH5UdADai1QtDro3jx
nl4x7HaWIo9F8Gp/H1c=
 </ds:SignatureValue>
 <ds:KeyInfo>
  <ds:X509Data>
   <ds:X509Certificate>MIIElzCCA3+gAwIBAgIQNT2i6HKJtCXFUFRB8qYsZjANBgkqhkiG9w0BAQUFADB3MQswCQYDVQQG
    EwJGUjEOMAwGA1UEBxMFUGFyaXMxDDAKBgNVBAoTA3BzYTEgMB4GA1UECxMXY2VydGlmaWNhdGUg
    YXV0aG9yaXRpZXMxKDAmBgNVBAMTH0FDIFBTQSBQZXVnZW90IENpdHJvZW4gUHJvZ3JhbXMwHhcN
    MDkwODE5MDcxNTE4WhcNMTEwODE5MDcxNTE5WjCBhjELMAkGA1UEBhMCZnIxHzAdBgkqhkiG9w0B
    CQEWEHBhc3NleHRAbXBzYS5jb20xGDAWBgoJkiaJk/IsZAEBEwhtZGVtb2IwMDEMMAoGA1UEChMD
    cHNhMREwDwYDVQQLEwhwcm9ncmFtczEbMBkGA1UEAxMSVGVzdCAtIFBBU1NFWFQgREVWMIGfMA0G
    CSqGSIb3DQEBAQUAA4GNADCBiQKBgQCuY1nrepgACvDSTLWk5A1cFOJSwDbl6CWfYp3cNYR0K3YV
    e07MDZn+Rv4jo3SusHVFds+mzKX2f8AeZjkA3Me/0yiS9UpS9LQZu9mnhFlZRhmUlDDoIZxovLXN
    aOv/YHmPeTQMQmJZu5TjqraUq7La1c187AoJuNfpxt227N1vOQIDAQABo4IBkTCCAY0wDgYDVR0P
    AQH/BAQDAgWgMB8GA1UdIwQYMBaAFLceWtTfVeRuVCTDQWkmwO4U01X/MAwGA1UdEwEB/wQCMAAw
    gbYGA1UdIASBrjCBqzCBqAYKKoF6ARfOEAEBBDCBmTBBBggrBgEFBQcCARY1aHR0cDovL3JldW5p
    cy5pbmV0cHNhLmNvbS9hdXRvcml0ZS9QQy1BQy1Qcm9ncmFtcy5wZGYwVAYIKwYBBQUHAgIwSDAK
    FgNwc2EwAwIBARo6UG9saXRpcXVlIGRlIENlcnRpZmljYXRpb24gQUMgUFNBIFBldWdlb3QgQ2l0
    cm9lbiBQcm9ncmFtczBcBgNVHR8EVTBTMFGgT6BNhktodHRwOi8vaW5mb2NlcnQucHNhLXBldWdl
    b3QtY2l0cm9lbi5jb20vQUMtUFNBLVBldWdlb3QtQ2l0cm9lbi1Qcm9ncmFtcy5jcmwwHQYDVR0l
    BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBYGA1UdDgQPBA1BVVRPX0dFTkVSQVRFMA0GCSqGSIb3
    DQEBBQUAA4IBAQCvRtP6bFkOUEHcqc6yUX0Q1Gk2WaAcx4ziUB0tw2GR9I0276JRJR0EGuJ/N6Fn
    3FhLQrSPmS97Xvc9XmiI66fQUdg64g9YqBecdiQlUkR20VLgI6Nq8pldQlWjU2iYlkP15U7VF4Qr
    0Pb2QiIljZUCKdv3qdED2Ri33za46LfykrlwZB0uhTVUxI/AEtjkKVFaZaqanJg+vJyZI5b30z7g
    Ff8L3ht4Z7SFKdmY3IQSGzElIAAUfduzTJX0cwnGSU9D4BJu1BS8hWnYPwhk+nBJ7OFhXdwYQFWq
    fhpBLq+ciJti9OMhcdCSIi0PbrOqzqtX7hZUQOvfShhCTJnl5TJJ</ds:X509Certificate>
  </ds:X509Data>
 </ds:KeyInfo>
</ds:Signature>

我只是不明白的是,为什么证书在签名中?

我的意思是通常我以一种安全的方式从公司获得证书,所以我知道证书来自他们。并且当签名验证成功时,我知道我们的合作伙伴公司已经签名了。

但是当证书在 SAML-Response 的签名中时,任何人都可以发送它!我唯一知道的是回复没有被伪造。但关键是,我不知道是谁发送了 SAML。

谁能向我解释一下,这是如何工作的?

4

4 回答 4

70

SAML 响应带有签名和该签名的公钥。

您可以使用公钥来验证 SAML 响应的内容是否与密钥匹配 - 换句话说 - 该响应肯定来自具有与消息中的公钥匹配的私钥的人,并且该响应尚未篡改。

我不知道您正在使用什么技术,但在 .Net 中您可以像这样检查它:

// load a new XML document
var assertion = new XmlDocument { PreserveWhitespace = true };
assertion.LoadXml("The SAML XML that you were sent");

// use a namespace manager to avoid the worst of xpaths
var ns = new XmlNamespaceManager(assertion.NameTable);
ns.AddNamespace("samlp", @"urn:oasis:names:tc:SAML:2.0:protocol");
ns.AddNamespace("asrt", @"urn:oasis:names:tc:SAML:2.0:assertion");
ns.AddNamespace("dsig", @"http://www.w3.org/2000/09/xmldsig#");

// get nodes down to the signature
var responseNode = assertion.SelectSingleNode("/samlp:Response", ns);
var assertionNode = responseNode.SelectSingleNode("asrt:Assertion", ns);
var signNode = assertionNode.SelectSingleNode("dsig:Signature", ns);

// load the XML signature
var signedXml = new SignedXml(assertion.DocumentElement);
signedXml.LoadXml(signNode as XmlElement);

// get the certificate, basically:
//     signedXml.KeyInfo[0].Certificates[0]
// ...but with added casting
var certificate = GetFirstX509Certificate(signedXml);

// check the key and signature match
bool isSigned = signedXml.CheckSignature(certificate, true);

这只是检查消息是否来自它所说的人。您需要额外检查消息是否来自您信任的人,并且此检查速度较慢 - 它需要包括撤销,并且可能需要验证整个证书链。

通常这将是您将接受 SAML 响应的公钥列表。

然后,您可以检查该消息是否未被篡改,并且来自您信任的人,因此您可以授权提供的 SAML 属性中提供的用户详细信息。

可能已经拥有公钥,这意味着签名不需要再次包含公钥,但您也可能有多个可能的已知发件人,甚至是已知发件人链。

例如,您可能有两个受信任的提供者——在任何一种情况下,在检查您是否信任任一提供者之前,您都要检查消息是否被篡改。如果密钥不在签名中,则断言可能会小一些,但现在您必须提前知道断言来自哪个身份提供者。

所以,实际上,公钥在签名中有两个主要原因:

  1. 篡改检查比身份检查要快,如果知道公钥,就可以隔离。
  2. 如果密钥在断言中,则更容易支持多个身份。
于 2011-05-26T13:11:49.540 回答
54

在 SAML 响应中指定公钥的原因是身份提供者的元数据可以指定多个公钥。这允许身份提供者(断言方)向服务提供者(依赖方)指定正确的公钥,以用于验证 SAML 响应中的签名。

例如,断言方的元数据可能如下所示:

<KeyDescriptor>
    <ds:KeyInfo>
        <ds:X509Data>
            <ds:X509Certificate>BQUAMCMBgN...XerfXHHEZYZs=</ds:X509Certificate>
        </ds:X509Data>
        <ds:X509Data>
            <ds:X509Certificate>H24a88h7zl...2zo28hH5DK78=</ds:X509Certificate>
        </ds:X509Data>
    </ds:KeyInfo>
</KeyDescriptor>

尽管 SAML 2.0 不要求包含公钥,但我还没有遇到任何不将公钥包含在 SAML 响应中的身份提供者。如果断言中没有指定公钥,那么它应该可以通过身份提供者的元数据进行推断。

就信任响应中发送的公钥而言,公钥必须与身份提供者元数据中定义的公钥匹配。这些元数据详细信息通常由希望使用 SSO 访问您的应用程序的客户提供——您将确切知道要查找的公钥(即您可能会要求他们向您提供其身份提供者的元数据 URL,所以您可以获取他们的元数据并下拉相关信息,例如公钥、颁发者端点等)。

如果随签名提供的公钥是元数据中未指定的公钥,则 SAML 系统在验证签名时必须生成错误。

于 2013-06-03T21:54:39.430 回答
9

签名证书的公共部分在 SAML 消息中。这用于检查令牌本身的签名,当然也允许接收者知道是谁发布了令牌并相应地处理它。

它存在的事实是 XML 数字签名规范的一部分,它实际上并不是任何特定于 SAML 的东西。如果没有证书,你怎么知道令牌来自哪里,以及如何验证它?

XmlDSig 确实指定了其他方法,您可以通过主题、序列号、哈希等来识别签名密钥,但这假设接收方拥有公共证书。对于 SAML,情况可能并非如此,因此嵌入了 X509 证书的公共部分。

于 2009-11-09T19:55:58.280 回答
0

身份提供者使用自己的私钥签署了 saml 响应。在注册/SAML 元数据交换阶段,双方共享他们的公钥证书。任何一方都可以拥有多个签名证书,并且可以免费使用其中一个。对应的公钥已经与依赖方共享,因此在 SAML 响应中共享公钥只是通知(在数字验证时使用此证书)给依赖方。

于 2021-03-23T13:08:28.933 回答