我正在我的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()
并将其与他的“用户名”一起添加到请求标头中(例如Authoration: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密钥,解密并使用该密钥。
重要的是,您必须以某种可以解密的方式对其进行加密,这排除了散列。
消息签名 import hmac digest_maker = hmac.new(b'secret-shared-key-goes-here') with open('lorem.txt', 'rb') as f: while True: block = f.read(1024) if not block: break
虽然我理解加盐和散列密码过程背后的神学,但我不太理解方法论。据我所知,这个问题及其相关答案中列出的方法,以及MSDN的这篇文章,都经历了创建不同长度的salt的步骤,以便在散列给定密码的过程中使用。 但是,稍后检查密码怎么样?据我所知,再次创建哈希将导致生成全新的盐,最终导致在尝试登录时验证失败。 我是否错过了盐或盐配方的保存位置?还是我不太了解这个过程?
我一直在阅读OWASP10,我遇到了存储信息的最佳实践。咸杂碎。在这里,您为每个密码生成一个随机的salt,并对其进行梳理、散列和存储。我的疑问是,如果salt是随机生成的,当用户键入密码时,如何对密码进行身份验证?salt是否与用户名一起保存?如果是这样,这种做法仍然是脆弱的。或者他们是怎么做到的?
我正在尝试将用户从旧的Drupal6 CMS迁移到KeyCloak。我想迁移用户与他们的旧密码,然后分配一个“更新密码”要求的行动到他们的个人资料。 然而,迁移密码似乎有问题,因为我只能以散列形式访问它们。 null 有没有人有幸让这个功能发挥作用?
<?php $pw='simplewind'; $afpw=sp_password($pw);//加密字符串 echo $afpw;//输出加密后的字符串 ?>
问题内容: 我有这个生成 HMAC (而不是简单的消息摘要)的php代码: 并与输入输出是: 我需要在Java中将其克隆。 所以这是我当前的Java克隆: 但这并不能完成工作,因为对于相同的输入(ABC),其输出为: 我尝试了很多其他的Java代码,但没有一个是php版本的精确克隆。 我做错什么了? 问题答案: 您只是忘了模仿Java代码中的行为(无论您需要使用什么)。 用 在您的Java代码中。