Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly store password locally

Tags:

c#

encryption

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 array to hold the random value. 
byte[] salt1 = new byte[8];
using (RNGCryptoServiceProvider rngCsp = ne RNGCryptoServiceProvider())
{
    // Fill the array with a random value.
    rngCsp.GetBytes(salt1);
}

//data1 can be a string or contents of a file.
string data1 = "Some test data";
//The default iteration count is 1000 so the two methods use the same iteration count.
int myIterations = 1000;
try
{
    Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(pwd1,salt1,myIterations);
    Rfc2898DeriveBytes k2 = new Rfc2898DeriveBytes(pwd1, salt1);
    // Encrypt the data.
    TripleDES encAlg = TripleDES.Create();
    encAlg.Key = k1.GetBytes(16);
    MemoryStream encryptionStream = new MemoryStream();
    CryptoStream encrypt = newCryptoStream(encryptionStream, encAlg.CreateEncryptor(), CryptoStreamMode.Write);
    byte[] utfD1 = new System.Text.UTF8Encoding(false).GetBytes(data1);

    encrypt.Write(utfD1, 0, utfD1.Length);
    encrypt.FlushFinalBlock();
    encrypt.Close();
    byte[] edata1 = encryptionStream.ToArray();
    k1.Reset();

My question is, how would I properly Read/Write the hashed data to/from a text file?

My main goal is to do what this developer is doing. I need to store a password locally. When my application prompts the user for the password, the user will enter the password, then my application will read from the text file and verify if the password that the user entered is indeed correct. How would I go about doing it?

like image 709
Emma Geller-Green Avatar asked Oct 26 '15 21:10

Emma Geller-Green


People also ask

Is it safe to store passwords locally?

You can make it safer, but never really safe. Your app has to read it, so someone can find those methods if they know what they're doing. You can make it a little safer by using the user machine's serial number as the key (or part of the key).

Where is the safest place to put passwords?

"Keep your most sensitive passwords in your head. Do not write them down," Joseph Steinberg, cyber security and emerging technologies advisor, tells Yahoo Life. Mikko Laaksonen, chief executive officer of Responsible Cyber, agrees. "The best place to keep a password is in your head," he tells Yahoo Life.

Should you store your passwords on your computer?

While it may be tempting to click “Remember Password” when your web browser prompts you, doing so puts your security at RISK. If you walk away from your unlocked computer, (even briefly) at work or in public, there is a very real risk that someone could steal your passwords in just a few simple clicks.


2 Answers

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.

like image 73
Mr. Young Avatar answered Oct 03 '22 15:10

Mr. Young


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.

like image 25
Giorgi Moniava Avatar answered Oct 03 '22 16:10

Giorgi Moniava