为什么使用 API 密钥和机密?

我遇到过许多既给用户提供 API 钥匙又给用户提供 秘密的 API。但我的问题是: 两者之间的区别是什么?

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

那为什么要用两把钥匙?

Edit: or is that API key used to lookup the API secret?

68857 次浏览

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

RSA security is based on 2 matching keys. There is a public key for each user, and everybody can (should) know it. There is also a private key that only the user should know. A message encrypted by the public key can only be decrypted by the private key, and visa versa.

因此,如果我想给你发送一条只有你能读的消息,我会从网络中获得你的公钥,用这个密钥加密这条消息,而你是唯一能够解密它的人。

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

This form of encryption is fairly computer intensive, so what sometimes done is, to encrypt a one-time "secret key" with RSA technology is used, then encrypt the rest of the message with the secret key, then encrypt my signature in the second fashion. 然后逆转这个过程,因此如果消息和签名是可读的,那么只有您可以读取它,并且确保我发送了消息。

或者

you can visit this link for more detailed explanation.

How do API Keys and Secret Keys work?

你需要两把不同的钥匙,一把能告诉他们你是谁,另一把能证明你就是你所说的那个人。

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

Simple answer, if I understood it correctly...

如果您使用 API 密钥进行加密,服务如何知道谁在联系他们?他们要怎么解密那条信息?

您使用 API 键来声明您是谁,这是您发送的纯文本。 任何人的密钥。你只需要用它来加密。然后发送加密信息。如果不发送用于加密的密钥,就会破坏加密的目的。

有解释什么是秘密和(公开)密钥的答案。这是一对公私钥匙,他们给它起的名字让人摸不着头脑。但是没有人说明为什么 API 需要两者,而且许多 API 只给了您一个秘密!我也没见过任何 API 的文件解释为什么他们有两把钥匙,所以我只能推测..。

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

But many – actually most it seems – APIs have you send both keys in requests since that's easier than making people do their own signatures; can't have pure cURL examples otherwise! In that case, it's pointless to have them separate. I guess the separate keys are just for in case they change the API later to take advantage of them. Or some have a client library that might do it the more secure way.

有一点我没有在这里提到,尽管它是 Marcus Adams 答案的一个扩展,那就是如果存在 时间攻击的可能性,就不应该使用单个信息来识别和验证用户,时间攻击可以利用响应时间的差异来猜测字符串比较到了什么程度。

如果你使用的系统使用“密钥”来查找用户或凭证,那么随着时间的推移,通过发送成千上万的请求和检查数据库查找(或不查找)记录所花费的时间,这些信息可以被逐步猜测出来。如果“密钥”以明文形式而不是密钥的单向散列形式存储,则尤其如此。如果需要再次向用户显示密钥,则需要以明文或对称加密的方式存储用户的密钥。

通过拥有第二条信息,或者说“机密”,你可以首先使用“密钥”来查找用户或者证书,这些信息很容易受到定时攻击,然后使用一个定时安全的比较函数来检查“机密”的值。

下面是 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. 使用单独的密钥和 secret,显示 secret,散列并存储它,然后对散列 secret 进行正常的比较。这就消除了使用双向加密的必要性,并且在系统受到攻击时还有保护您的秘密安全的额外好处。它的缺点是不能再次向用户显示这个秘密。
  4. 使用 一把钥匙,向用户显示一次,散列它,然后对散列或加密的密钥进行正常的查找。这只使用一个键,但不能再次显示给用户。如果系统受到攻击,有保证密钥安全的好处。
  5. 使用 一把钥匙,将其显示给用户一次,对其进行加密,然后对加密的秘密进行常规查找。可以再次显示给用户,但代价是如果密钥系统受到破坏,那么密钥就容易受到攻击。

其中,我认为3是最好的平衡安全和方便。我已经看到这个实施在许多网站时,得到密钥发出。

此外,我邀请任何实际的安全专家对这个答案进行评论。我只是想把这个说出来,作为另一个讨论点。