使用散列 "password" 生成 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()
并将其添加到请求 header 以及他的 "user name"(例如 Authorization: THE_USER_NAME:abcd1234xyz890
)。
在 server-side 上,我正在尝试以同样的方式 re-create 它:
# 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 | b$UOIKEBFBedbcYFhbXBclJOZIEgSGaFmeZYhQtaE4l6WobFW1qvIf6 |
我现在面临的问题是客户端使用了 "secret key" 的 un-hashed 版本来生成我无法在 server-side 上执行的签名,因为我没有它在 plain-text 了。
类似方法的示例之一是 generating HMAC signature in Amazon Web Services (also simplified explanation of the same process),它不需要任何额外的 log-ins 或身份验证,也不会为 [=46] 提供任何令牌或 "replacements" =]组合。我真的怀疑 AWS 是否将秘密以纯文本形式存储在数据库中 (?)
如何在 server-side 上使用数据库中 "secret key" 的散列版本重新创建 HMAC 签名,同时不强制 client-side 更改其签名生成方法(例如避免安装bcrypt
甚至完全散列秘密)?
密码散列不使用共享密钥。散列秘密的行为应该会破坏实际值,同时保留验证密码的能力。不能合理地期望您从哈希中恢复密码。
Hmac 身份验证和验证使用共享密钥。双方都必须知道这个秘密。
因此,密码散列与 hmac 根本不同,您不能简单地对 hmac 密钥进行散列。哈希将不允许您返回到实际密钥。
[澄清后删除无关部分]
所以你必须在某个地方有某种秘密,但它不需要在数据库中。实际的 hmac 共享机密可以使用对称密码在数据库中加密(使用不在数据库中的不同密钥)。因此,服务器读取加密的 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()
并将其添加到请求 header 以及他的 "user name"(例如 Authorization: THE_USER_NAME:abcd1234xyz890
)。
在 server-side 上,我正在尝试以同样的方式 re-create 它:
# 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 | b$UOIKEBFBedbcYFhbXBclJOZIEgSGaFmeZYhQtaE4l6WobFW1qvIf6 |
我现在面临的问题是客户端使用了 "secret key" 的 un-hashed 版本来生成我无法在 server-side 上执行的签名,因为我没有它在 plain-text 了。
类似方法的示例之一是 generating HMAC signature in Amazon Web Services (also simplified explanation of the same process),它不需要任何额外的 log-ins 或身份验证,也不会为 [=46] 提供任何令牌或 "replacements" =]组合。我真的怀疑 AWS 是否将秘密以纯文本形式存储在数据库中 (?)
如何在 server-side 上使用数据库中 "secret key" 的散列版本重新创建 HMAC 签名,同时不强制 client-side 更改其签名生成方法(例如避免安装bcrypt
甚至完全散列秘密)?
密码散列不使用共享密钥。散列秘密的行为应该会破坏实际值,同时保留验证密码的能力。不能合理地期望您从哈希中恢复密码。
Hmac 身份验证和验证使用共享密钥。双方都必须知道这个秘密。
因此,密码散列与 hmac 根本不同,您不能简单地对 hmac 密钥进行散列。哈希将不允许您返回到实际密钥。
[澄清后删除无关部分]
所以你必须在某个地方有某种秘密,但它不需要在数据库中。实际的 hmac 共享机密可以使用对称密码在数据库中加密(使用不在数据库中的不同密钥)。因此,服务器读取加密的 hmac 密钥,对其进行解密并使用它。
重要的是你必须以某种你可以解密的方式对其进行加密,这排除了散列。