2

所以我对 HMAC 身份验证非常陌生,我真的不知道自己在做什么,也不知道在读 atm。

我一直在尝试正确理解以下文章/链接/讨论:

如何在 RESTful WCF API 中实现 HMAC 身份验证

http://blogs.microsoft.co.il/blogs/itai/archive/2009/02/22/how-to-implement-hmac-authentication-on-a-restful-wcf-service.aspx

http://buchananweb.co.uk/security01.aspx

话虽如此,我有几个问题:

  1. 了解第一个链接,例如,如果我在 .net 中创建了一个 loginAuthentication 服务并将从 iPhone 应用程序访问,我是否为此传递了一个未加密的用户名(消息)并且应该只返回一个真/假,或者它应该返回一个加密的我稍后将在其中用于其他事务(删除、插入服务等)的字符串?

    [ServiceContract]
    
    public partial class LoginService
    {
    
     [OperationContract]
     bool Authenticate(string username) {
       // stuffs
     }
    

    }

  2. 话虽如此,在我验证了用户之后,这就是我迷路的地方。我在数据库中保存一些“带有时间戳”的东西会更好吗(有人告诉我这个,我也读过一些关于这个的讨论)?还是我只是将其与加密消息一起返回(取决于第一个问题),以便每次发出请求时都已经附加了时间戳?

    一种。我该怎么处理那个时间戳?

    湾。一旦再次发送消息以进行另一笔交易,是否会使用它?

  3. 密钥和秘密消息。我理解的方式是密钥将是用户的密码。因此,如果用户发送他的用户名,我可以使用该用户的密码打开消息吗?如果用户已经有一个会话并且只是请求获取数据或请求删除、插入等,这是有道理的。如果它只是验证用户的用户名和密码,是否仍然是相同的方式?

感谢您的时间!

4

2 回答 2

4

首先我要提到的是 WCF Web Api 是一个 beta 项目,不再被开发。它被 ASP.NET Web API 取代,这是一个用于开发 RESTful 服务的出色框架。

如果您想了解 RESTful 服务和身份验证的工作原理,Netflix API 将是一个很好的起点。他们有很多关于安全部分的文档,这有助于我更多地了解 HMAC。

HMAC 使用密钥创建散列。客户端和服务器都维护一个密钥的副本,以便它们可以生成匹配的哈希值。这使您可以“签署”一个请求,该请求既可用作身份验证(您知道发送它的人就是他们所说的身份)和消息完整性(知道他们发送的消息是原始消息并且没有被篡改)。

签名是通过组合创建的

1. Timestamp (unix epoc is the easiest to send in urls)
2. Nonce (a random number that can never be used twice to protect against someone re-using it)
3. Message (for a GET request this would be the URL, a POST would be the whole body)
4. Signature (the three previous items combined and hashed using the secret key)

上述每一项都可以在请求的查询字符串中发送,然后服务器可以使用前 3 个及其密钥副本重新创建签名。如果签名匹配,那么一切都很好。

在一个基于普通 HTTP 的 RESTful API(不使用基于 ssl 的 HTTPS)中,我会签署每个发送的请求,因为这再次验证并提供消息完整性。否则,如果您只是发送一个身份验证令牌,您知道用户已通过身份验证,但是如果您没有要比较的消息摘要(HMAC 哈希),您怎么知道消息没有被篡改?

实现签名的服务器端检查的一种简单方法是覆盖 System.Web.Http.AuthorizeAttribute 的 OnAuthorization(确保不使用 Mvc autorize 属性)。让它重建签名,就像您在客户端使用他们的密钥一样,如果它不匹配,您可以返回 401。然后您可以使用新的授权属性装饰所有需要身份验证的控制器。

希望这有助于消除您的一些困惑,并且不会进一步混淆水。如果您需要,我稍后可以提供一些更具体的示例。

参考:

Netflix Api Docs: http: //developer.netflix.com/docs/Security#0_18325(转到关于创建签名的部分,他们还有一个链接显示了用于创建 HMAC 签名的完整 .NET 示例)

用于创建 HMAC 签名的 .NET 类 http://oauth.googlecode.com/svn/code/csharp/OAuthBase.cs

我写的 Netflix API 包装器https ://bitbucket.org/despertar1318/netflix-api/overview

ASP.NET Web APIhttp ://www.asp.net/web-api

于 2012-11-29T18:51:01.690 回答
0

依次看你的问题

...我是否为此传递了一个未加密的用户名(消息)并且应该只返回一个真/假,还是应该返回一个加密的字符串,我稍后将在其中用于其他事务(删除、插入服务等)?

如果您只是返回一个布尔值,那么您将无法将身份验证请求与后续请求进行匹配。您需要返回某种身份验证指示符,在经典网站上,这将是会话 cookie,在您的实例中,您希望传递一个充当共享密钥的值。

我在数据库中保存一些“带有时间戳”的东西会更好吗?还是我只是将其与加密消息一起返回,以便每次发出请求时都已附加时间戳?

回到会话类比,您希望将问题一的密钥存储在某个地方(数据库?),并带有一个时间戳,该时间戳指示会话的生命周期/密钥的有效性。如果它是永远的,那么我不会打扰时间戳,如果它是其他任何东西,你需要在它到期时说些什么。

我理解的方式是密钥将是用户的密码。因此,如果用户发送他的用户名,我可以使用该用户的密码打开消息吗?如果用户已经有一个会话并且只是请求获取数据或请求删除、插入等,这是有道理的。如果它只是验证用户的用户名和密码,是否仍然是相同的方式?

这就是 HMACing 发生的地方。你有你的共享秘密,你有一条消息,这就是我通常将它们组合在一起的方式。

使用所有消息作为要散列的数据主体(这样您就可以确定某人不只是复制了散列和消息的一部分)。使用我们在第一步中共享的密钥对消息正文进行哈希处理。如果需要,你可以加盐,我会使用用户名。

最后确保消息包含时间戳(最好是UTC),这样您可以帮助防止以后重播消息。响应消息的服务可以将时间戳与它认为的时间进行比较。如果超出给定范围,则消息失败。因为时间戳将是 HMAC 的一部分,所以不能只更新日期并重播消息,一旦消息被篡改,哈希值就不会匹配。

于 2012-11-29T20:19:29.057 回答