通过 GET 方法对 SAML Authn 请求进行签名验证失败

2024-01-09

我正在发送一个SIGNED使用 c# 和 asp.net 向 idp 发出 authnRequest。我的代码对 authnRequest 进行签名,但签名验证在 idp 处失败。

Details

我尝试了很多解决方案但没有成功。 这就是我正在遵循的准则所做的事情https://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf https://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf:

  • STEPS

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

所有这些工作正常,但签名验证失败!

这是我的代码,与此处找到的代码类似https://github.com/Sustainsys/Saml2/blob/v0.21.2/Kentor.AuthServices/WebSSO/Saml2RedirectBinding.cs#L53-L68 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(...) 不知道 https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.cryptoconfig?view=netframework-4.8 about http://www.w3.org/2000/09/xmldsig#rsa-sha1作为摘要+签名算法。如果CryptoConfig.createFromName()不返回 null,无论注册什么算法http://www.w3.org/2000/09/xmldsig#rsa-sha1可能不是 RSA-SHA1。这是一个显式的实现SignatureDescription使用 RSA 和 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)注册并在那里进行验证。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过 GET 方法对 SAML Authn 请求进行签名验证失败 的相关文章

  • 嵌入式系统中的malloc [重复]

    这个问题在这里已经有答案了 我正在使用嵌入式系统 该应用程序在 AT91SAMxxxx 和 cortex m3 lpc17xxx 上运行 我正在研究动态内存分配 因为它会极大地改变应用程序的外观 并给我更多的力量 我认为我唯一真正的路线是为
  • 使用 Microsoft Graph API 订阅 Outlook 推送通知时出现 400 错误请求错误

    我正在尝试使用 Microsoft Graph API 创建订阅以通过推送通知获取 Outlook 电子邮件 mentions 我在用本文档 https learn microsoft com en us graph api subscri
  • 为什么 POSIX 允许在只读模式下超出现有文件结尾 (fseek) 进行搜索

    为什么寻找文件结尾很有用 为什么 POSIX 让我们像示例中那样在以只读方式打开的文件中进行查找 c http en cppreference com w c io fseek http en cppreference com w c io
  • 为什么禁止在 constexpr 函数中使用 goto?

    C 14 对你能做什么和不能做什么有规则constexpr功能 其中一些 没有asm 没有静态变量 看起来相当合理 但标准也不允许goto in constexpr功能 即使它允许其他控制流机制 这种区别背后的原因是什么 我以为我们已经过去
  • C# 中可空类型是什么?

    当我们必须使用nullable输入 C net 任何人都可以举例说明 可空类型 何时使用可空类型 https web archive org web http broadcast oreilly com 2010 11 understand
  • 将字符串从非托管代码传递到托管

    我在将字符串从非托管代码传递到托管代码时遇到问题 在我的非托管类中 非托管类 cpp 我有一个来自托管代码的函数指针 TESTCALLBACK FUNCTION testCbFunc TESTCALLBACK FUNCTION 接受一个字符
  • 使用 C# 在 WinRT 中获取可用磁盘空间

    DllImport kernel32 dll SetLastError true static extern bool GetDiskFreeSpaceEx string lpDirectoryName out ulong lpFreeBy
  • 使用 Google Analytics API 在 C# 中显示信息

    我一整天都在寻找一个好的解决方案 但谷歌发展得太快了 我找不到有效的解决方案 我想做的是 我有一个 Web 应用程序 它有一个管理部分 用户需要登录才能查看信息 在本节中 我想显示来自 GA 的一些数据 例如某些特定网址的综合浏览量 因为我
  • C# 用数组封送结构体

    假设我有一个类似于 public struct MyStruct public float a 我想用一些自定义数组大小实例化一个这样的结构 在本例中假设为 2 然后我将其封送到字节数组中 MyStruct s new MyStruct s
  • 当 Cortex-M3 出现硬故障时如何保留堆栈跟踪?

    使用以下设置 基于 Cortex M3 的 C gcc arm 交叉工具链 https launchpad net gcc arm embedded 使用 C 和 C FreeRtos 7 5 3 日食月神 Segger Jlink 与 J
  • 我的 strlcpy 版本

    海湾合作委员会 4 4 4 c89 我的程序做了很多字符串处理 我不想使用 strncpy 因为它不会终止 我不能使用 strlcpy 因为它不可移植 只是几个问题 我怎样才能让我的函数正常运行 以确保它完全安全稳定 单元测试 这对于生产来
  • .NET 选项将视频文件流式传输为网络摄像头图像

    我有兴趣开发一个应用程序 它允许我从 xml 构建视频列表 包含视频标题 持续时间等 并将该列表作为我的网络摄像头流播放 这意味着 如果我要访问 ustream tv 或在实时通讯软件上激活我的网络摄像头 我的视频播放列表将注册为我的活动网
  • 用 C 实现 Unix shell:检查文件是否可执行

    我正在努力用 C 语言实现 Unix shell 目前正在处理相对路径的问题 特别是在输入命令时 现在 我每次都必须输入可执行文件的完整路径 而我宁愿简单地输入 ls 或 cat 我已经设法获取 PATH 环境变量 我的想法是在 字符处拆分
  • 如何在asp.net中按下按钮后刷新Gridview

    我正在尝试制作一个简单的图书馆数据库 我在网格视图中列出搜索结果 然后有一个文本框和一个按钮 用户输入 isbn 并单击贷款按钮 然后 如果有足够数量的物品 itemNumber gt 0 则由用户借出 这是用户界面的屏幕截图 我的问题是
  • 可空属性与可空局部变量

    我对以下行为感到困惑Nullable types class TestClass public int value 0 TestClass test new TestClass Now Nullable GetUnderlyingType
  • 将应用程序从 Microsoft Access 迁移到 VB 或 C#.NET

    我目前正试图说服管理层需要将我们的应用程序之一移植到 NET 该应用程序已经发展成为 Access 中的一个庞然大物 SQL 后端 拥有 700 个链接表 650 个表单 子表单 130 个模块和 850 个查询 我几乎知道这样做的所有主要
  • 在 URL 中发送之前对特殊字符进行百分比编码

    我需要传递特殊字符 如 等 Facebook Twitter 和此类社交网站的 URL 为此 我将这些字符替换为 URL 转义码 return valToEncode Replace 21 Replace 23 Replace 24 Rep
  • 已过时 - OpenCV 的错误模式

    我正在使用 OpenCV 1 进行一些图像处理 并且对 cvSetErrMode 函数 它是 CxCore 的一部分 感到困惑 OpenCV 具有三种错误模式 叶 调用错误处理程序后 程序终止 Parent 程序没有终止 但错误处理程序被调
  • 如何在内存中存储分子?

    我想将分子存储在内存中 这些可以是简单的分子 Methane CH4 C H bond length 108 7 pm H H angle 109 degrees But also more complex molecules like p
  • 如何使用 ReactiveList 以便在添加新项目时更新 UI

    我正在创建一个带有列表的 Xamarin Forms 应用程序 itemSource 是一个reactiveList 但是 向列表添加新项目不会更新 UI 这样做的正确方法是什么 列表定义 listView new ListView var

随机推荐