如何使用用户友好的客户端密码实现强大的服务器端帐户密码

时间:2012-11-26 00:38:25

标签: .net security encryption

我要求用户在单个设备上使用4+数字引脚式密码。显然这是一个不好的密码,可以直接用于保护他们的服务器端帐户,所以我想锁定'此PIN到特定设备,以便某人必须同时拥有PIN和设备才能登录,并且获取设备访问权限的人无法访问PIN。此外,他们已经拥有更常规的用户名/密码登录,并且通过注册设备,他们正在为此现有帐户添加一组新的登录凭据。所以这是我目前的计划:

  1. 在本地设备注册过程中,本地生成一个强密码。
  2. 将此生成的强密码作为服务器端设备特定帐户密码发送到服务器。
  3. 使用提供的4位数密码对本地对称加密强生成的密码。
  4. 将此加密的强密码存储在本地设备上。
  5. 在该设备上的后续登录过程中,用户提供相同的4位数密码,用于解密以前存储的强密码,并将强密码发送到服务器进行登录。
  6. 所以我相信这实现了强大的服务器端密码要求。但是,我还需要在注册过程之后尽可能地保护受攻击的客户端设备(在注册过程之前/期间受损的设备是丢失的原因)。显然,使用4位加密密钥,只有10,000种可能的组合,因此攻击者可以很容易地快速尝试本地加密的强密码的每种组合。 我想知道的是,我是否必须选择特定的对称加密方案和/或生成的密码格式,以便攻击者无法单独从本地数据中分辨出哪些10k解密尝试是正确的? 即他仍然必须在服务器端登录时尝试每个10k密码。

    此外,这种方法或实现这些要求的更标准方法是否存在明显的错误?如果有标准方法,那么这种方法是否有标准的.NET库?

2 个答案:

答案 0 :(得分:4)

您可以在本地设备中存储salt并使用PBKDF2计算key1。然后使用该密钥服务器端使用单独存储的盐计算key2。由于key1从未存储过,因此攻击者没有所需的信息。

答案 1 :(得分:2)

您的解决方案“糟糕”,因为无论您使用的加密程度如何“强大”,攻击者必须搜索的密钥空间非常小。即使使用8位数字密码,也只有10 ^ 8或1亿个可能的密钥。

我的方法会有所不同。我首先要问“为什么在设备上存储任何凭据?”我不相信这个问题有一个很好的答案。

而是考虑这个解决方案:

用户想要激活PIN。首先,他选择了PIN;让我们打电话给他的选择N.他联系你的网络服务,用他的用户名和密码识别自己并发送N。

在服务器端,你生成一个随机字符串,让我们称之为X.你连接X和N,然后使用像SHA-256这样的哈希。让我们调用结果H.服务器现在存储(X,H)。请注意,您的服务器存储PIN。

稍后,当用户打开移动设备并输入他的PIN时,设备会联系您的网络服务并说:“我即将为用户'Nik Bougalis'执行PIN验证。给我一个挑战!“

服务器为此身份验证创建一个状态:它找到帐户记录,找到X值并发送给用户“X,R”,其中R是为此状态生成的随机数。

用户输入他的PIN,我们称之为P.移动设备现在连接X和P,并使用服务器使用的相同算法对结果进行哈希处理,生成H.它现在将H和R组合,并散列结果。这会生成一个新哈希,我们称之为V。

移动设备将V发送到服务器。服务器组合来自数据库的H值和与状态相关联的R,散列组合并将其与V进行比较。如果它们匹配,则在移动设备中输入的PIN是正确的,并且您授予用户访问权限。如果它们不匹配,则输入的PIN码不正确。

此方法的优点是服务器可以对身份验证尝试进行速率限制并减缓暴力攻击。它甚至可以在太多次尝试失败后锁定帐户,需要密码才能解锁。

如果你通过SSL进行这整个交换,你可以跳过发送随机值R,虽然计算成本太低,我还是只包括它。

潜在的缺点是,如果设备无法与服务器通信,则用户无法使用PIN“登录”。我不知道你是否要求允许离线登录,但根据你的特定应用程序和市场,这可能不是什么大问题 - 有些人甚至称之为优势。

要明确的是,这不是“超级防弹解决方案”。如果有人闯入并获得对包含H值的表的访问权限,则他们可以在不知道PIN的情况下冒充用户。如果这是一个问题,那里有一些解决方法。

如果您真的对高安全性感兴趣(我怀疑您,因为您正在考虑4位数的PIN),可以使用更先进的算法来执行零知识的身份证明。