SAML: Почему сертификат в подписи?
Я должен внедрить SSO с SAML для веб-сайта моей компании (в качестве проверяющей стороны). Неотъемлемой частью курса является проверка подписи. Вот часть подписи образца 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.
Может кто-нибудь объяснить мне, как это работает?
5 ответов
Ответы 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.
У вас уже может быть открытый ключ, это означает, что подпись не должна снова включать открытый ключ, но вы также можете иметь несколько возможных известных отправителей или даже цепочку известных отправителей.
Например, у вас может быть два доверенных поставщика - в любом случае вы проверяете, что сообщение не было подделано, прежде чем проверять, доверяете ли вы какому-либо поставщику. Если ключ отсутствует в подписи, утверждения могут быть немного меньше, но теперь вы должны заранее знать, от какого поставщика удостоверений получено утверждение.
Итак, действительно, есть две основные причины, по которым открытый ключ находится в подписи:
- Проверка несанкционированного доступа выполняется быстрее, чем проверка личности, и ее можно изолировать, если известен открытый ключ.
- Несколько идентификаторов гораздо проще поддерживать, если ключ находится в утверждении.
Причина, по которой указан ключ, заключается в том, что в метаданных поставщика удостоверений можно указать несколько ключей подписи, и вы можете указать ключ для использования, включив его в подпись. 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 должна генерировать ошибку при проверке подписи.
Открытая часть сертификата подписи находится в сообщении SAML. Это используется для проверки подписи для самого токена и, конечно, для того, чтобы получатели могли сказать, кто выдал токен, и соответственно обработать его.
Тот факт, что он там есть, является частью спецификаций цифровой подписи XML, но на самом деле это не что-то особенное для SAML. Без сертификата, как вы могли бы узнать, откуда взялся токен, и как вы могли бы его проверить?
XmlDSig действительно определяет другие методы, вы можете идентифицировать ключ подписи по теме, серийному номеру, хешу и т. Д., Но это предполагает, что принимающая сторона имеет открытый сертификат. Для SAML это может быть не так, поэтому встраивание публичной части сертификата X509.
Публикация довольно поздно, но мне пришлось работать над 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
Поставщик удостоверений подписал ответ saml, используя собственный закрытый ключ. и на этапе регистрации / обмена метаданными SAML Обе стороны обмениваются сертификатами открытого ключа друг с другом. Любая сторона может иметь несколько сертификатов подписи, и использовать один из них можно бесплатно. Соответствующий открытый ключ уже предоставлен проверяющей стороне, поэтому предоставление открытого ключа в ответе SAML является просто уведомлением (используйте этот сертификат при цифровой проверке) для проверяющей стороны.