如何从单个字符串中获取两个独立的密码?
我不确定标题是否准确,如果合适,请随意重命名问题。
我正在考虑在远程服务器上存储敏感数据的服务。为了最大程度地保护隐私,数据将在客户端进行加密(使用 AES),并且加密密钥不会存储在任何地方,因此即使服务器受到威胁,敏感数据仍然相对安全。
现在的问题是,我需要第二个密码才能访问该服务,但是第二个密码必须存储在服务器上的某个位置。
用户注册时会发生这种情况:
- 用户选择用户名/密码(密码 A)和加密密钥(密码 B)。
- hash(密码A)存储在服务器上
- 密码B不存储在任何地方。
然后:
- 用户输入密码A =>密码 A 被传输到服务器 服务器
- 根据用户数据库检查哈希值(密码 A),授予访问
- 客户端下载首选项和加密数据的权限
- 用户输入密码 B ->加密数据被解密(本地)。
这对我来说看起来不错,但缺点是用户需要两个不同的密码。这是不切实际的,而且还存在用户为两者选择相同字符串的风险,从而大大降低了模型的有效性。
我想要的是使用两个独立的密码,但只询问用户一个密码。
第一次尝试
我的第一个想法是询问用户密码,然后将其分成两部分,并使用第一部分作为服务凭证(密码 A),而第二部分将是加密密钥(密码 B)。
这样做的缺点是会降低密码的强度:如果用户提供的字符串已经很弱/很短,则密码 A 和密码 B 会更弱。
第二次尝试
另一种选择:使用用户提供的密码作为加密密钥(密码 B),并使用该密码的哈希值 (SHA-256) 作为服务凭证。
注册:
- 用户选择一个密码 PASS
- hash(PASS) 传输到服务器
- 服务器在用户数据库中存储用户名的 hash(hash(PASS))
然后:
- 用户进入 PASS
- 服务 发送密码 A = hash(PASS) 到服务器
- server检查用户数据库的哈希值(密码 A),授予访问
- 客户端下载首选项,加密数据
- 客户端使用密码 B = PASS 解密加密数据。
这意味着
- 加密密码的哈希值通过网络传输 2) a a
- a hash(hash(加密密钥)) 现在存储在服务器上,即与加密数据一起存储,
这是否会显着降低系统的安全性?即,当攻击者获得对服务器的访问权限时,在知道 hash(hash(加密密钥)) 的情况下是否更容易解密敏感数据?
是否有另一种(更好)的方法来从单个字符串开始获取两个独立的密码?
I'm not sure the title is accurate, please feel free to rename the question if appropriate.
I'm thinking about a service that stores sensitive data on a remote server. For maximum privacy, the data would be encrypted on the client (using AES) and the encryption key not stored in any place, so that should the server be compromised, sensitive data would still be relatively safe.
Now the problem is, I need a second password to access the service, but this second password must be stored somewhere on the server.
This would be what happens when a user registers:
- user picks a username/password (Password A) and an encryption key (Password B).
- hash(Password A) is stored on the server
- Password B isn't stored anywhere.
then:
- user enters Password A => Password A is transmitted to the server
- server checks hash(Password A) against the user db, grants access
- client downloads preferences and encrypted data
- User enters Password B -> encrypted data is decrypted (locally).
This looks good to me, but the drawback is that the user needs two distinct passwords. This is impractical and also carries the risk that users pick the same string for both, strongly reducing the model's effectiveness.
What I would like is to use two independent passwords but only ask the user a single one.
First attempt
The first idea I had is to ask the user a password, then split it in two and use the first part as service credentials (Password A) while the second part would be the encryption key (Password B).
This has the drawback of reducing the strength of the passwords: if the user-provided string is already weak/short, Password A and Password B would be even weaker.
Second attempt
Another option: use the user-provided password as encryption key (Password B) and use a hash (SHA-256) of that password as service credentials.
Registration:
- user picks a single password PASS
- hash(PASS) is transmitted to the server
- server stores hash(hash(PASS)) with username in the user db
Then:
- user enters PASS
- service sends Password A = hash(PASS) to the server
- server checks hash(Password A) against the user db, grants access
- client downloads preferences and encrypted data
- client decrypts encrypted data with Password B = PASS.
This means that
- a hash of the encryption password travels over the network 2) a
- a hash(hash(encryption key)) is now stored on the server, i.e. alongside the encrypted data
Does this significantly reduces the security of the system? I.e. when an attacker gains access to the server, is it easier to decrypt the sensitive data when knowing hash(hash(encryption key))?
Is there another (better) way to get two independent passwords starting from a single string?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我会采取不同的方法。使用 openid 对您的系统进行身份验证。这样您就根本不需要将密码传输到您的服务器。
在第一种方法中,您应该只传输哈希值。
I would go a different approach. Using openid to authenticate to your system. This way you do not have to transmit a password to your server at all.
On your first approach, you should only transmit the hash.
如果我没记错的话, LastPass 使用此系统:
我可能会倒退哪个哈希用于哪个,但听起来你想要非常相似的东西。如果您有兴趣,Security Now #256 中详细解释了整个事情。
If I remember correctly, LastPass uses this system:
I may have it backwards which hash is used for which, but it sounds like you want something very similar. The whole thing was explained in detail in Security Now #256, if you're interested.
使用安全密码方案的建议是正确的。您可能想要做的是将用户文本传递到密码方案之前进行一些小的更改。如果用户输入“password”,则将“passwordLOCAL”传递给本地密码方案,将“passwordREMOTE”传递给远程密码方案。
这允许用户输入单个密码,但仍然拥有两个不同的本地和远程密码。当然,实际上不要使用“LOCAL”和“REMOTE”,这太不安全了。使用两个不同的随机字符串,就像两种不同的盐一样。
The advice to use a secure password scheme is correct. What you might want to do is to make a small change before passing the user's text to the password scheme. If the user enters "password" then pass "passwordLOCAL" to the local password scheme and "passwordREMOTE" to the remote password scheme.
That allows the user to enter a single password yet still have two different local and remote passwords. Don't actually use "LOCAL" and "REMOTE" of course, far too insecure. Use two different random strings, much like two different salts.
正如 @Tim 在他的回答中所建议的 - 不要创建新的用户身份验证方案(您自己的用户 ID 和密码组合)。
根据您构建此应用程序的目的,您基本上有 2 个选择:
请注意,您的应用程序不必必须基于网络才能使用它们。 (不过,您确实需要互联网接入)。 详细信息,请参阅此问题
有关加密的 密钥,使用某种密钥派生函数(也称为
PRF+
)用于密钥派生 - 最好也与其他组件一起使用。例如,向 PRF/KDF 提供以下内容(串联):Francesco secureapp keypad
)这有点类似于 IKEv2 协议中的 AUTH 负载计算,
这样潜在的攻击者就会需要从不同位置访问信息位,以便能够解密用户的敏感数据。
另外,不要在服务器端存储用户的加密密码。每当请求需要的内容时,客户端应始终向用户询问(或将其缓存一定时间),并通过加密通道将其发送(以纯文本或散列形式)到服务器解密。
此外,如果您想对加密密码实施某种密码策略,请参阅此漫画和< a href="https://stackoverflow.com/a/457512/180174">这个答案作为参考应该如何完成。
As suggested by @Tim in his answer - do not create a new user authentification scheme (your own user-id & password combination).
Based on what you are building this for, you basically have 2 options:
Please note that your application does not have to be web based in order to use them. (You do need internet access, though). See this question for details
For the encryption keys, use some sort of Key Derivation Function (also known as
PRF+
) for the key derivation - preferably with other components as well. Feed the PRF/KDF for example the following (concatenated):Francescos secureapp keypad
)This is somewhat similar to AUTH payload calculation in the IKEv2 protocol
This way the potential attacker would need to access bits of information from various locations in order to be able to decrypt user's sensitive data.
Also, don't store the user's encryption password on the server side. The client should always ask it (or cache it for certain amount of time) from the user and send it (in plain or hashed) over an encrypted channel to the server whenever requesting something that needs [en|de]cryption.
Furthermore, if you want to enforce some sort of a password policy on the encryption passwords, see this comic and this answer for reference how it should be done.
您可以在服务器上生成并存储一个 IV(或两个,如果需要),然后将其发送到客户端的 HMAC。这会生成所需的加密密钥。
You could generate and store an IV (or two, if needed) on the server, and send it to the client to HMAC. This produces the encryption keys that are needed.