checksignature java,SignedXml checksignature返回false

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

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.

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

The verify method is

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

}

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)

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

What am I missing here?

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

解决方案

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.

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.

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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值