Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用哈希“生成HMAC签名”;密码";_Python_Python 3.x_Hash_Bcrypt_Hmac - Fatal编程技术网

Python 使用哈希“生成HMAC签名”;密码";

Python 使用哈希“生成HMAC签名”;密码";,python,python-3.x,hash,bcrypt,hmac,Python,Python 3.x,Hash,Bcrypt,Hmac,我正在RESTfulAPI项目中使用身份验证方法,我非常喜欢生成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 gen

我正在RESTfulAPI项目中使用身份验证方法,我非常喜欢生成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()
并将其与他的“用户名”一起添加到请求头中(例如,
授权:用户名: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\u SECRET\u密钥,并存储散列字符串:

| username      | key                                                          |
--------------------------------------------------------------------------------
| THE_USER_NAME | $2b$12$UOIKEBFBedbcYFhbXBclJOZIEgSGaFmeZYhQtaE4l6WobFW1qvIf6 |
我现在面临的问题是,客户端使用未散列版本的“密钥”来生成签名,这是我在服务器端无法做到的,因为我不再有明文形式的签名

类似方法的一个示例是(也)不需要任何额外的登录或身份验证,也不为密钥/秘密组合提供任何令牌或“替换”。我真的怀疑AWS是否将秘密以明文形式存储在数据库(?)


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

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

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

由于这个原因,密码散列与hmac有着本质的不同,您不能简单地散列hmac密钥。散列将不允许您返回实际密钥

[澄清后删除不相关章节]

所以你必须在某个地方有某种秘密,但它不需要在数据库中。可以使用对称密码(使用数据库中不存在的其他密钥)在数据库中加密实际的hmac共享密钥。因此,服务器读取加密的hmac密钥,对其解密,然后使用该密钥


重要的是,您必须以某种可以解密的方式对其进行加密,这就排除了散列。

感谢您在此澄清一些内容!!我试着想想你的句子“……你通常用其他方式进行身份验证,然后对实际的消息使用hmac”,但有些服务使用与我描述的相同的方法,即使没有额外的身份验证。。。我用真实世界的例子更新了我的答案,请查看(上一段之前的段落)。你会注意到这个例子是一个共享的秘密。您通过登录来管理访问密钥()来创建它,然后您有责任将它交给正确的人并保护它不受错误的人的攻击。是的,我理解:)在我的示例中也有一个“共享密钥”(超级密钥)。。。我想弄明白的是,如何避免在我的数据库中将该键存储为未删除的字符串…哦,你只是不希望它以明文形式“在数据库中”,这是合理的。您可以使用对称加密密码或PKPK在数据库中对其进行加密。不管是哪种方式,你都必须让某人键入其他秘密,或者在某个地方以明文形式输入其他秘密来解密它。。。只是不在数据库中。您链接的文档提到了一种常见的解决方案,即将其以明文形式保存在配置文件中,并依靠操作系统在某人的操作系统登录后确保其安全。是的,我一点也不担心客户端将如何存储或隐藏它。。。我担心泄露数据库中的秘密。所以,您建议在我的数据库中使用一些散列函数,而不是使用“varchar”或类似的列类型并以这种方式存储它?类似的东西?