How to obtain two independent passwords from a single string?
我不确定题目是否准确,如果合适,请随意改名。
我正在考虑在远程服务器上存储敏感数据的服务。为了最大限度地保护隐私,数据将在客户机上加密(使用AES),加密密钥不会存储在任何地方,因此,如果服务器受到攻击,敏感数据仍然是相对安全的。
现在的问题是,我需要第二个密码来访问服务,但是第二个密码必须存储在服务器的某个地方。
当用户注册时会发生这种情况:
- 用户选择用户名/密码(密码A)和加密密钥(密码B)。
- 哈希(密码A)存储在服务器上
- 密码B不存储在任何地方。
然后:
- 用户输入密码A=>密码A传输到服务器
- 服务器根据用户数据库检查哈希(密码A),授予访问权限
- 客户端下载首选项和加密数据
- 用户输入密码b->加密数据被解密(本地)。
这看起来不错,但缺点是用户需要两个不同的密码。这是不切实际的,同时也带来了用户为两者选择相同字符串的风险,这大大降低了模型的有效性。
我想要的是使用两个独立的密码,但只要求用户一个。
第一次尝试我的第一个想法是询问用户一个密码,然后将其分为两部分,并使用第一部分作为服务凭据(密码A),而第二部分是加密密钥(密码B)。
这样做的缺点是降低了密码的强度:如果用户提供的字符串已经很弱/很短,那么密码A和密码B将更弱。
第二次尝试另一个选项:使用用户提供的密码作为加密密钥(密码B),并使用该密码的哈希(sha-256)作为服务凭据。
注册:
- 用户选择一个密码通行证
- 哈希(pass)传输到服务器
- 服务器在用户数据库中存储用户名为的哈希(哈希(pass))。
然后:
- 用户进入通行证
- 服务向服务器发送密码a=hash(pass)
- 服务器根据用户数据库检查哈希(密码A),授予访问权限
- 客户端下载首选项和加密数据
- 客户端使用密码b=pass解密加密数据。
这意味着
这会显著降低系统的安全性吗?也就是说,当攻击者获得对服务器的访问权限时,在知道哈希(哈希(加密密钥))时解密敏感数据是否更容易?
有没有另一种(更好的)方法从一个字符串开始获取两个独立的密码?
我会采取不同的方法。使用OpenID对系统进行身份验证。这样就不必向服务器传输密码。
在第一种方法中,您应该只传输哈希。
使用安全密码方案的建议是正确的。您可能需要做的是在将用户的文本传递到密码方案之前做一个小的更改。如果用户输入"password",则将"password local"传递到本地密码方案,将"password remote"传递到远程密码方案。
这允许用户输入一个密码,但仍然有两个不同的本地和远程密码。当然,不要使用"本地"和"远程",太不安全了。使用两种不同的随机串,就像两种不同的盐。
正如@tim在回答中建议的那样-不要创建新的用户身份验证方案(您自己的用户ID和密码组合)。
根据您为此构建的内容,您基本上有两个选项:
- 如果在企业内部应用程序中只集成到Active Directory或任何内部用户数据库和身份验证后端,则
- 如果这是公共的,请使用OpenID(如果您只需要身份验证)或OAuth(如果您还需要授权)。
请注意,您的应用程序不必基于Web才能使用它们。(不过,你确实需要上网)。有关详细信息,请参阅此问题
对于加密密钥,使用某种类型的密钥派生函数(也称为
- 来自验证器的用户唯一标识符(openid、ad、随便什么)
- 系统范围的应用程序标识符字符串(例如
Francescos secureapp keypad ) - 与用户信息一起存储的每用户随机数据(例如,来自系统随机源的16个字节)
- 用户的加密密码-这是您必须关心的单一密码。
这与ikev2协议中的auth有效负载计算有些相似。
这样,潜在的攻击者就需要访问来自不同位置的信息位,以便能够解密用户的敏感数据。
另外,不要在服务器端存储用户的加密密码。每当请求需要[加密]的内容时,客户机应该总是向用户询问(或缓存一定时间),并通过加密通道将其发送到服务器(以普通或散列方式)。
此外,如果您想对加密密码实施某种密码策略,请参阅本手册和此答案,以了解如何执行。
如果我没记错,LastPass使用这个系统:
我可能把它倒过来,哪个哈希用于哪个,但听起来你想要非常相似的东西。如果你感兴趣的话,整个事情现在已经在安全中详细解释了256。
您可以在服务器上生成并存储一个IV(或者两个,如果需要的话),然后将它发送到客户机HMAC。这将生成所需的加密密钥。