使用散列“密码”

时间:2017-07-24 14:32:14

标签: python python-3.x hash bcrypt hmac

我在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 |

我们都知道这是绝对不可接受,因此我尝试使用SUPER_SECRET_KEY简单地散列bcrypt并存储散列字符串:

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

我现在面临的问题是客户端使用未散列版本的“密钥”来生成我无法在服务器端执行的签名,因为我不再使用纯文本了。

类似方法的一个示例是generating HMAC signature in Amazon Web Services(也是simplified explanation of the same process),它不需要任何额外的登录或身份验证,也不提供密钥的任何令牌或“替换”/秘密组合。我真的怀疑AWS是将秘密存储在数据库中的纯文本中吗?(?)

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

1 个答案:

答案 0 :(得分:1)

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

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

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

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

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

重要的是你必须以某种方式加密它,你可以解密,并排除散列。