116

所以现在有很多不同的服务,谷歌 API、Twitter API、Facebook API 等等。

每个服务都有一个 API 密钥,例如:

AIzaSyClzfrOzB818x55FASHvX4JuGQciR9lv7q

所有密钥的长度和它们包含的字符都不同,我想知道生成 API 密钥的最佳方法是什么?

我不是要一种特定的语言,只是创建密钥的一般方法,它们应该是对用户应用程序细节的加密,还是散列,还是随机字符串的散列等。我们是否应该担心散列算法(MSD、SHA1、bcrypt)等?

编辑: 我和几个朋友谈过(电子邮件/推特),他们建议只使用去掉破折号的 GUID。

不过,这对我来说似乎有点 hacky,希望能得到更多的想法。

4

6 回答 6

72

使用专为密码学设计的随机数生成器。然后base-64对数字进行编码。

这是一个 C# 示例:

var key = new byte[32];
using (var generator = RandomNumberGenerator.Create())
    generator.GetBytes(key);
string apiKey = Convert.ToBase64String(key);
于 2013-09-11T00:30:35.937 回答
34

API 密钥需要具有以下属性:

  • 唯一标识授权 API 用户——“API 密钥”的“密钥”部分
  • 验证该用户 - 不能被猜测/伪造
  • 如果用户行为不端,可以撤销 - 通常他们键入可以删除记录的数据库。

通常,您将拥有数千或数百万个 API 密钥,而不是数十亿,因此它们不需要:

  • 可靠地存储有关 API 用户的信息,因为这些信息可以存储在您的数据库中。

因此,生成 API 密钥的一种方法是获取两条信息:

  1. 保证唯一性的序列号
  2. 足够的随机位来填充密钥

并使用私人秘密对其进行签名。

计数器保证他们唯一标识用户,并且签名防止伪造。可撤销性要求在执行任何需要 API 密钥授权的操作之前检查密钥在数据库中是否仍然有效。

如果您需要从多个数据中心生成密钥,或者没有其他好的分布式方式来分配序列号,那么一个好的 GUID 生成器是递增计数器的一个很好的近似值。


或随机字符串的哈希

散列并不能防止伪造。 签名是保证密钥来自您的保证。

于 2014-06-23T14:02:11.097 回答
7

我使用 UUID,格式为小写,不带破折号。

生成很容易,因为大多数语言都内置了它。

API 密钥可能会被泄露,在这种情况下,用户可能希望取消他们的 API 密钥并生成一个新的,因此您的密钥生成方法必须能够满足这一要求。

于 2013-01-20T08:55:02.290 回答
6

如果你想要一个只有字母数字字符的 API 密钥,你可以使用base64-random方法的变体,只使用 base-62 编码。base-62 编码器基于

public static string CreateApiKey()
{
    var bytes = new byte[256 / 8];
    using (var random = RandomNumberGenerator.Create())
        random.GetBytes(bytes);
    return ToBase62String(bytes);
}

static string ToBase62String(byte[] toConvert)
{
    const string alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    BigInteger dividend = new BigInteger(toConvert);
    var builder = new StringBuilder();
    while (dividend != 0) {
        dividend = BigInteger.DivRem(dividend, alphabet.Length, out BigInteger remainder);
        builder.Insert(0, alphabet[Math.Abs(((int)remainder))]);
    }
    return builder.ToString();
}
于 2018-06-20T20:35:58.620 回答
2

您可以通过打开一个新选项卡来尝试您的 Web 浏览器控制台,在 Chrome 上按 CTRL + SHIFT + i,然后输入以下立即调用的函数表达式 (IIFE):

(async function (){
  let k = await window.crypto.subtle.generateKey(
    {name: "AES-GCM",length: 256},true,["encrypt", "decrypt"]);
  const jwk = await crypto.subtle.exportKey("jwk", k)
  console.log(jwk.k)
})()

示例输出:

gv4Gp1OeZhF5eBNU7vDjDL-yqZ6vrCfdCzF7HGVMiCs

参考:

https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey

https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/exportKey

我承认我主要是为自己写这个以供将来参考......

于 2022-02-02T20:13:48.763 回答
1

API 密钥应该是一些随机值。随机到无法预测。它不应包含其所针对的用户或帐户的任何详细信息。如果您确定创建的 ID 是随机的,则使用 UUID 是一个好主意。

例如,早期版本的 Windows 产生了可预测的 GUID,但这是老生常谈了。

于 2013-01-20T09:26:41.153 回答