1

我想实现一个 API 密钥系统来保护对我的应用程序的 API 调用。

我认为可行的方式是每个帐户都有一个私钥/秘密。每个请求都包含时间、帐户 ID 和哈希(时间+秘密)。
然后,服务器可以对数据库中的用户密码执行相同的操作,并根据客户端发送的哈希值进行检查。

这是一个合理的方法吗?它对蛮力攻击是开放的,但我认为只要秘密很长(即uuid),它就不应该成为太大的问题......

一个想法

任何人都可以同时提交另一个请求并进行哈希处理,并最终被接受,对吧?

4

3 回答 3

4

问题是可以重放随机数+哈希。真正的身份验证协议至少需要两条消息:

Server                Client

    ---->challenge --->
    <----response------

例如,挑战可能是由服务器提供的随机数,而客户端的响应将是密码与随机数的哈希值。

不幸的是,这需要state,而 RESTful 协议的全部问题是它们不想要保持状态的麻烦。然而他们想要验证...

所以你真的有三个选择:

方案一:假装问题不存在,使用无状态的“认证”协议。这与使用 cookie 没有什么不同。nonce + password-hash 并不比 cookie 更安全。Cookies 可以被盗等,并被重放。整个网络现在都受到这些重放攻击的困扰。

选项 2:尝试将身份验证协议绑定到无状态通信方法上。在这里,您将让客户端向您发送 UTC 时间戳而不是随机数。时间戳的使用提供了对重放的有限防御。显然,您的时钟不会与客户端的时钟同步,因此您的服务器将允许在某个误差范围内的任何时间戳,并且该误差范围将是身份验证协议的重放范围。请注意,这违反了 REST,因为身份验证消息不是幂等的。幂等意味着“可以被攻击者成功重放”。

选项 3:不要尝试将身份验证协议绑定到无状态协议上。使用 SSL。使用客户端证书。不要让客户端下载字符串,而是让他们生成证书,或者您可以为他们提供密钥对。它们通过 SSL 进行身份验证,并且不在您的 REST 层中进行身份验证。SSL 有很多“开销”。它不是轻量级的,正是因为它确实解决了这些重播问题。

因此,归根结底,这取决于您对 API 访问的重视程度。

于 2011-11-09T12:43:56.690 回答
2

对于仅检索数据(私有数据除外)而不是创建、修改或删除数据的 API,此答案中的选项 1 可能就足够了。例如,请参阅Bing Maps REST APIGoogle Maps Premier 网络服务(在这里,Google Maps 还使用数字签名和只有 API 用户知道的特殊密钥对 URL 进行哈希处理,同时提供防止修改 URL ,显然仍然不提供重放攻击保护)。

事实上,某些检索数据的 API 不使用 API 密钥,而是以其他方式限制访问(例如,YouTube API 允许在无需身份验证的情况下检索视频和用户频道的公开可用数据,但限制最近要求)。

对于不仅仅检索公开可用数据的 API 需要选项 2 和/或 3,例如,如果它修改用户配置文件、发布内容或访问私人信息:请参见YouTube 数据 API 身份验证页面,其中OAuth 作为一种可能的身份验证方案被提及。

特别是对于选项 1,此处的 API 密钥用于跟踪用户对您的 API 的访问,最重要的是,限制这些用户的访问。选项 1 可能不适用于允许无限制数据访问的 API。

(这是一个答案,因为评论太长了。)

于 2011-11-09T17:25:41.880 回答
0

服务器包含:

  • 用户名
  • 密码哈希

客户端发送:

  • 用户名
  • 随机字符串
  • (密码哈希+随机字符串)的哈希

当客户端调用服务器时,服务器创建密码哈希(它自己知道)+随机字符串(通过调用客户端在 GET 中给出)的哈希,并评估是否匹配哈希(通过调用客户端在 GET 中给出)

更好的是创建 1 个函数,该函数从(密码哈希 + 随机数)生成秘密哈希,其中“随机数”(随机数)也存储在服务器上。然后可以使用用户名+密码调用服务器一次,返回秘密哈希;然后让后续调用仅依赖于用户名 + 随机字符串 + (秘密哈希 + 随机字符串)的哈希,使用与上述相同的方法,但秘密是当时的密码。这样,即使你的秘密被截获和逆转,你的通行证仍然是安全的。

显然,好的散列算法:没有 rot13 甚至只有 md5 是有问题的。

于 2011-11-09T10:57:01.573 回答