質問

私はこの問題に関してここで他の投稿を見ましたが、それらのどれも私の状況に対処していないようです。

私は先週、SAMLの主張を検証しようとしてきましたが、SAMLを送ってくれた2人のクライアントがいますが、検証することはできません。

主なプロセスは、base64エンコードされたアサーションを取得し、それをデコードすることです。 preservewhitespace = trueを使用してxmldocmentにロードします。

検証方法はです

  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.");
    }

web.config(base64エンコード文字列として保存されている)から読んだクライアントからの証明書を持っていますxmlelementは署名された要素であり、signedxmlはsignedxmlオブジェクトです。

どちらのクライアントもChecksignatureによって虚偽を返されますが、証明書で自分の署名されたSAMLを作成すると、Trueが返されます。

ここに何が欠けていますか?

編集:はい、両方のクライアントがJavaに参加しているので、SetSigingKeyFromKeyInfoメソッドを投稿しました

役に立ちましたか?

解決

私は過去に署名されたXMLの多くを扱いました。私が言えるのは、それが悪夢だったということだけです。基本的に、XMLに署名すると、Canonicalization(C14N)と呼ばれるプロセスを通過します。 XMLテキストを署名できるバイトストリームに変換する必要があります。 XML C14N標準のWhitespace&Namepaceの処理は、理解するのが難しく、正しく実装するのがさらに難しいです。 C14Nには複数のタイプがあります。

.NET実装は、それが受け入れるものについて非常に選択的です。他の実装が.NETのものとまったく同じ方法で機能しない可能性は非常に高いです。これは確かにとても悲しいです。たとえば、署名する前に、ソースXMLからホワイトスペースと名前空間を排除できる場合、それは役立ちます。また、両方の実装が同じC14N設定を使用していることを確認できる場合。

そうでなければ、多くのデバッグがあなたを待っています。フレームワークにデバッグするか、内部メソッドを反射して手作業で呼び出して、XMLフラグメントと署名をどのように計算するかを確認できます。また、他の実装でも同じことを行います。基本的に、両方の場合に署名されている正確なバイトストリームを確認する必要があります。これは、署名前の変換の最後のステップです。これらのバイトストリームが一致する場合、RSAの署名部品に私の経験に問題はありません。あなたの場合のように、それらが一致しない場合、少なくとも問題がどこにあるかがわかります。

他のヒント

私は同様の問題を抱えていて、多くの時間を失いました。おそらくこれは誰かを助けることができます。

私の環境は100%.NET 4.5で、コードはSignedXMLクラスのみを使用しています。しかし、SAMLの主張はある場所で受け入れられ、別の場所で拒否されました。

1つの場所が、で初期化されたXmldocumentインスタンスを介してアサーションをロードしていることが判明しました。 PreserveWhitespace = true, 、もう1つはそうではありませんでした。

そして、このアサーションはかなり印刷されていたので、キャリッジリターンと多くのインデントスペースがありました。すべてのキャリッジリターンを削除すると、インデントスペースが私の問題を修正しました。

TimoresとしてSAMLと同様の問題がありました。 SAMLはbase64からデコードする必要がありましたが、最初に使用しました。

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

しかし、これはASCIIデコードを使用し、特殊文字に問題がありました。つまり、XMLは署名されたときとわずかに異なっていたため、失敗しました。それを変更しました:

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

そして、それはすべてのケースで機能しました。

正しいエンコードを使用していることを確認してください!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top