繁体   English   中英

使用散列的“密码”生成HMAC签名

[英]Generating HMAC signature with hashed “password”

我在RESTful API项目中使用身份验证方法,我非常喜欢生成HMAC-SHA256签名作为身份验证方法的想法。

客户端只需几个简单的步骤即可创建签名:

# example client-side code
sig = hmac.new(bytes('SUPER_SECRET_KEY', 'utf-8'), b'', sha256)
sig.update(request_path)
sig.update(request_body)
# ...other variables needed for generating the signature...

signature = sig.hexdigest()

并将其及其“用户名”添加到请求标头(例如, Authorization: THE_USER_NAME:abcd1234xyz890 )。

在服务器端,我试图以相同的方式重新创建它:

# example server-side code
def do_check(request):
    # get user name from request header
    username = request.headers['Authorization'].split(':')[0]

    # some method to retrieve the "secret key" from database
    user = db.User().filter(username=username).one()

    # use user's "secret key" to generate the signature
    sig = hmac.new(bytes(user.key, 'utf8'), b'', sha256)
    sig.update(bytes(request.path, 'utf-8'))
    sig.update(request.data)
    # ...other variables needed for generating the signature...

    return sig.hexdigest()
    # compare the returned signature with the one client sent us...

只要我将用户的密钥以纯文本格式存储在数据库中,这一切就可以正常工作:

| username      | key              |
------------------------------------
| THE_USER_NAME | SUPER_SECRET_KEY |

我们都知道这绝对不可接受的 ,因此我尝试使用bcrypt简单地对SUPER_SECRET_KEY进行哈希处理并存储一个哈希处理的字符串:

| username      | key                                                          |
--------------------------------------------------------------------------------
| THE_USER_NAME | $2b$12$UOIKEBFBedbcYFhbXBclJOZIEgSGaFmeZYhQtaE4l6WobFW1qvIf6 |

我现在面临的问题是,客户端使用了未加密的“秘密密钥”版本来生成签名,由于不再使用纯文本格式,因此无法在服务器端进行签名。

一种类似方法的示例之一是在Amazon Web Services中生成HMAC签名 (也是同一过程的简化说明 ),它不需要任何其他登录或身份验证,也不需要为密钥/提供任何令牌或“替换”。秘密组合。 我真的怀疑AWS是否将秘密以纯文本格式存储在数据库中(?)

如何在数据库中使用哈希表的“秘密密钥”的哈希版本在服务器端重新创建HMAC签名,而又不强制客户端更改其签名生成方法(例如,避免安装bcrypt甚至根本不加密密钥)?

密码哈希不使用共享机密。 散列密码的行为应该破坏实际值,同时保留对密码进行身份验证的能力。 不能合理地期望您从哈希中恢复密码。

Hmac身份验证和验证使用共享机密。 双方都必须知道这个秘密。

因此,密码散列与hmac根本不同,您不能简单地散列hmac密钥。 哈希将不允许您返回到实际密钥。

[澄清后删除不相关的部分]

因此,您必须在某处具有某种机密,但不必将其保存在数据库中。 可以使用对称密码(使用不在数据库中的其他密钥)在数据库中对实际的hmac共享密钥进行加密。 因此,服务器读取加密的hmac秘密密钥,然后对其进行解密并使用。

重要的是您必须以某种可以解密的方式对其进行加密,从而排除了哈希。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM