通过GET方法对SAML身份验证请求的签名验证失败 [英] Signature Validation for a SAML Authn Request via GET method fails

查看:270
本文介绍了通过GET方法对SAML身份验证请求的签名验证失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试了很多解决方案,但徒劳无功.这就是我按照 https://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf :

I tried a lot of solutions but in vain. This is what i am doing following guidlines set by https://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf:

  • STEPS

  • STEPS

  1. 定义身份验证请求,然后对base64进行编码,最后对它进行Url编码.让我们称之为AR
  2. URL对RelayState进行编码.让我们称之为RS
  3. 网址对签名算法字符串进行编码.让我们称之为SA
  4. 因此现在要签名的字符串变为 SAMLRequest = AR& RelayState = RS& SigAlg = SA
  5. 现在,我使用私钥(服务提供商私钥)对在步骤4中获得的字符串进行签名.6,我得到的结果签名,以64为基数进行编码,然后通过URL对其进行编码.因此,我得到了base64和url编码的签名.让我们称之为SG
  6. 现在,我将在步骤6中获得的签名附加到步骤4中的查询字符串.所以最终的查询字符串变成 SAMLRequest = AR& RelayState = RS& SigAlg = SA& Signature = SG

一切正常,但签名验证失败!

All this works fine but the signature validation is failing !

这是我的代码,类似于在这里找到的代码

Here's my code which is similar to the code found here https://github.com/Sustainsys/Saml2/blob/v0.21.2/Kentor.AuthServices/WebSSO/Saml2RedirectBinding.cs#L53-L68

protected void btnSendAuthRequest_Click(object sender, EventArgs e)
    {
        string authRequest = txtInput.Text;
        //authRequest = authRequest.TrimEnd('\r', '\n');
        authRequest = DeflateBase64UrlEncode(authRequest);

        string spPrivateKey= txtKey.Text;
        string relayState = HttpUtility.UrlEncode("https://example.com/pages/home.aspx");

        string qs = "SAMLRequest=" + authRequest + "&RelayState=" + relayState;
        qs = AddSignature(qs, spPrivateKey);

        txtOutput.Text = qs;
    }

public string AddSignature(string queryString, string PrivateKeyNoHeaders)
    {
        RSACryptoServiceProvider tmpRsa = RSAKeyTests.RSAKeyUtils.DecodePrivateKeyInfo(Convert.FromBase64String(PrivateKeyNoHeaders));

        string signingAlgorithmUrl = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";

        queryString += "&SigAlg=" + HttpUtility.UrlEncode(signingAlgorithmUrl);

        var signatureDescription = (SignatureDescription)CryptoConfig.CreateFromName(signingAlgorithmUrl);
        HashAlgorithm hashAlg = signatureDescription.CreateDigest();
        hashAlg.ComputeHash(Encoding.UTF8.GetBytes(queryString));

AsymmetricSignatureFormatter asymmetricSignatureFormatter =
            signatureDescription.CreateFormatter(
                ((RSACryptoServiceProvider)tmpRsa));
        //.GetSha256EnabledRSACryptoServiceProvider()); 
        // Is the signature failing because of above ? 

        byte[] signatureValue = asymmetricSignatureFormatter.CreateSignature(hashAlg);
        queryString += "&Signature=" + HttpUtility.UrlEncode(Convert.ToBase64String(signatureValue));

        return queryString;
    }

private string DeflateBase64UrlEncode(string input)
    {
        var inputs = string.Format(input, Guid.NewGuid());
        var bytes = Encoding.UTF8.GetBytes(inputs);
        using (var output = new MemoryStream())
        {
            using (var zip = new DeflateStream(output, CompressionMode.Compress))
            {
                zip.Write(bytes, 0, bytes.Length);
            }
            var base64 = Convert.ToBase64String(output.ToArray());
            return HttpUtility.UrlEncode(base64);
        }
    }

推荐答案

CryptoConfig.createFromName(...)

CryptoConfig.createFromName(...) doesn't know about http://www.w3.org/2000/09/xmldsig#rsa-sha1 as the digest+signing algorithm. If CryptoConfig.createFromName() is not returning null, whatever algorithm is registered for http://www.w3.org/2000/09/xmldsig#rsa-sha1 might not be RSA-SHA1. Here's an explicit implementation of SignatureDescription with RSA and SHA1:

public class RSASHA1SignatureDescription : SignatureDescription {

        public RSASHA1SignatureDescription() {
            KeyAlgorithm = "System.Security.Cryptography.RSA";
            DigestAlgorithm = "System.Security.Cryptography.SHA1Cng";
            FormatterAlgorithm = "System.Security.Cryptography.RSAPKCS1SignatureFormatter";
            DeformatterAlgorithm = "System.Security.Cryptography.RSAPKCS1SignatureDeformatter";
            _hashAlgorithm = "SHA1";
        }

        public override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key) {
            AsymmetricSignatureDeformatter item = (AsymmetricSignatureDeformatter) CryptoConfig.CreateFromName(DeformatterAlgorithm);
            item.setKey(key);
            item.SetHashAlgorithm(_hashAlgorithm);
            return item;
        }

        public override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key) {
            AsymmetricSignatureFormatter item = (AsymmetricSignatureFormatter) CryptoConfig.CreateFromName(FormatterAlgorithm);
            item.setKey(key);
            item.SetHashAlgorithm(_hashAlgorithm);
            return item;
        }

        private string _hashAlgorithm;
    }

另一种可能性是,但是您正在验证签名,而不希望rsa-sha1(许多身份提供程序通过配置禁止rsa-sha1)或验证不正确.尝试向真实的IdP(例如Okta或Salesforce)进行注册,并在那里进行验证.

The other possibility is that however you're validating the signature doesn't want rsa-sha1 (many identity providers prohibit rsa-sha1 via configuration) or the validation is incorrect. Try registering with a real IdP such as Okta or Salesforce and validate there.

这篇关于通过GET方法对SAML身份验证请求的签名验证失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆