SignedXml checksignature返回falseSignedXml、checksignature、false

2023-09-04 22:41:57 作者:猎杀者的温柔+:)

我在这里就这个问题和他们都不来解决我的情况看其他职务。

I've looked at other posts on here regarding this issue and none of them seem to address my situation.

我一直在试图验证SAML断言的最后一个星期,我都已经给我发了SAML的2客户端,但我无法验证它。

I've been trying to verify a SAML assertion for the last week and I have 2 clients that have sent me SAML but I cannot verify it.

主要过程是,我们得到一个base64连接codeD断言和c它,我去$ C $。将其加载到其中preserveWhitespace的XmlDocment =真。

The main process is we get a base64 encoded assertion and I decode it. Load it into an XmlDocment with PreserveWhitespace = true.

的验证方法是

  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 EN codeD字符串存储)XMLELEMENT是带符号的元素阅读客户端证书,signedXml是与新的SignedXml(XMLELEMENT)创建一个SignedXml对象

I have the certificate from the client that I read in from Web.Config (its stored as base64 encoded string) xmlelement is the signed element, signedXml is a SignedXml object that was created with new SignedXml(xmlElement)

这两个客户获取虚假通过checksignature回来,但是当我创建自己签名的SAML与我的证书,它将返回true。

Both clients get false returned by checksignature but when I create my own signed saml with my certificate it will return true.

我在想什么吗?

编辑:有两个客户都是在Java和我张贴的SetSigningKeyFromKeyInfo方法

Yes both of the clients are on Java and I posted the SetSigningKeyFromKeyInfo method

推荐答案

我处理了签名的XML的很多过去。我可以说的是,这是一场噩梦。基本上,当你签署XML,它会经历一个过程称为规范化(C14N)。它需要转XML文本到可签名的字节流。空白和放大器;命名空间的处理,除其他外,XML C14N标准是很难理解的,甚至是难以实现的权利。甚至有多种类型的C14N的。

I dealt with signed XML's a lot in the past. All I can say is that it was a nightmare. Basically, when you sign XML, it goes through a process called canonicalization (C14N). It needs to turn XML text to a byte stream which can be signed. Whitespace & namespace handling, among others, in XML C14N standards are hard to understand, even harder to implement right. There are even multiple types of C14N.

在.NET实现是非常有选择性的关于什么是接受。这很可能是你的其他的实现并不以完全相同的方式作为.NET一部作品。这是很可悲的确实。如果你能在签名前应消除空白和命名空间,从您的XML源,例如,可以提供帮助。此外,如果你能确保这两个实现使用相同的C14N设置。

The .NET implementation is very selective about what it accepts. It's quite possible that your other implementation doesn't work in the exact same way as the .NET one. This is very sad indeed. If you can eliminate whitespace and namespaces from your source XML before signing, for example, that could help. Also if you could make sure that both implementations use the same C14N settings.

否则大量的调试恭候您的光临。你可以调试到框架,或致电其内部的方法,用手工与反思,看看它是如何计算的XML片段和签名。并与其它实现也这样做。基本上你需要看到,在这两种情况下签订的精确的字节流。这是签名前的变换的最后步骤。如果这些字节流的匹配,那么你不会有任何问题,在我的经验,RSA签名的一部分。如果这些不匹配,因为在你的情况下,至少你会看到哪里出了问题。

Otherwise a lot of debugging awaits you. You could debug into the framework, or call its internal methods by hand with reflection, to see how it calculates the XML fragment and the signature. And do the same with the other implementation. Basically you need to see the exact byte streams that are signed in both cases. This is the final step of the conversion before signing. If those byte streams match, then you'll have no problems with the RSA signing part in my experience. If those don't match, as is in your case, at least you'll see where the problem is.