[英]Signed XML signature verification for SSO SAML (Using sha256)
Using VS 2008 with .Net Framework 3.5 on windows 2003 server. 在Windows 2003服务器上使用VS 2008和.Net Framework 3.5。
We have implemented SSO with SAML for security. 为了安全起见,我们使用SAML实施了SSO。 We work at service provider end where we validate the Signed XML SAML Assertuib token generated from client's system.
我们在服务提供商端工作,我们验证从客户端系统生成的签名XML SAML Assertuib令牌。 As of now whatever signed documents we came across were using the Signature Algorithm "rsa-sha1", but now we have new customer who sends a file with the signature algorithm as "rsa-sha256" and here is the problem started.
截至目前,我们遇到的任何签名文档都使用了签名算法“rsa-sha1”,但现在我们有新客户发送带有签名算法的文件“rsa-sha256”,这就是问题的开始。
public static string VerifySignature()
{
if (m_xmlDoc == null)
return "Could not load XMLDocument ";
try
{
XmlNamespaceManager nsm = new XmlNamespaceManager(new NameTable());
nsm.AddNamespace("dsig", SignedXml.XmlDsigNamespaceUrl);
XmlElement sigElt = (XmlElement)m_xmlDoc.SelectSingleNode(
"//dsig:Signature", nsm);
// Load the signature for verification
SignedXml sig = new SignedXml(m_xmlDoc);
sig.LoadXml(sigElt);
if (!sig.CheckSignature())
return "Invalid Signature";
}
catch (Exception ex)
{
return ex.Message;
}
return string.Empty;
}
Now, when I try the same code for this new customer (with signature algorithm rsa-sha256h) - this is not working and I am getting the error "SignatureDescription could not be created for the signature algorithm supplied." 现在,当我为这个新客户尝试相同的代码(使用签名算法rsa-sha256h)时 - 这不起作用,我收到错误“无法为提供的签名算法创建SignatureDescription。”
Going through many blogs and articles in last 2-3 days, I came to know that SignedXml does not support sha256. 在过去2-3天内浏览了许多博客和文章,我发现SignedXml不支持sha256。 Fine.
精细。 But what next.
但接下来是什么。 Somewhere its mentioned that use the WIF, I have also checked & tried this .
在其提到的某个地方使用WIF,我也检查过并试过这个 。
I am also trying to use RSAPKCS1SignatureDeformatter's VerifySignature method. 我也在尝试使用RSAPKCS1SignatureDeformatter的VerifySignature方法。 But not really sure what are the two parameters to be passed.
但不确定要传递的两个参数是什么。
Dotnet 4.6.2+ has the newer sha
hashes built in. For dotnet 4 +, to get access to rsa-sha512, rsa-sha384, and rsa-sha256, you should include this code someplace. Dotnet 4.6.2+内置了较新的
sha
哈希。对于dotnet 4 +,要访问rsa-sha512,rsa-sha384和rsa-sha256,你应该在某个地方包含这个代码。
/// <summary>Declare the signature type for rsa-sha512</summary>
public class RsaPkCs1Sha512SignatureDescription : SignatureDescription
{
public RsaPkCs1Sha512SignatureDescription()
{
KeyAlgorithm = typeof(RSACryptoServiceProvider).FullName;
DigestAlgorithm = typeof(SHA512CryptoServiceProvider).FullName;
FormatterAlgorithm = typeof(RSAPKCS1SignatureFormatter).FullName;
DeformatterAlgorithm = typeof(RSAPKCS1SignatureDeformatter).FullName;
}
public override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key)
{
var sigProcessor = (AsymmetricSignatureDeformatter)CryptoConfig.CreateFromName(DeformatterAlgorithm);
sigProcessor.SetKey(key);
sigProcessor.SetHashAlgorithm("SHA512");
return sigProcessor;
}
public override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key)
{
var sigProcessor =
(AsymmetricSignatureFormatter)CryptoConfig.CreateFromName(FormatterAlgorithm);
sigProcessor.SetKey(key);
sigProcessor.SetHashAlgorithm("SHA512");
return sigProcessor;
}
}
/// <summary>Declare the signature type for rsa-sha384</summary>
public class RsaPkCs1Sha384SignatureDescription : SignatureDescription {
public RsaPkCs1Sha384SignatureDescription()
{
KeyAlgorithm = typeof(RSACryptoServiceProvider).FullName;
DigestAlgorithm = typeof(SHA384CryptoServiceProvider).FullName;
FormatterAlgorithm = typeof(RSAPKCS1SignatureFormatter).FullName;
DeformatterAlgorithm = typeof(RSAPKCS1SignatureDeformatter).FullName;
}
public override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key)
{
var sigProcessor = (AsymmetricSignatureDeformatter) CryptoConfig.CreateFromName(DeformatterAlgorithm);
sigProcessor.SetKey(key);
sigProcessor.SetHashAlgorithm("SHA384");
return sigProcessor;
}
public override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key)
{
var sigProcessor =
(AsymmetricSignatureFormatter)CryptoConfig.CreateFromName(FormatterAlgorithm);
sigProcessor.SetKey(key);
sigProcessor.SetHashAlgorithm("SHA384");
return sigProcessor;
}
}
/// <summary>Declare the signature type for rsa-sha256</summary>
public class RsaPkCs1Sha256SignatureDescription : SignatureDescription
{
public RsaPkCs1Sha256SignatureDescription()
{
KeyAlgorithm = typeof(RSACryptoServiceProvider).FullName;
DigestAlgorithm = typeof(SHA256CryptoServiceProvider).FullName;
FormatterAlgorithm = typeof(RSAPKCS1SignatureFormatter).FullName;
DeformatterAlgorithm = typeof(RSAPKCS1SignatureDeformatter).FullName;
}
public override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key)
{
var sigProcessor =
(AsymmetricSignatureDeformatter) CryptoConfig.CreateFromName(DeformatterAlgorithm);
sigProcessor.SetKey(key);
sigProcessor.SetHashAlgorithm("SHA256");
return sigProcessor;
}
public override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key)
{
var sigProcessor =
(AsymmetricSignatureFormatter)CryptoConfig.CreateFromName(FormatterAlgorithm);
sigProcessor.SetKey(key);
sigProcessor.SetHashAlgorithm("SHA256");
return sigProcessor;
}
}
Then, you should activate these sig descriptions by calling code like this. 然后,您应该通过调用这样的代码来激活这些sig描述。 You only need to call it once, so you can call it from a static constructor if you wish.
您只需要调用一次,因此如果您愿意,可以从静态构造函数中调用它。
CryptoConfig.AddAlgorithm(typeof(RsaPkCs1Sha512SignatureDescription),
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha512");
CryptoConfig.AddAlgorithm(typeof(RsaPkCs1Sha384SignatureDescription),
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha384");
CryptoConfig.AddAlgorithm(typeof(RsaPkCs1Sha256SignatureDescription),
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
Tip o' the hat to Microsoft's Carlos Lopez and BitSchupster and Andrew on SO. 提示微软的Carlos Lopez和BitSchupster以及Andrew的SO。
For .net 4 and earlier, I found that the following works once you add the Security.Cryptography from http://clrsecurity.codeplex.com/ 对于.net 4及更早版本,我发现从http://clrsecurity.codeplex.com/添加Security.Cryptography后,以下工作正常。
(Note X509CertificateFinder is my own, looks for the signature certificate in the certificate store by thumbprint) (注意X509CertificateFinder是我自己的,通过指纹查找证书存储区中的签名证书)
/// <summary>
/// Validate an XmlDocuments signature
/// </summary>
/// <param name="xnlDoc"> The saml response with the signature elemenet to validate </param>
/// <returns> True if signature can be validated with certificate </returns>
public bool ValidateX509CertificateSignature(XmlDocument xnlDoc)
{
XmlNodeList XMLSignatures = xnlDoc.GetElementsByTagName("Signature", "http://www.w3.org/2000/09/xmldsig#");
// Checking If the Response or the Assertion has been signed once and only once.
if (XMLSignatures.Count != 1) return false;
var signedXmlDoc = new SignedXml(xnlDoc);
signedXmlDoc.LoadXml((XmlElement)XMLSignatures[0]);
var certFinder = new X509CertificateFinder();
var foundCert = certFinder.GetSignatureCertificate();
CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
return signedXmlDoc.CheckSignature(foundCert,false);
}
This qualifies for "simple" but perhaps not "solution" :) For the few clients we've encountered this with, we've asked them to change their IdP to sign using SHA-1. 这符合“简单”但可能不是“解决方案”的条件:)对于我们遇到过的少数客户,我们已经要求他们使用SHA-1将他们的IdP更改为签名。 They are able to change it, and when they do it works.
他们能够改变它,当他们这样做时。
Not a technical solution, but it has worked 'in the field' so I'd thought I'd mention it. 不是技术解决方案,但它在“现场”工作,所以我想我会提到它。
只需将其更新到.NET framework 4.6.01590或更高版本,它将支持SHA-512而无需更改任何代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.