How to properly store password locally

前端 未结 3 1452
萌比男神i
萌比男神i 2021-02-19 17:42

I\'ve been reading this article from MSDN on Rfc2898DeriveBytes. Here is the sample encryption code they provide.

string pwd1 = passwordargs[0];
// Create a byte         


        
相关标签:
3条回答
  • 2021-02-19 18:07

    You should store the password as a one-way hash and the salt used to create that password. This way you are absolutely sure that the password for the user can never be DECRYPTED. Never use any two-way encryption for this particular task, as you risk exposing user information to would-be attackers.

    void Main()
    {
        string phrase, salt, result;
        phrase = "test";
        result = Sha256Hash(phrase, out salt);
    
        Sha256Compare(phrase, result, salt);
    }
    
    public string Sha256Hash(string phrase, out string salt)
    {
        salt = Create256BitSalt();
        string saltAndPwd = String.Concat(phrase, salt);
        Encoding encoder = Encoding.Default;
        SHA256Managed sha256hasher = new SHA256Managed();
        byte[] hashedDataBytes = sha256hasher.ComputeHash(encoder.GetBytes(saltAndPwd));
        string hashedPwd = Encoding.Default.GetString(hashedDataBytes);
        return hashedPwd;
    }
    
    public bool Sha256Compare(string phrase, string hash, string salt)
    {
        string saltAndPwd = String.Concat(phrase, salt);
        Encoding encoder = Encoding.Default;
        SHA256Managed sha256hasher = new SHA256Managed();
        byte[] hashedDataBytes = sha256hasher.ComputeHash(encoder.GetBytes(saltAndPwd));
        string hashedPwd = Encoding.Default.GetString(hashedDataBytes);
        return string.Compare(hash, hashedPwd, false) == 0;
    }
    
    public string Create256BitSalt()
    {
        int _saltSize = 32;
        byte[] ba = new byte[_saltSize];
        RNGCryptoServiceProvider.Create().GetBytes(ba);
        return Encoding.Default.GetString(ba);
    }
    

    You could also figure out another method for obtaining the salt, but I have made mine to that it computes 2048 bits worth of random data. You could just use a random long you generate but that would be a lot less secure. You won't be able to use SecureString because SecureString isn't Serializable. Which the whole point of DPAPI. There are ways to get the data out but you end up having to jump a few hurdles to do it.

    FWIW, PBKDF2 (Password-Based Key Derivation Function 2) is basically the same thing as SHA256 except slower (a good thing). On its own both are very secure. If you combined PBKDF2 with an SHA256 as your salt then you'd have a very secure system.

    0 讨论(0)
  • 2021-02-19 18:13

    You typically store the hash of the password, then when user enters password, you compute hash over the entered password and compare it with the hash which was stored - that said, just hashing is usually not enough (from security point of view) and you should use a function such as PKBDF2 (Password-Based Key Derivation Function 2) instead. Here is article covering all that information in more elaborate way as well as sample code (bottom of the page): http://www.codeproject.com/Articles/704865/Salted-Password-Hashing-Doing-it-Right

    Here is a link to codereview, which I guess refers to the same implementation as above article.

    0 讨论(0)
  • 2021-02-19 18:18

    How to properly store password locally

    Just don't do it. No really don't do it.

    ...But if you really really have to, never just implement it yourself. I would recommend reviewing how ASP.NET Identity hashes passwords. Version 3 is pretty rock solid at the moment:

    note that the following is taken from github.com and may be changed at any time. For the latest, please refer to the previous link.

    private static byte[] HashPasswordV3(string password, RandomNumberGenerator rng, KeyDerivationPrf prf, int iterCount, int saltSize, int numBytesRequested)
        {
            // Produce a version 3 (see comment above) text hash.
            byte[] salt = new byte[saltSize];
            rng.GetBytes(salt);
            byte[] subkey = KeyDerivation.Pbkdf2(password, salt, prf, iterCount, numBytesRequested);
    
            var outputBytes = new byte[13 + salt.Length + subkey.Length];
            outputBytes[0] = 0x01; // format marker
            WriteNetworkByteOrder(outputBytes, 1, (uint)prf);
            WriteNetworkByteOrder(outputBytes, 5, (uint)iterCount);
            WriteNetworkByteOrder(outputBytes, 9, (uint)saltSize);
            Buffer.BlockCopy(salt, 0, outputBytes, 13, salt.Length);
            Buffer.BlockCopy(subkey, 0, outputBytes, 13 + saltSize, subkey.Length);
            return outputBytes;
        }
    
    0 讨论(0)
提交回复
热议问题