【问题标题】:Why use an API key and secret?为什么要使用 API 密钥和秘密?
【发布时间】:2012-07-18 11:15:31
【问题描述】:

我遇到了许多 API,它们为用户提供了 API keysecret。但我的问题是:两者有什么区别?

在我看来,一把钥匙就够了。假设我有一把钥匙,只有我和服务器知道。我用这个密钥创建一个 HMAC 哈希并进行 API 调用。在服务器上,我们再次创建 HMAC 哈希并将其与发送的哈希进行比较。如果相同,则调用经过身份验证。

那么为什么要使用两个键呢?

编辑: 还是该 API 密钥用于查找 API 机密?

【问题讨论】:

标签: api security authentication api-key secret-key


【解决方案1】:

密钥加密依赖于使用相同的密钥对消息进行编码,然后再对消息进行解码。因此,只有知道“秘密”的人才能阅读消息。

RSA 安全性基于 2 个匹配的密钥。每个用户都有一个公钥,每个人都可以(应该)知道它。还有一个只有用户应该知道的私钥。用公钥加密的消息只能用私钥解密,反之亦然。

因此,如果我想向您发送只有您可以阅读的消息,我会(从网络)获取您的公钥,使用该密钥加密消息,而您是唯一可以解密的人。

或者,如果我想向你证明我发送了一条消息,我可以用我的私钥加密这条消息,告诉你(以公开文本或另一条消息的形式)它是如何加密的。然后你可以用我的公钥解密这个消息,如果它变得可读,你就知道它来自我。

这种形式的加密是相当计算机密集型的,所以有时会使用 RSA 技术加密一次性“密钥”,然后用密钥加密消息的其余部分,然后加密我的签名第二种方式。 然后,您反转此过程,因此如果消息和签名是可读的,那么只有您可以阅读它,并且您可以确保我发送了消息。

您可以访问此链接以获得更详细的说明。

How do API Keys and Secret Keys work?

【讨论】:

  • 很好的答案,但是当我在 Facebook 或 Gmail 等中使用 API 机密和密钥时,我绝不需要加密或散列任何东西。在这些情况下,API 机密和密钥的意义何在?
  • 以 Facebook 为例,您可以在两种情况下使用 app_secret。第一个不需要散列。它主要用于防止您的重定向网址被劫持。在用户登录并授予您的应用访问权限后,如果 facebook 将访问令牌直接发送到重定向 url,您将无法验证访问令牌是否来自 Facebook。我可以将我自己的访问令牌发布到您的重定向 url 并执行来自您的 api 的 facebook 操作。相反,facebook 会向重定向 url 发送一个代码。然后 api 将代码交换为实际的访问令牌。
  • 在后半部分,将代码交换为实际的访问令牌,facebook 希望您的 api 通过签名验证其身份。在这种情况下,他们不需要公钥加密进行签名,他们只是相信您会真正保密您的应用程序并将其用作您的签名。对我来说,不继续使用单向函数来生成签名似乎总是很愚蠢,但我想他们有诸如性能等原因来解决直接使用应用程序密钥的问题。
  • 我想既然你选择了这个额外的安全功能,你也已经做出了某种决定,以允许 Facebook 使用加密哈希调用验证你的签名的额外性能开销。无论如何,在这种情况下,您将通过 Facebook api 请求传递两个值。 access_token 和一个名为 appsecret_proof 的值,用作您的签名。应用秘密证明是通过使用 app_secret 作为密钥对 access_token 进行加密散列生成的。
  • 我很惊讶这被选为接受的答案。该问题询问 API 密钥和密钥,我认为它们与公钥加密或加密没有任何关系。马库斯·亚当斯(Marcus Adams)的那个确实是这个问题的答案。
【解决方案2】:

您需要两个单独的密钥,一个告诉他们您是谁,另一个证明您就是您所说的那个人

“key”是您的用户 ID,“secret”是您的密码。他们只是使用“关键”和“秘密”术语,因为他们就是这样实现的。

【讨论】:

  • 如果你通过 https 进行通信呢?那么用一些密钥加密你的消息有什么意义呢?
  • 重点始终是降低风险。如果 https 通信受到破坏,那么可以读取您的请求的攻击者将无法伪造新的请求。如果你的 API 即将对猫的图片进行排名,没什么大不了的,如果它是一个支付 API,你最好有多个安全层 :)
  • 我想它的目的是两个单独的密钥,因为单个客户端应用程序的不同用户可以有不同的秘密,否则如果他们都拥有相同的秘密,那么拥有一个密钥就没有用了。对吗?
  • 为什么这些 API 不使用Bearer: 身份验证呢?你会有一个 ID 和一个密码。
【解决方案3】:

简单的答案,如果我理解正确的话......

如果您使用 API 密钥进行加密,服务如何知道谁在联系他们?他们将如何解密该消息?

您使用 API 密钥来说明您的身份,这就是您以纯文本形式发送的内容。 您不发送给任何人的秘密密钥。您只需将其用于加密。然后你发送加密的消息。您不发送用于加密的密钥,这会破坏目的。

【讨论】:

  • 你会的。您将 api 密钥发送到服务器。因此,这意味着您将该价值提供给任何可能拦截您与服务器通信的人。
  • 几乎我见过的每个 API 都有你将密钥和秘密都发送到服务器。与服务器的连接在理论上以相同的安全级别进行加密。但我从不给服务器以外的任何人。
  • 我从未见过以纯文本形式发送secret。你能给我一个链接吗?我看到的是使用secret 来加密一些数据。并连同加密数据一起发送apiKey,以便服务器知道如何解密数据。
  • twilio.com/docs/sms/tutorials/…nexmo.github.io/Quickstarts/sms/send 是我看到的例子,促使我在 StackOverflow 上进行搜索。
  • Twilio 并未完全使用这些术语。但是 Nexmo 肯定是……但是,快速浏览后,他们似乎只是在调用数据 secretapiKey,而他们实际上在做的是 usernamepassword。这是完全不同的事情......
【解决方案4】:

有解释什么是秘密和(公共)密钥的答案。这是一个公钥-私钥对,他们给出了令人困惑的名称。但是没有人说为什么 API 需要两者,而且许多 API 只给你一个秘密!我也从未见过任何 API 的文档解释为什么它们有两个键,所以我能做的最好的就是推测......

最好只将你的公钥放在你的请求中,并用你的私钥在本地对请求进行签名;不再需要发送任何内容。但是有些人只是在请求中包含秘密就逃脱了。好的,任何好的 API 都会使用一些传输安全性,比如 TLS(通常通过 HTTPS)。但是您仍然以这种方式将您的私钥暴露给服务器,从而增加了他们以某种方式错误处理它的风险(参见:最近发现的 GitHub 和 Twitter 的密码记录错误)。 HTTPS 在理论上同样安全,但始终存在实施缺陷。

但是很多——实际上似乎是大多数——API 让你在请求中发送两个密钥,因为这比让人们自己签名更容易;否则不能有纯 cURL 示例!在这种情况下,将它们分开是没有意义的。我想单独的密钥只是为了以防他们稍后更改 API 以利用它们。或者有些人有一个客户端库,可能会以更安全的方式做到这一点。

【讨论】:

    【解决方案5】:

    我没有看到这里提到的一件事,虽然它是 Marcus Adams 答案的扩展,但如果有可能@987654321,你不应该使用一条信息来识别和验证用户@,它可以使用响应时间的差异来猜测字符串比较的距离。

    如果您使用的系统使用“密钥”来查找用户或凭据,则可以通过发送数千个请求并检查数据库查找所需的时间来逐步猜测该信息(或找不到)记录。如果“密钥”以明文而不是密钥的单向哈希存储,则尤其如此。如果您需要能够再次向用户显示密钥,您可能希望以明文或对称加密的形式存储用户的密钥。

    通过拥有第二条信息或“秘密”,您可以首先使用“密钥”查找用户或凭据,这可能容易受到定时攻击,然后使用定时安全比较功能来检查“秘密”的价值。

    这是 Python 对该函数的实现:

    https://github.com/python/cpython/blob/cd8295ff758891f21084a6a5ad3403d35dda38f7/Modules/_operator.c#L727

    它暴露在hmac lib(可能还有其他)中:

    https://docs.python.org/3/library/hmac.html#hmac.compare_digest


    这里要注意的一点是,我认为这种攻击不会对查找前经过散列或加密的值起作用,因为每次输入字符串中的字符发生变化时,被比较的值都会随机变化.我找到了一个很好的解释 here

    存储 API 密钥的解决方案是:

    1. 使用单独的密钥和秘密,使用密钥查找记录,并使用时间安全比较来检查秘密。这允许您再次向用户显示密钥和秘密。
    2. 使用单独的密钥和秘密,对秘密使用对称的确定性加密,并对加密的秘密进行正常比较。这使您可以再次向用户显示密钥和秘密,并且可以使您不必进行时间安全比较。
    3. 使用单独的密钥和秘密,显示秘密,散列并存储它,然后对散列的秘密进行正常比较。这消除了使用双向加密的必要性,并具有在系统受到损害时保护您的秘密安全的额外好处。它的缺点是您无法再次向用户显示秘密。
    4. 使用单一密钥,向用户展示一次,对其进行散列,然后对散列或加密密钥进行正常查找。这使用单个键,但无法再次向用户显示。如果系统受到威胁,则可以确保密钥安全。
    5. 使用单一密钥,向用户展示一次,对其进行加密,然后正常查找加密的密钥。可以再次向用户展示,但如果系统受到威胁,则密钥易受攻击。

    其中,我认为 3 是安全性和便利性的最佳平衡点。我已经在许多网站上看到了在获取密钥时实现了这一点。

    另外,我邀请任何真正的安全专家来评论这个答案。我只是想把这个作为另一个讨论点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-05
      • 2018-07-04
      • 1970-01-01
      • 2014-05-25
      • 2011-10-13
      • 2013-09-15
      • 2019-11-29
      相关资源
      最近更新 更多