Security 在Phoenix/Elixir中对api键进行散列,并为此使用comeonin

Security 在Phoenix/Elixir中对api键进行散列,并为此使用comeonin,security,hash,elixir,phoenix-framework,Security,Hash,Elixir,Phoenix Framework,在我的系统中,每个用户都可以有多个api密钥。我想散列api键并将它们的散列存储在数据库中。我用comeonin来做这个 1) 存储api键的散列而不是它们的普通原始值是否明智 2) 当一个api请求进来时,里面只有一个普通的api键值,没有用户的电子邮件——这是我设计的系统 如何检查api密钥是否有效?我必须这样做吗--重新计算散列 given_api_plain_key = get_key_from_request() # re-hash it again # but how about

在我的系统中,每个用户都可以有多个api密钥。我想散列api键并将它们的散列存储在数据库中。我用comeonin来做这个

1) 存储api键的散列而不是它们的普通原始值是否明智

2) 当一个api请求进来时,里面只有一个普通的api键值,没有用户的电子邮件——这是我设计的系统

如何检查api密钥是否有效?我必须这样做吗--重新计算散列

given_api_plain_key = get_key_from_request()

# re-hash it again
# but how about the original salt???

given_api_hash_key = Comeonin.Bcrypt.hashpwsalt(given_api_plain_key)


case Repo.get_by(ApiKey, key_hash: given_api_hash_key) do
  nil -> IO.puts("not found")
  a -> IO.puts("gooood")
end
或者有更好的方法吗?

(1)存储api键的哈希值而不是它们的普通原始值是否明智

您的目标似乎是防止在有人访问您的数据库(例如,通过SQL注入、命令注入或系统上的反向shell)时可能发生的重大损害。在这种情况下,是的,这是明智的,特别是如果每个用户都有不同的API密钥。然而,对于可能影响您决策的其他考虑因素,值得一读

(2) 如何检查api密钥是否有效

很明显,您需要散列输入,并查看是否与数据库中的某些内容匹配

(3) 实施

您不希望应用与密码相同的保护。密码本质上倾向于具有低熵,因此我们需要像bcrypt这样的工具来处理它们。Bcrypt在设计上很慢(以防止暴力攻击),并且使用盐类来帮助选择不当的密码的安全性

API键不应该具有低熵,因此您不需要慢函数来处理它们。事实上,速度慢的函数会带来DoS风险,所以您肯定不希望对每个传入的请求都执行bcrypt。盐分也使用例复杂化(当您知道谁在提供输入时,盐分起作用,但在您的情况下,您事先不知道输入来自谁)


简短回答:只需使用SHA256,不需要盐。

bcrypt是密码的一个很好的解决方案:因为密码往往具有低熵,bcrypt通过降低散列计算速度来减缓暴力攻击。但API密钥可能具有高熵,因此暴力攻击不存在这种风险。总结:一个更快的函数,比如SHA256,可能更适合您的设计。@TheGreatContini,好吧,这是答案的一部分。在@TheGreatContini的评论之后,我认为只要您生成的API键是长且随机的,就根本不需要哈希。关于散列API密钥的想法:根据这一点,SHA是没有解密机制的单向加密。那么,以这种方式存储API密钥有什么意义呢?