服务如何生成和使用公共和秘密API密钥? [英] How services generate and use public and secret API keys?

查看:93
本文介绍了服务如何生成和使用公共和秘密API密钥?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Google,Stripe和许多其他公司都有公共API密钥和Secret API密钥.

生成随机字符串很容易,但是我的问题是,如何生成公共密钥和秘密密钥,将其存储并正确使用它们?

公共API密钥用于告诉用户是谁,秘密在于确认其身份.

我的流程如下:-用户创建一个帐户-用户激活服务(内部)-服务返回一个公共密钥和一个秘密API密钥(UARRHAtPtJcLxx5RmMWo9oTrca4gRt2k,C9YS7Mhzichq2vqBuRkNJxkNci5W2Xua)-用户使用其网站上的公钥和服务器端上的私钥

我使用的是nodejs,当用户要求提供API密钥时,公共密钥是按需生成的:

 让public =等待crypto.randomBytes(32).toString('base64'); 

将机密存储在数据库中就像用明文存储密码.我认为我们不希望这样做,并且需要以某种方式对其进行哈希处理.我是否生成一个私有"密钥并使用argon2对其进行哈希处理?用户将永远无法再次看到他/她的密钥,因此需要立即保存,这是一个好习惯吗?

我找不到太多有关该如何工作的信息.

解决方案

从技术上讲,您所指的只是用户名和密码.唯一重要的区别是,这些通常是由API生成的,并且是非常随机的,与用户选择的真实用户名和密码相反,通常不是非常随机的.(由于公用密钥加密方式不同,因此调用这些公用密钥和专用密钥会产生误导.您通常不需要API密钥,而管理PKI就是蠕虫病毒,正确执行此操作的成本也很高.)

由于从技术上讲,它们与用户名和密码相同,因此您希望对它们进行类似的处理.让我们称这些客户端ID(公共"部分)和客户端密钥(秘密"部分).

一些想法:

  • 您应该使用加密安全的随机生成器来生成随机字符串.上面的 crypto.randomBytes()很好.
  • 您应该考虑熵来设置密钥的适当长度.熵基本上是随机性".键的位数,以位为单位.仅作为示例,如果密钥空间是说1024个具有相同概率的不同可能密钥,那么可以说该密钥具有log2(1024)= 10位熵.熵使密钥的长度与随机源的安全性脱钩,例如,您可能拥有很长的密钥,但仍然很不安全,因为随机源有缺陷.您想要密钥的熵多少取决于用例,例如在任何情况下是否都可能进行离线攻击或仅在线请求等等(您可能还应该考虑使用离线攻击,这种攻击非常非常快)).根据经验,您不应将熵降到128位以下,而为了提高安全性,您应该将熵降到256位以上.如果密钥区分大小写并且为字母数字,则可能有62个不同的字符,密钥长度22提供约131位( log2(62 ^ 22)=〜130.99 ).当然,您总是可以花更长的时间,对于256位,需要区分大小写的字母数字长度为43.
  • 正如您正确指出的那样,存储此类密钥至关重要.至少,您要像其他任何密码一样,将它们散列存储(使用适当的散列,请参阅下文),就像其他任何密码一样,这样即使攻击者获得了对数据库的访问权限,他们也不会看到您的api密钥.任何合适的密钥派生函数(Argon2,bcrypt,PBKDF2等)都适合此目的,但是普通的加密哈希函数(sha1,sha2等)不是.
  • 您正确的是,如果您对这些机密进行哈希处理,则用户将只能在生成这些机密时看到它们,而再也不会看到它们.这就是在安全的在线服务中发生的情况,通常是一种好习惯.您可以警告用户注意该秘密,因为您将无法再次显示它们.(而且,如果他们忘记了,他们可以理想地生成一个新的,因此通常没什么大不了的.)
  • 更好的办法是将这些密钥存储在其他位置.考虑到云,此类秘密的好去处将是您的云提供商提供的服务,例如AWS中的Secrets Manager.好处包括使用KMS密钥加密,审核,并且您可以确保访问密钥的唯一方法是通过适当的IAM角色(例如,您不必担心诸如公开的备份之类的事情).
  • 虽然客户端ID并非机密,但您需要在存储中保护其完整性(以及与客户端机密关联的完整性).想象一下这样一种情况,攻击者可以以某种方式更改您的数据库,并为现有客户端ID分配不同的(攻击者已知的)客户端机密.那将意味着与该客户ID相关联的数据的全面泄露.因此,您要确保除了保持客户端的秘密安全之外,攻击者也无法更改这些密码(例如,通过对涉及组件的访问控制).

Google, Stripe and many other companies have public API key and Secret API key.

It is easy to generate random strings but my question is, how can I generate public and secret keys, store them and use them properly?

The public API key is to tell who the user is and the secret is to confirm their identity.

My flow is as follow: - User create an account - User activates a service (in-house) - The service return a public and a secret API key (UARRHAtPtJcLxx5RmMWo9oTrca4gRt2k, C9YS7Mhzichq2vqBuRkNJxkNci5W2Xua) - User use the public key on his/her website and the private key on the server-side

I am using nodejs and the public key is generated on demand, when the user asks for an API key:

let public = await crypto.randomBytes(32).toString('base64');

Storing the secret in a database would be like storing password in plaintext. I presume we do not want this and it needs to be hashed somehow. Do I generate a "private" key and hash it using argon2 for example? The user will never be able to see his/her key again and will need to save it right away, is this good practice?

I couldn't find much information on how this is suppose to work.

解决方案

Technically what you are referring to are just a username and a password. The only important difference is these are typically generated by the API and very random, as opposed to a real username and password which are chosen by a user, and usually not very random. (Calling these public and private keys is a little misleading as public key cryptography is different - you don't typically need that for API keys, managing a PKI is a can of worms, and also very costly to do it properly.)

As these are technically the same as a username and a password, you want to treat them similarly. Let's call these client id (the "public" part) and client key (the "secret" part).

A few thoughts:

  • You should use a cryptographically secure random generator to generate random strings. crypto.randomBytes() as above is fine.
  • You should consider entropy to set an appropriate length for the key. Entropy is basically the "randomness" of your keys, and is measured in bits. Just for an example, if the key space is say 1024 different possible keys with equal probabilities, then you can say the key has log2(1024) = 10 bits of entropy. Entropy decouples the length of the key from the security of the random source, for example you can have very long keys which are still not secure, because the random source is flawed. How much entropy you want for your keys depends on the usecase, like if offline attacks are possible in any scenario or online requests only and so on (you should likely count with offline attacks too, which are very fast). As a rule of thumb, you should not go below 128 bits of entropy, and for higher security you should probably go 256+ bits. If the key is case sensitive and alphanumeric, then there are 62 different possible characters, a key length of 22 provides ~131 bits (log2(62^22) =~ 130.99). You can always go longer of course, for 256 bits you would need a length of 43 with case sensitive alphanumeric.
  • As you correctly noted, storing such keys is critical. At the very least, you would want to store them hashed (with an appropriate hash, see below), just like any other password, so that even if an attacker gains access to your database, they won't get to see your api keys. Any proper key derivation function (Argon2, bcrypt, PBKDF2 and so on) is fit for this purpose, but plain crypto hash functions (sha1, sha2 and so on) are not.
  • You are right that if you hash these secrets, the user will only be able to see them when they are generated and never again. That's exactly what happens in secure online services, and is generally a good practice. You can warn your user to take note of the secret because you will not be able to show them again. (Also they can ideally generate a new one if they forgot it, so it's usually not a big deal.)
  • Even better would be to store these keys somewhere else. Thinking about cloud, a good place for such secrets would be a service provided by your cloud provider, like for example Secrets Manager in AWS. The benefits include encryption with a KMS key, auditing, and you can make sure that the only way to access your keys is through appropriate IAM roles (you don't need to worry about things like a disclosed backup for example).
  • While the client id is not a secret, you need to protect its integrity (and the integrity of the association with a client secret) in your storage. Imagine a scenario where an attacker can somehow alter your database and assign a different (attacker-known) client secret to an existing client id. That would mean a total compromise of data associated with that client id. So you want to make sure that besides keeping the clietn secret secure, it is also not possible for an attacker to change those (via for example access control to components involved).

这篇关于服务如何生成和使用公共和秘密API密钥?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆