使用HMAC-SHA1进行API身份验证 - 如何安全地存储客户端密码?

在使用S3样式身份验证的RESTful API中,API客户端使用HMAC-SHA1使用其密钥对请求进行签名,因此密钥永远不会通过线路传输。 然后,服务器使用该客户端的密钥对客户端进行身份验证,以重复签名过程本身,并将结果与​​客户端发送的签名进行比较。 这一切都很好,但这意味着服务器需要访问客户端共享密钥的明文。面对所有建议,这反对在数据库中清除用户密码。就我所知,只存储密码的盐渍哈希不是一个选项 - 因为那时我无法验证客户端的签名。 我应该强调我的API是RESTful的,因此应该是无状态的:我宁愿在其他API调用之前避免登录步骤。 一种可选的解决方案是使用一些对称密钥算法加密所有用户密码。但是,服务器必须将密钥存储在易于访问的某个地方,例如,在源代码中。这比没有好,但不是最佳解决方案(正如@Rook在他的回答中提到的,它违反了CWE-257)。 解决方案的另一个方向可能是非对称签名,但我无法弄清楚如何将其应用于HMAC,并且找不到关于该主题的任何文章。 我错过了一些明显的东西吗?许多可敬的提供商已经实施了这种认证方案 - 它们不能都违反共同的安全原则,是吗? 如果没有,您是否有可以分享的最佳实践?     
已邀请:
这是对称密钥质询 - 响应式身份验证的缺点 - 您不会将密码置于线路上,但您必须在两端存储密钥。 (HMAC是对称密钥系统)。 请注意,它不是密码 - 这是一个共享的秘密。这里存在根本区别 - 密码通常由用户选择,而共享密钥随机生成并提供给用户(在此上下文中它们通常称为“API密钥”)。 以可逆格式存储密码是不好的,因为如果您的数据库被泄露,那么攻击者已经获得了可能(并且可能已经)在其他地方使用过的密码。另一方面,存储共享秘密并不是一个问题 - 这是您的服务所特有的秘密,因此所有攻击者都获得了登录您服务的能力。 另一方面,可以具有不必在服务器端存储秘密的非对称系统。基本思想是服务器知道客户端的公钥和当前消息序列号。当发送API请求时,客户端递增消息序列号并计算序列号和API请求参数上的签名,服务器可以使用公钥来验证。如果消息包含旧消息序列号,则拒绝消息以防止重放攻击。     
理想情况下,在用户登录后,您可以为他们提供一个加密随机数,该加密随机数用作该会话生命周期的HMAC密钥K.这是一种安全的方法,但它不是RESTful,因为REST是无状态的。每次登录发出的消息认证码的这种想法在技术上是一种状态。 加密密码并将其存储在数据库中违反了CWE-257。     
我不确定我是否在这里遗漏了一些东西但是一个选项是使用散列密码作为对称密钥。     

要回复问题请先登录注册