密码验证 - 如何安全检查输入的密码是否正确 [英] Password Verification - How to securely check if entered password is correct

查看:754
本文介绍了密码验证 - 如何安全检查输入的密码是否正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



以下是我正在考虑的方式:



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


香蕉


< blockquote>

当用户输入密码时,我使用RNCryptor使用输入的密钥加密 Banana ,并将加密的字符串存储到服务器。



稍后,当有人尝试输入密码时,我从服务器获取散列值,并尝试使用他们输入的密码作为密钥进行解密。如果解密的值等于香蕉我知道他们输入了正确的密码。



我是新来的安全我不知道这是否是一个合适的解决方案。所有的帮助都不胜感激。



更新



在进行了@Greg和apt @ -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]; (int i = 0; i <32; i ++){
salt [i] =(unsigned char)arc4random();

}
NSData * dataSalt = [NSData dataWithBytes:salt length:sizeof(salt)];
return dataSalt;
}


解决方案


  • 不要使用任何哈希函数的一次通过来存储密码。

  • 不要在8-16字节范围内使用随机盐。

  • 不要使用可逆加密来存储密码。

  • 不要使用正确输入的加密密钥。



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




  • 生成一个密码随机的8-16字节盐

  • 使用PBKDF2,BCrypt或SCrypt与所述盐和大的迭代计数/工作因子,因为处理器可以处理创建密码哈希


    • 如果您使用特定的PBKDF2,请不要求比本机散列大小更大的输出(SHA-1 = 20字节,SHA-256为32字节, SHA-384是48字节,SHA-512是64字节),或者你提高了攻击者对你的比较优势,后者。




然后在数据库中存储该用户的特定内容:




  • 盐在清楚的

  • 迭代计数/工作因子


    • 所以你可以很容易地/ />
    • 结果密码哈希

    • 验证协议版本 - 这将是2,大概或1.


      • 所以如果你从这个方法转到NewWellKnownMethod以后,你可以稍后更改/升级$ / $ b



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




    • 从数据库中检索他们的版本,盐,迭代次数/工作因子和生成的哈希值

    • 填入他们刚刚输入的任何关键字/密码数据库中的盐和迭代次数/工作系数。

    • 比较刚刚获得的结果与数据库中的内容;如果他们是一样的,让他们进来。


      • 高级:使用常量时间比较,所以它不只是退出尝试,如果第一个字节是




    请阅读如何安全地哈希密码?,其中Thomas Porrin的答案目前是最常用的Stackexchange密码散列论文,当然迄今为止我所见过的最好的。


    I'm developing an app that requires multiple passwords to access varying data areas. For example, a group of people could set up a chat that requires password authentication to view.

    Here's how I'm considering doing it:

    I have my keyword, let's say hypothetically:

    Banana

    When the user enters their password, I use RNCryptor to encrypt Banana using their entered key, and store that encrypted string to the server.

    Later, when someone tries to enter a password, I take the hashed value from the server and try to decrypt it using the password they entered as a key. If the decrypted value equals Banana I know they entered the correct password.

    I'm new to security, so I'm not sure if this would be an appropriate solution. All help is appreciated.

    Update

    After making some alterations suggested by @Greg and the aptly named @Anti-weakpasswords, here's what I have:

    - (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;
    }
    

    解决方案

    • Do not use a single pass of any hashing function to store passwords.
    • Do not fail to use a random salt in the 8-16 byte range.
    • Do not use reversible encryption to store passwords.
    • Do not use the password precisely as entered as your encryption key.

    Instead, when the user is selecting a keyword/passphrase

    • Generate a cryptographically random 8-16 byte salt
    • Use PBKDF2, BCrypt, or SCrypt with said salt and as large an iteration count/work factor as your processors can handle to create a password hash
      • If you use PBKDF2 in specific, do not request a larger output than the native hash size (SHA-1 = 20 bytes, SHA-256 is 32 bytes, SHA-384 is 48 bytes, and SHA-512 is 64 bytes), or you increase the comparative advantage an attacker has over you, the defender.

    Then in your database, you store that user's particular:

    • Salt in the clear
    • Iteration count/work factor
      • So you can easily change/upgrade it later
    • Resulting password hash
    • Version of authentication protocol - this would be 2, probably, or 1.
      • So you can easily change/upgrade it later if you move from this method to NewWellKnownMethod later

    When the user wants to authenticate to your system, you:

    • Retrieve their version, salt, iteration count/work factor, and resulting hash from the database
    • Hash whatever keyword/password they just entered with the salt and iteration count/work factor from the database.
    • Compare the result you just got with what was in the database; if they're the same, let them in.
      • Advanced: use a constant time compare, so it doesn't just quit trying if the first byte is different, to reduce the vulnerability to timing attacks.

    Please read How to securely hash passwords?, of which Thomas Porrin's answer is currently the most commonly referred to Stackexchange treatise on password hashing, and certainly the best I've seen so far.

    这篇关于密码验证 - 如何安全检查输入的密码是否正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆