SSO SAML的已签名XML签名验证(使用sha256)
本文关键字:签名验证 使用 sha256 XML SAML SSO | 更新日期: 2023-09-27 18:15:12
在windows 2003服务器上使用VS 2008和。net Framework 3.5。
为了安全性,我们已经使用SAML实现了SSO。我们在服务提供者端工作,验证从客户端系统生成的Signed XML SAML Assertuib令牌。到目前为止,我们遇到的任何签名文件都是使用签名算法"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;
}
现在,当我为这个新客户(使用签名算法rsa-sha256h)尝试相同的代码时-这不起作用,并且我得到错误"无法为提供的签名算法创建SignatureDescription"。
在过去的2-3天里,通过阅读许多博客和文章,我知道SignedXml不支持sha256。很好。但接下来呢?有些地方提到使用WIF,我也检查了&尝试这个。
我也在尝试使用RSAPKCS1SignatureDeformatter的verifsignsignature方法。但是不确定要传递的两个参数是什么
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;
}
}
然后,您应该通过调用这样的代码来激活这些信号描述。你只需要调用它一次,所以如果你愿意,你可以从静态构造函数调用它。
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");
向微软的Carlos Lopez、BitSchupster和Andrew致敬。
对于。net 4及更早版本,我发现添加Security后,下面的工作就可以了。密码从http://clrsecurity.codeplex.com/
(注意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);
}
这符合"简单",但可能不是"解决方案":)对于我们遇到的少数客户,我们已经要求他们将IdP更改为使用SHA-1签名。他们能够改变它,当他们这样做时,它就会起作用。
不是一个技术上的解决方案,但它已经在"现场"工作,所以我想我应该提一下。
只需更新到。net框架4.6.01590或更高版本,它将支持SHA-512而无需任何代码更改