Question

Je l'ai regardé d'autres postes ici à ce sujet et aucun d'entre eux semblent répondre à ma situation.

J'ai essayé de vérifier une assertion SAML pour la semaine dernière et j'ai 2 clients qui me ont envoyé SAML, mais je ne peux pas le vérifier.

Le processus principal est que nous obtenons une affirmation codée base64 et je le décoder. Chargez dans un XmlDocment avec PreserveWhitespace = true.

La méthode verify est

  public static bool Verify(X509Certificate2 cert, XmlElement xmlElement, SignedXml signedXml)
  {
       bool flag;
       try
       {
           KeyInfo keyInfo = new KeyInfo();
           var clause = new KeyInfoX509Data(cert);
           keyInfo.AddClause(clause);

            XmlElement signatureElement = GetSignatureElement(xmlElement);
            if (signatureElement == null)
            {
                string message = "The XML does not contain a signature.";
                throw new SAMLSignatureException(message);
            }
            signedXml.LoadXml(signatureElement);
            if (keyInfo != null)
            {
                signedXml.KeyInfo = keyInfo;
            }
            SetSigningKeyFromKeyInfo(signedXml);
            flag = signedXml.CheckSignature(cert.PublicKey.Key);
        }
        catch (Exception exception)
        {
            throw new SAMLSignatureException("Failed to verify the XML signature.", exception);
        }
        return flag;
    }

 private static void SetSigningKeyFromKeyInfo(SignedXml signedXml)
    {
        IEnumerator enumerator = signedXml.KeyInfo.GetEnumerator();
        while (enumerator.MoveNext())
        {
            if (enumerator.Current is KeyInfoX509Data)
            {
                var current = (KeyInfoX509Data) enumerator.Current;
                if (current.Certificates.Count != 0)
                {
                    var certificate = (X509Certificate) current.Certificates[0];
                    var certificate2 = new X509Certificate2(certificate);
                    AsymmetricAlgorithm key = certificate2.PublicKey.Key;
                    signedXml.SigningKey = key;
                    return;
                }
            }
            else
            {
                if (enumerator.Current is RSAKeyValue)
                {
                    var value2 = (RSAKeyValue) enumerator.Current;
                    signedXml.SigningKey = value2.Key;
                    return;
                }
                if (enumerator.Current is DSAKeyValue)
                {
                    var value3 = (DSAKeyValue) enumerator.Current;
                    signedXml.SigningKey = value3.Key;
                    return;
                }
            }
        }
        throw new SAMLSignatureException("No signing key could be found in the key info.");
    }

Je le certificat du client que je lis depuis web.config (son stocké sous forme base64 chaîne codée) xmlelement est l'élément signé, SignedXml est un objet SignedXml qui a été créé avec le nouveau SignedXml (xmlelement)

Les deux clients obtiennent de faux retourné par CheckSignature mais quand je crée mon propre SAML signé avec mon certificat, il retourne vrai.

Qu'est-ce que je manque ici?

EDIT: Oui les deux clients sont en Java et j'ai posté la méthode SetSigningKeyFromKeyInfo

Était-ce utile?

La solution

Je traite beaucoup dans le passé XML signé. Tout ce que je peux dire est que ce fut un cauchemar. En fait, lorsque vous vous XML, il passe par un processus appelé canonicalisation (C14N). Il doit transformer un texte XML à un flux d'octets qui peut être signé. manipulation et espace de nommage des espaces, entre autres, dans les normes XML C14N sont difficiles à comprendre, encore plus difficile à mettre en œuvre le droit. Il y a même plusieurs types de C14N.

La mise en œuvre .NET est très sélectif sur ce qu'il accepte. Il est tout à fait possible que votre autre mise en œuvre ne fonctionne pas de la même manière exacte que celui .NET. Ceci est très triste. Si vous pouvez éliminer les espaces et les espaces de noms XML à partir de votre source avant la signature, par exemple, cela pourrait aider. Aussi, si vous pouvez vous assurer que les deux implémentations utilisent les mêmes paramètres de C14N.

Sinon beaucoup de débogage vous attend. Vous pouvez déboguer dans le cadre, ou appeler ses méthodes internes à la main avec la réflexion, pour voir comment il calcule le fragment XML et la signature. Et faire la même chose avec l'autre mise en œuvre. Fondamentalement, vous avez besoin de voir les flux d'octets exacts qui sont signés dans les deux cas. Ceci est la dernière étape de la conversion avant de signer. Si les flux octet correspondance, alors vous aurez aucun problème avec la partie de signature de RSA dans mon expérience. Si ceux-ci ne correspondent pas, comme dans votre cas, au moins vous verrez où est le problème.

Autres conseils

Je viens d'avoir un problème similaire et perdu beaucoup de temps, peut-être ce que quelqu'un peut aide.

Mon environnement est de 4,5 à 100% .Net, et mon code utilise uniquement la classe SignedXml. Mais une assertion SAML a été acceptée à un endroit et a refusé à l'autre.

est avéré que l'un endroit chargeait l'affirmation par une instance de XmlDocument initialisé avec PreserveWhitespace = true, tandis que l'autre n'a pas.

Et l'affirmation avait été assez imprimé, il avait des retours chariot et beaucoup d'espaces d'indentation. Suppression de tous les retours chariot et les espaces d'indentation fixe mon problème.

eu un problème similaire avec Saml comme Timores. Le Saml avait besoin d'être décodé à partir base64 mais d'abord i utilisé:

var saml = System.Text.Encoding.Default.GetString(Convert.FromBase64String(samlToken))

Mais ce décodage ASCII utilisé et avait du mal avec des caractères spéciaux. Ce qui signifie que XML est légèrement différent de quand il a été signé et est la raison pour laquelle il a échoué. Changé à:

var saml = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(samlToken))

et cela a fonctionné pour tous les cas.

Alors assurez-vous que vous utilisez le bon encodage!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top