我必须为我公司的网站(作为依赖方)使用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。
任何人都可以向我解释一下这是如何运作的吗?
答案 0 :(得分:58)
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 :(得分:33)
指定密钥的原因是身份提供程序的元数据可以指定多个签名密钥,您可以通过将密钥包含在签名中来指定要使用的密钥。 SAML 2.0要求如果未使用Assertion
指定密钥,则可以通过上下文(来自断言方的元数据)来推断它。
例如,您可以在断言方的元数据中使用此功能:
<KeyDescriptor>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
BQUAMCMxITAfBgNVBAMTGGlkcDEudGFuZ29oZWFsdGhkZW1vLmNvbTAeFw0xMzA1
...snip...
ttHq2Wi5J7img1M2zo28hH5DK78S+XerfXHK2HEZYZs=
</ds:X509Certificate>
</ds:X509Data>
<ds:X509Data>
<ds:X509Certificate>
H24a88h7zlq+pnAxQm0CAwEAAaN3MHUwVAYDVR0RBE0wS4IYaWRwMS50YW5nb2hl
...snip...
mg1M2zo28hH5DK78=
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</KeyDescriptor>
签名的每个XML元素都可以指定用于签名的密钥。但是,对于SAML 2.0的情况,该签名密钥必须(例如)匹配生成签名的一方在元数据中定义的一个。如果随签名提供的密钥不可信(在本例中未在元数据中指定),则SAML系统在验证签名时必须生成错误。
答案 2 :(得分:9)
签名证书的公共部分位于SAML消息中。这用于检查令牌本身的签名,当然也允许接收者告知谁发出令牌并相应地对其进行处理。
事实上它存在于XML数字签名规范的一部分,它实际上并不是SAML特有的。如果没有证书,您如何知道令牌的来源,以及如何验证它?
XmlDSig确实指定了其他方法,您可以通过主题,序列号,哈希等来识别签名密钥,但这假设接收方具有公共证书。对于SAML,情况可能并非如此,因此嵌入了X509证书的公共部分。
答案 3 :(得分:0)
发帖很晚但我不得不在SAML上工作并找到这些文件。他们对SAML有很好的了解 - 它是如何工作的以及它所期望的参数。应该为其他SAML新手提供一些帮助。
http://developers.onelogin.com/v1.0/page/intro-to-onelogins-open-source-saml-toolkits
http://developers.onelogin.com/v1.0/page/saml-toolkit-for-ruby-on-rails
答案 4 :(得分:0)
身份提供者使用自己的私钥对 saml 响应进行签名。在注册/SAML 元数据交换阶段,双方共享他们的公钥证书。任何一方都可以拥有多个签名证书,并且可以免费使用其中一个。对应的公钥已经与依赖方共享,因此在 SAML 响应中共享公钥只是通知(在数字验证时使用此证书)给依赖方。