web-dev-qa-db-fra.com

SAML: Pourquoi le certificat est-il dans la signature?

Je dois implémenter l'authentification unique avec SAML pour le site Web de mon entreprise (en tant que partie de confiance). Une partie essentielle du cours est la vérification de la signature. Voici la partie signature d'un exemple de SAML de notre société partenaire (revendicateur):

<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>

Ce que je ne comprends tout simplement pas, c'est pourquoi le certificat se trouve-t-il dans la signature?

Je veux dire généralement que je reçois un certificat de la société de manière sécurisée, alors je sais que le certificat vient d’eux. Et lorsque la vérification de la signature est réussie, je sais que notre société partenaire l’a signée.

Mais lorsque le certificat est dans la signature de la réponse SAML, n'importe qui aurait pu l'envoyer! La seule chose que je sache, c'est que la réponse n'a pas été falsifiée. Mais le fait est que je ne sais pas du tout qui a envoyé le SAML.

Quelqu'un peut-il m'expliquer comment cela fonctionne?

96
Dante

Les réponses SAML sont accompagnées d'une signature et d'une clé publique pour cette signature.

Vous pouvez utiliser la clé publique pour vérifier que le contenu de la réponse SAML correspond à la clé - en d'autres termes - cette réponse provient certainement de quelqu'un qui possède la clé privée correspondante pour la clé publique dans le message, et la réponse n'a pas été altéré.

Je ne sais pas avec quelle technologie vous travaillez, mais en .Net, vous pouvez le vérifier comme ceci:

// 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);

Cela vérifie simplement que le message provient de qui il est dit. Vous avez besoin d'une vérification supplémentaire indiquant que le message provient d'une personne de confiance, et cette vérification est plus lente. Elle doit inclure la révocation et peut-être vérifier toute une chaîne de certificats.

Normalement, il s'agira d'une liste de clés publiques à partir desquelles vous accepteriez des réponses SAML.

Ensuite, vous pouvez vérifier que ce message n'a pas été falsifié et provient d'une personne en qui vous avez confiance. Vous pouvez ainsi autoriser les détails de l'utilisateur fournis dans les attributs SAML fournis.

Vous pouvez avez déjà la clé publique, ce qui signifie que la signature ne devrait plus avoir à inclure la clé publique, mais vous pouvez également avoir plusieurs expéditeurs connus possibles, voire une chaîne d'expéditeurs connus.

Par exemple, vous pouvez avoir deux fournisseurs de confiance - dans les deux cas, vous vérifiez que le message n'a pas été falsifié avant de vérifier si vous faites confiance à l'un ou l'autre des fournisseurs. Si la clé n'est pas dans la signature, les assertions peuvent être un peu plus petites, mais vous devez maintenant savoir à l'avance de quel fournisseur d'identité provient l'assertion.

Donc, vraiment, il y a deux raisons principales pour lesquelles la clé publique est dans la signature:

  1. La vérification d'inviolabilité est plus rapide que la vérification d'identité et peut être isolée si la clé publique est connue.
  2. Les identités multiples sont beaucoup plus faciles à supporter si la clé est dans l'assertion.
59
Keith

La raison pour laquelle la clé est spécifiée est que les métadonnées du fournisseur d'identité peuvent spécifier plusieurs clés de signature. Vous pouvez également spécifier la clé à utiliser en l'incluant avec la signature. SAML 2.0 exige que si la clé n'est pas spécifiée avec le Assertion, elle peut être déduite par le contexte (à partir des métadonnées de la partie défenderesse).

Par exemple, vous pouvez avoir ceci dans vos métadonnées pour la partie affirmée:

        <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>

Chaque élément XML signé peut spécifier quelle clé est utilisée pour la signature. Toutefois, dans le cas de SAML 2.0, cette clé de signature doit (par exemple) correspondre à celle définie dans les métadonnées de la partie qui a généré la signature. Si la clé fournie avec la signature n'est pas sécurisée (non spécifiée dans les métadonnées dans ce cas), le système SAML doit alors générer une erreur lors de la validation de la signature.

34
jbindel

La partie publique du certificat de signature se trouve dans le message SAML. Ceci est utilisé pour vérifier la signature du jeton lui-même, et bien sûr pour permettre aux destinataires de dire qui a émis le jeton et de le traiter en conséquence.

Le fait qu’il soit inclus dans les spécifications de signature numérique XML n’est pas vraiment spécifique à SAML. Sans le certificat, comment savoir d'où vient le jeton et comment le valider?

XmlDSig spécifie d'autres méthodes, vous pouvez identifier la clé de signature par un sujet, un numéro de série, un hachage, etc., mais cela suppose que la partie destinataire possède le certificat public. Pour SAML, cela peut ne pas être le cas, d’où l’intégration de la partie publique du cert. X509.

9
blowdart

J'ai posté assez tard, mais j'ai dû travailler sur SAML et j'ai trouvé ces documents. Ils donnent un bon aperçu de SAML - comment cela fonctionne et quels paramètres il attend. Devrait être une aide pour d'autres nouveaux à 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

0
user3445140