如何在不使用OAuth的情况下制作安全API


How to make a Secure API without using OAuth?

我的要求

我正在制作一个网站,该网站也将具有移动版本。所以,我正在让它以API为中心。现在我想让我的 API 安全,而没有 OAuth 的复杂性,因为我需要的安全性非常简单。我不希望任何有权访问 api 链接的人能够访问我的数据。

因此,我遇到了这篇文章 http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/它非常惊人,并消除了我的大部分疑虑。

现在,我正在尝试重新创建文章中的任何内容。我正在使用Laravel 5框架进行PHP开发。

我想确保 API 仅由移动应用程序和网络版本使用,而不是其他人使用。我见过这样的 api 链接

example.com/fetchallinformation&publicKey=<something>&Hashkey?<some_hash_key>

现在,我知道这个键是使用 php 中的hash_hmac()函数生成的。

我的方法

  • 有一个表,我在其中存储我的 api 用户的公钥和私钥
  • URL 中的哈希密钥是通过在客户端对私钥和公钥进行哈希处理生成的,然后发送到服务器。因此,我将生成的哈希值与公钥一起发送到服务器。
  • 在服务器端,我采用公钥和哈希。我从公钥对应的表中检索私钥并拥有它们并检查结果哈希是否与客户端发送的哈希相同
  • 如果是一样的,那么我允许他们,否则,我不。

我的困惑

  • 我不确定这是否是正确的方法。

  • 我们可以通过解密哈希来获取用于使用 hash_hmac() 生成哈希的数据吗?

URL 中的哈希密钥是通过在客户端对私钥和公钥进行哈希处理生成的,然后发送到服务器。因此,我将生成的哈希值与公钥一起发送到服务器。

接近,但不完全是。 正如您刚才所描述的,具有给定公钥的用户将在每个请求中发送相同的 hmac。 这并不比"用户名和密码"更好。

旁注:如果您不使用HTTPS,那么您已经不安全了,并且您为保护网站所做的任何其他事情都相对没有价值。

生成 hmac 签名的要点在于,它不仅验证用户是否拥有密钥,而且还验证该用户在特定时间窗口内发出的特定请求。 背靠背的两个不同的请求应该具有不同的 hmac。 今天的一个请求和明天的相同请求应该具有不同的 hmac。 否则,您将受到重放攻击。 这意味着有关签名的当前时间或过期时间的信息以及有关请求本身的信息必须包含在通过 hmac 算法传递的信息中,否则您将无法完成太多工作。

对于特定用户在特定时间提出的任何给定请求,只能有一个可能的有效签名。 HMAC 是不可逆的,因此您无法在服务器端拆开签名并找出请求的属性。

当然,在考虑将密钥嵌入到应用程序中时,请记住,这种策略对于逆向工程来说可能相对微不足道。

它是一种可行的身份验证机制吗? 答案是肯定的。 正如文章所指出的那样,亚马逊网络服务在其API上使用hmac签名,并且它们具有巨大的潜在攻击面。但这是否意味着您将以有意义的安全方式实施它? 不一定。 总有人比你想象的更聪明、更狡猾、更坚定。

甚至亚马逊显然也意识到他们的签名版本 2 并不像它可能的那样强大,所以他们现在有了签名版本 4,它具有更复杂的算法,包括几轮哈希和生成中间"签名密钥",该密钥派生自您的密钥、当前日期、特定的 AWS 服务, AWS 区域和其他属性。 Amazon S3 在 2014 年或之后首次部署的区域根本不支持原始 Sig V2 - 似乎只有安全意识才能推动这一决定,因为到目前为止,旧算法的计算成本更低。

在滚动自己的安全机制时要小心。

如果您主要试图避免使用OAuth的学习曲线,我同意一开始这很烦人,那么您可能会在做傻瓜的差事。

如果这种方法适合您,那绝对没问题,毫无疑问它是安全的。

关于解密 - HMAC 由于其性质(哈希(而不应该被解密。HMAC被认为是非常安全的,你应该没有问题。您可以阅读更多关于如何以及何时使用 HMAC?[SE 安全]

我想确保 API 仅由移动应用程序和网络版本使用,而不是其他人使用。

这是OAuth和AWS风格的签名身份验证都没有真正帮助的问题。两者都是关于对用户进行身份验证,而不是应用程序。如果你有很多时间沉浸其中,你当然可以实现任何一种方法,但在这两种情况下,你都需要在你的应用程序中嵌入一个"秘密",一旦你将这个应用程序提供给用户,你的秘密就不再是真正的秘密了......

没有很好的方法可以完成您正在寻找的事情。如果有人要花时间对您的应用程序进行逆向工程以了解如何直接命中底层 API,那么您在客户端为"验证"调用应用程序所做的任何其他操作也可以进行反向工程。

我建议甚至不要打扰,并花时间节省时间来完善您的应用程序,这样就没有人愿意绕过它并直接访问您的 API。 :)

相关文章: