DotNetOpenAuth:消息签名不正确

Posted

技术标签:

【中文标题】DotNetOpenAuth:消息签名不正确【英文标题】:DotNetOpenAuth: Message signature was incorrect 【发布时间】:2011-01-31 02:59:49 【问题描述】:

我在尝试使用 MyOpenID 和 Yahoo 进行身份验证时收到“消息签名不正确”异常。

我使用的几乎都是 DotNetOpenAuth 3.4.2 附带的 ASP.NET MVC 示例代码

public ActionResult Authenticate(string openid)

    var openIdRelyingParty = new OpenIdRelyingParty();
    var authenticationResponse = openIdRelyingParty.GetResponse();

    if (authenticationResponse == null)
    
        // Stage 2: User submitting identifier
        Identifier identifier;

        if (Identifier.TryParse(openid, out identifier))
        
            var realm = new Realm(Request.Url.Root() + "openid");
            var authenticationRequest = openIdRelyingParty.CreateRequest(openid, realm);
            authenticationRequest.RedirectToProvider();
        
        else
        
            return RedirectToAction("login", "home");
        
    
    else
    
        // Stage 3: OpenID provider sending assertion response
        switch (authenticationResponse.Status)
        
            case AuthenticationStatus.Authenticated:
            
                // TODO
            
            case AuthenticationStatus.Failed:
            
                throw authenticationResponse.Exception;
            
        
    

    return new EmptyResult();

与 Google、AOL 和其他公司合作良好。但是,Yahoo 和 MyOpenID 属于 AuthenticationStatus.Failed 情况,但有以下例外:

DotNetOpenAuth.Messaging.Bindings.InvalidSignatureException: Message signature was incorrect.
   at DotNetOpenAuth.OpenId.ChannelElements.SigningBindingElement.ProcessIncomingMessage(IProtocolMessage message) in c:\Users\andarno\git\dotnetopenid\src\DotNetOpenAuth\OpenId\ChannelElements\SigningBindingElement.cs:line 139
   at DotNetOpenAuth.Messaging.Channel.ProcessIncomingMessage(IProtocolMessage message) in c:\Users\andarno\git\dotnetopenid\src\DotNetOpenAuth\Messaging\Channel.cs:line 992
   at DotNetOpenAuth.OpenId.ChannelElements.OpenIdChannel.ProcessIncomingMessage(IProtocolMessage message) in c:\Users\andarno\git\dotnetopenid\src\DotNetOpenAuth\OpenId\ChannelElements\OpenIdChannel.cs:line 172
   at DotNetOpenAuth.Messaging.Channel.ReadFromRequest(HttpRequestInfo httpRequest) in c:\Users\andarno\git\dotnetopenid\src\DotNetOpenAuth\Messaging\Channel.cs:line 386
   at DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingParty.GetResponse(HttpRequestInfo httpRequestInfo) in c:\Users\andarno\git\dotnetopenid\src\DotNetOpenAuth\OpenId\RelyingParty\OpenIdRelyingParty.cs:line 540

看来其他人也有同样的问题:http://trac.dotnetopenauth.net:8000/ticket/172

有人有解决方法吗?

【问题讨论】:

在执行此测试时,我使用 DotNetOpenAuth 测试台也遇到了同样的异常:test-id.org/RP/POSTAssertion.aspx 这看起来像一个类似的问题:***.com/questions/2508327/… 【参考方案1】:

原来这是在网络农场环境中使用 DotNetOpenAuth 时出现的问题。

当您创建 OpenIdRelyingParty 时,请确保在构造函数中传递 null。

这会将您的网站置于 OpenID 无状态或“哑”模式。用户登录的速度稍慢(如果您注意到的话),但您不必编写 IRelyingPartyApplicationStore 以允许 DotNetOpenAuth 在您的农场中工作;

var openIdRelyingParty = new OpenIdRelyingParty(null);

【讨论】:

我怀疑这可能会引入安全漏洞。有人可以确认吗?【参考方案2】:

所有这些讨论都围绕以下问题:

依赖方 (RP) 如何确保包含身份验证令牌的请求来自他将用户请求转发到的 OP(OpenId 提供者)?

以下步骤解释了它是如何发生的

    用户请求来自回复方 (RP),在我们的案例中是我们的网站 应用程序将该用户对应的唯一签名存储在本地签名存储(LSS)中,然后将该签名嵌入到消息中,并将该消息转发给 OpenId Provider(OP) 用户键入他的凭据,OP 对其消息进行身份验证,然后将该消息(其中仍嵌入签名)转发回 RP RP 将嵌入在消息中的签名与 LSS 中的签名进行比较,如果它们匹配 RP,则对用户进行身份验证

如果 LSS 在消息从 OP 返回之前消失(不知何故),则 RP 无法将签名与之进行比较,因此它无法验证用户并抛出错误:消息签名不正确。

LSS 怎么会消失:

    ASP.net 刷新应用程序池 IIS 已重新启动 在网络场中,消息由托管在不同服务器上的应用程序提供服务

这个问题的两个解决方案:

    RP 在哑模式下运行

    a. 它不在本地存储和签名,因此不使用签名比较来确保消息来自他将用户转发到的 OP 以进行身份​​验证

    b. 相反,一旦 RP 收到来自 OP 的身份验证消息,它会将消息发送回 OP,并要求他检查他是否是验证此用户的人并且是消息。如果 OP 回复是,我是此消息的发起者并且我已创建此消息,则用户已通过 RP 身份验证

    实现您自己的不会消失的持久性存储,无论 ASP.net 对进程做什么,就像使用 SQL 存储会话状态一样。

【讨论】:

【参考方案3】:

我们通过实现 IRelyingPartyApplicationStore(在较新版本的 DotNetOpenAuth 中为IOpenIdApplicationStore)并将商店类名称添加到 .config 来解决此问题

<dotNetOpenAuth>
  <openid ...>
    <relyingParty>
      ...
      <store type="some.name.space.MyRelyingPartyApplicationStore, some.assembly"/>
    </relyingParty>
  </openid>
  ...
</dotNetOpenAuth>

接口是由另外两个接口组成的,总共有五个成员。

/// <summary>
/// A hybrid of the store interfaces that an OpenID Provider must implement, and
/// an OpenID Relying Party may implement to operate in stateful (smart) mode.
/// </summary>
public interface IOpenIdApplicationStore : ICryptoKeyStore, INonceStore


我们使用哑模式作为启动运行的快速解决方案,但最终您可能会想要这样的东西。

【讨论】:

以上是关于DotNetOpenAuth:消息签名不正确的主要内容,如果未能解决你的问题,请参考以下文章

在集群上运行 OpenId 提供程序时消息签名无效

字段“签名”的值不正确:值为 662655099,但应为 67324752

图解密码技术------第9章 数字签名

如何从 R 中的散列消息和签名中正确恢复 ECDSA 公钥 ||小号 || V格式?

DotNetOpenAuth 和 ResourceServer 服务 https 配置

使用 Google Latitude 和 DotNetOpenAuth 寻找代码示例