AES-256最佳实践实施

时间:2017-06-08 21:38:13

标签: encryption aes

我正在推翻应用,但我不是 AES算法的专家。 该应用程序为用户提供了脱机登录的机会。

要求用户提供 用户名 密码

这是用于存储用户信息的功能

    public void EncryptLoginInfo(string username, byte[] secretShared, byte[] salt)
{
  byte[] random = calc.GenerateRandomBytes();
  byte[] array = aes.Encrypt(secretShared, random);
  OfflineLogin loginInfo = new OfflineLogin()
  {
    Username = username,
    SecretShared = array,
    Iv = random,
    Salt = salt
  };
  this._userCredentials.StoreOfflineLoginData(username, loginInfo);
}

这是存储在应用程序内部配置文件中的信息。在下面的示例中,传递给 encryptLoginInfo 密码 123

Username: not_important
SecretShared: 4KVrjy1cQVWYpWF7aolpMS0HzhKyFf+9VXauQrXoXVUbf0bGXIDOLDJuSVhYoFo2
Iv:yil4nn02IoKsOnX5KXVsDg==
Salt: 5kJio2VQEqjomHRdQMqRVJ0zkBsmqi8K3NypC2VWJk4

如果用户想要进行离线登录,则会要求他提供用户名和密码。

问题:这个算法安全吗?如果攻击者能够获得SecretShared + Iv + Salt,则他能够恢复用户的密码(在此特定示例中为 123

这是解密功能

public void DencryptLoginInfo(OfflineLogin loginInfo)
{
  byte[] array = aes.Decrypt(loginInfo.SecretShared, loginInfo.Iv);
  loginInfo.SecretShared = array;
  loginInfo.Iv = (byte[]) null;
}

您是否能够发现此实施中的任何安全问题? 使用的算法应该是AES-256。。您是否能够在python中实现POC以在给出SecretShared + Iv + Salt的情况下解密密码?

1 个答案:

答案 0 :(得分:1)

根据您的评论,您的目标是验证用户身份。为此,我们在密码上使用密码基本密钥派生函数。通常人们将此称为“哈希密码”,这是一个不幸的术语,因为“哈希”可能意味着什么。但重点是我们不加密密码,而是通过一个设计缓慢的单向函数发送它们。缓慢的速度阻止了暴力攻击。

您不需要IV来执行此操作。相反,你的应用程序应该派生一个盐,并使用基于密码的密钥派生函数(有时称为“密码哈希”算法:你将不得不原谅业界已经弄清楚了这个主题的术语) 。您可以在整个网络上找到有关此内容的指导。但我建议您阅读point 4 in Top 10 Developer Crypto Mistakes以了解实施此问题时常见的陷阱。

不要使用openssl将密码转换为密钥(或密码哈希)! openssl中的算法是weak。 Openssl的EVP_BytesToKey()无法满足慢速的要求,这意味着很容易从密码中强行输入密钥。

这个问题的正确解决方案是使用诸如bcrypt或pbkdf2之类的算法(可以毫不费力地找到Java实现)从密码中导出“哈希”。然后,通过使用用户输入的密码和为此密码存储的盐重新执行相同的计算,验证用户是否正确输入了密码。如果匹配,则授予访问权限,否则访问被拒绝。

请注意,如果此应用与服务器进行交互,通常您会在服务器端进行密码验证。如果您的应用不与服务器交互,那么您可能有充分的理由在设备上进行此操作。我不知道你的应用程序做了什么,所以我不能告诉你对你有什么用。对不起。

正确执行此操作的一个很好的参考是How to Safely Store Your Users' Passwords in 2016