0

我正在开发一个需要多个密码才能访问不同数据区域的应用程序。例如,一群人可以建立一个需要密码验证才能查看的聊天。

这是我正在考虑这样做的方式:

我有我的关键字,假设说:

香蕉

当用户输入他们的密码时,我使用 RNCryptorBanana使用他们输入的密钥进行加密,并将该加密字符串存储到服务器。

后来,当有人尝试输入密码时,我从服务器获取哈希值并尝试使用他们输入的密码作为密钥对其进行解密。如果解密的值等于Banana我知道他们输入了正确的密码。

我是安全新手,所以我不确定这是否是一个合适的解决方案。感谢所有帮助。

更新

在进行了@Greg 和恰当命名的@Anti-weakpasswords 建议的一些更改之后,这就是我所拥有的:

- (NSDictionary *) getPasswordDictionaryForPassword:(NSString *)password {

    NSData * salt = [self generateSalt256];
    NSData * key = [RNCryptor keyForPassword:password salt:salt settings:mySettings];

    NSMutableDictionary * passwordDictionary = [NSMutableDictionary new];

    NSString * saltString = stringFromData(salt);
    NSString * keyString = stringFromData(key);

    passwordDictionary[@"key"] = keyString;
    passwordDictionary[@"salt"] = saltString;
    passwordDictionary[@"version"] = @"1.0.0";
    passwordDictionary[@"iterationCount"] = @"10000";

    return passwordDictionary;
}

static const RNCryptorKeyDerivationSettings mySettings = {
    .keySize = kCCKeySizeAES256,
    .saltSize = 32,
    .PBKDFAlgorithm = kCCPBKDF2,
    .PRF = kCCPRFHmacAlgSHA1,
    .rounds = 10000
};

- (NSData *)generateSalt256 {
    unsigned char salt[32];
    for (int i=0; i<32; i++) {
        salt[i] = (unsigned char)arc4random();
    }
    NSData * dataSalt = [NSData dataWithBytes:salt length:sizeof(salt)];
    return dataSalt;
}
4

2 回答 2

5
  • 不要使用任何散列函数的单次传递来存储密码。
  • 不要不使用 8-16 字节范围内的随机盐。
  • 不要使用可逆加密来存储密码。
  • 请勿使用与您输入的密码完全相同的密码作为加密密钥。

相反,当用户选择关键字/密码时

  • 生成一个加密随机的 8-16 字节盐
  • 将 PBKDF2、BCrypt 或 SCrypt 与所述盐一起使用,以及您的处理器可以处理的尽可能大的迭代计数/工作因子来创建密码哈希
    • 如果您特别使用 PBKDF2,请不要请求比本机哈希大小更大的输出(SHA-1 = 20 字节,SHA-256 是 32 字节,SHA-384 是 48 字节,SHA-512 是 64 字节),或者你增加了攻击者相对于你(防御者)的比较优势。

然后在您的数据库中,存储该用户的特定信息:

  • 盐分清
  • 迭代次数/工作系数
    • 因此您可以在以后轻松更改/升级它
  • 生成的密码哈希
  • 身份验证协议的版本 - 这可能是 2,也可能是 1。
    • 因此,如果您稍后从该方法转移到 NewWellKnownMethod,您可以在以后轻松更改/升级它

当用户想要对您的系统进行身份验证时,您:

  • 从数据库中检索他们的版本、盐、迭代计数/工作因子和结果哈希
  • 使用数据库中的盐和迭代计数/工作因子对他们刚刚输入的任何关键字/密码进行哈希处理。
  • 将您刚刚获得的结果与数据库中的结果进行比较;如果他们是一样的,让他们进来。
    • 高级:使用恒定时间比较,所以如果第一个字节不同,它不会只是退出尝试,以减少对时间攻击的脆弱性。

请阅读如何安全地散列密码?,其中 Thomas Porrin 的回答是目前最常被提及的关于密码散列的 Stackexchange 论文,当然也是迄今为止我所见过的最好的。

于 2014-03-22T02:51:43.770 回答
1

这不是一个好方法。您应该使用一种方法散列算法来散列密码(您将无法解密它)。对密码进行哈希处理后,在用户提供密码后将其保存到数据库中,您必须对其进行哈希处理并将其(哈希值)与您存储在数据库中的哈希值进行比较。如果匹配,则表示如果不是身份验证失败,则相同。

这样,即使有人可以访问数据库,数据也将受到保护,他不会对此做任何事情,它不是存储在那里的密码。

大多数身份验证都是这样进行的。

//扩展

您应该使用为此类工作制作的一些哈希算法。

查看SHAMD5

于 2014-03-21T16:10:57.973 回答