简体   繁体   English

SSO SAML的签名XML签名验证(使用sha256)

[英]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 LopezBitSchupster以及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.

相关问题 C# 使用带有 SHA256 证书的 ECDSA 进行签名验证 - C# signature verification using ECDSA with SHA256 certificate 使用SHA256的PayFort签名 - PayFort Signature using SHA256 SSO SAML数字签名验证-XML Unicode字符 - SSO SAML digital signature verification - XML unicode character SignedXml 使用 SHA256 计算签名 - SignedXml Compute Signature with SHA256 如何验证在 C# 中使用 google KMS(非对称符号,椭圆曲线 P-256 密钥 SHA256 摘要)签名的签名真实性 - How to verify signature authenticity that was signed using google KMS (Asymmetric sign, Elliptic Curve P-256 key SHA256 Digest) in C# RSA SHA256 签名生成和验证 - RSA SHA256 signature generation and validation 使用 WebServicesClientProtocol 和 sha256 的 Soap 签名 - Soap signature with WebServicesClientProtocol and sha256 使用BouncyCastle进行数字签名验证 - 带有SHA 256,C#的ECDSA - Digital Signature Verification using BouncyCastle - ECDSA with SHA 256, C# 使用BouncyCastle验证在C#中用ECDSA(带有SHA256)签名的XMLSignature抛出InvalidCastException - Verifying XMLSignature signed with ECDSA (with SHA256) in C# using BouncyCastle throws InvalidCastException 如何在C#中使用带有ECDSA算法的SHA256创建数字签名 - How to create a digital signature using SHA256 with ECDSA algorithm in C#
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM