I'm creating a C# application that will lock out functionality (key combinations, windows task bar, etc.) in a Kiosk-style environment. One of the requirements is that some people should still be able to break out of the application using a key combination and a password.
The application itself is completely done, but I have not found a good way to store and check against a password. Everything should be stored locally (there is not check against a network database or whatever). How can I define a password for unlocking my application while also making this flexible (the ability to change the password without recompiling the application). How can I accomplish this in a secure way?
Store a secure hash of the password, it doesn't need to be reversible.
When someone enters a password you hash that by the same algorithm and check it matches the hash.
Because you never store the actual password it's secure.
I recommend using a key stretching algorithm like PBKDF2. .NET has support for this using Rfc2898DeriveBytes or you can use System.Web.Helpers.Crypto.
In addition the password you use should be long (at least 12 chars, but longer the better) and salted with an extra string that stops attackers using a rainbow table attack.
The standard method for storing a password in a configuration file is to use a strong hash algorithm. Read the answer at How to store passwords in Winforms application? and maybe the wiki article at https://en.wikipedia.org/wiki/Cryptographic_hash_function
I have to disagree with Brian, because as of now the standard method for storing passwords in any database is to "salt" (see Wikipedia for a detailed explanation) the password with a randomly generated value and store the hashed value and the salt in your "database" (see remarks). The salt is not a secret so you can store it in plain text. Whenever the user enters the password you read the salt from your file, apply it to the entered password and then apply your chosen hash algorithm. Then you compare the results with your stored hash. If they match, the user is authenticated. For a good (and entertaining :)) explanation why "just" hashing the password isn't enough, see: How NOT to store passwords!
For a tutorial implementation of the salting and hashing process in C# see: C# Salting & Hashing Passwords
You can also find a good way to do this here: https://stackoverflow.com/a/12657970
For a quick reference, the process in pseudocode:
First password storage:
//get user input
username = GetUserName
password = GetPassword
//generate random salt
salt = GetRandomValue
//combine password and salt and apply hash
hashedPassword = Hash(password + salt)
//store hash value and salt in database
AddToDatabase(username, hashedPassword, salt)
User login:
//get user input
username = GetUserName
password = GetPassword
//read salt from database
salt = GetSaltFromDatabase(username)
//combine password and salt and apply hash
hashedPassword = Hash(password + salt)
//compare hash to stored hash value
correctHash = GetHashFromDatabase(username)
if (hashedPassword == correctHash) then
passwordIsCorrect = True
else
passwordIsCorrect = False
end if
Remarks:
This assumes that your usernames are unique as they are used as identifying key in your "database".
The "database" doesn't have to be any kind of "real" database, it can also be your configuration file or a plain text file.
You can store a hash of your key and a password somewhere, for example in some local file. When person input key and password, you get hashes for this values and compare it with hashes in your file.
You need a hash of the password and validate using the hashed text. Adding a salt can make your password more secure. In .Net, you can use System.Security.Cryptography.RNGCryptoServiceProvider .
Here is a good article talking about how to store your passwords and I use its way in my web application.
Is relatively easy using ProtectSection() and UnprotectSection() methods from SectionInformation class. See this article:
http://www.davidgiard.com/2012/06/05/EncryptingAndDecryptingApplicationConfigSections.aspx
http://msdn.microsoft.com/en-us/library/system.configuration.sectioninformation.protectsection.aspx
Related
is possible decrypt this type of password generated by Meteor application.
My idea is to use the same credentials (email and password) for my application in C #
As noted in other answers, you cannot decrypt the passwords, but you can very well use the Meteor database to authenticate in a different system.
This is how to do it:
In your other system, first find libraries that provide SHA256 and bcrypt implementations.
Then take the password as entered by the user, and first compute a SHA256 digest hash from it.
Then feed this hash string to bcrypt using number of rounds = 10 (This is the Meteor default).
Now compare the result from bcrypt with the services.password.bcrypt from the MongoDB database of Meteor. If they match, the user provided the correct password.
For reference, the Meteor implementation is here. It is quite simple and well commented.
The very purpose of hashing and encrypting your password is to make decrypting them unpractical.
However, you can reuse the bcrypt(hash(password)) from your meteor app and check against it in another application, provided you use the same scheme.
Is that a bcrypt hash? It depends on the size of the key as Blowfish as a variable sized key. If it's 32 bits. Sure, you could do it with some serious computing power and a few hours. It it is a 128bit key, you'd be long long dead (and so would the universe as we know it) before it every finishes brute forcing. Blowfish does have a minor vulnerability for weak keys though. I would rethink your implementation.
I encountered a similar use case where I was writing a C# application that would validate users created through a Meteor.js application. The code I got to work was this (using System.Security.Cryptography and BCrypt.Net-Next):
string sha256_hash(string value) {
StringBuilder stringBuilder = new StringBuilder();
using (SHA256 hash = SHA256.Create()) {
Encoding enc = Encoding.UTF8;
Byte[] resultingHash = hash.ComputeHash(enc.GetBytes(value));
foreach (Byte b in resultingHash) {
stringBuilder.Append(b.ToString("x2"));
}
}
return stringBuilder.ToString();
}
// First compute SHA256 hash
string sha256hash = sha256_hash("my_password");
// Let BCrypt.Net rehash and check if it matches Meteor's hash
if (BCrypt.Net.BCrypt.Verify(sha256hash, dbPassword) == true) {
Console.WriteLine("Valid!");
}
This question already has answers here:
Hashing a SecureString in .NET
(4 answers)
Closed 7 years ago.
I believe I'm misunderstanding a fundamental part of SecureString. I understand that string's are immutable and there a password or sensitive data is found as clear text on the heap.
What I'm struggling to understand is, how do I use SecureString in a client application which needs to verify the hashed password in a database?
Here's my context:
I'm using a WPF client application.
I have a local SQL database (on the client's machine)
The passwords are hashed and stored in the database.
The user tries logging into to my WPF application
The PasswordBox control stores the password in a SecureString via the SecurePassword property.
Now what? How do I hash a SecureString WITHOUT casting it back into string first?
All the advise I've received so far is to write extension methods converting SecureString to String, hash it and then send it to db to verify. But this defeats the whole exercise!
Must I just accept that SecureString is useless in my mentioned context and use plain string?
SecureString is represented as a byte[] you could encode the bytes e.g. with bitconverter and save the result.
Furthermore SecureString is a encryption not a hash as it can be decrypted. (see below)
SecureString mainly meant to store sensitive data in memory.
If you have a service / website, this is not as important as the values which are stored in the database. These should never be plaintext, and imo not be decryptable by your or any administrator
Also i'm not sure wether another server could decrypt the strings, so you may have a problem when you change the server or have somekind of cluster scenario.
Especially for passwords would prefer using hash algorithms (e.g. SHA256) .
These can't be uncrypted (like the sum of the digits).
In the use case of a login funtionality you would encrypt the userinput and compare the hashs the user and and the one thats in the database. (details se below)
I would also suggest to add a dynamic criteria like the userid to the hashinput so that 2 user with same password would have different hashes.
With this strategy you don't have a risc with userpasswords and therefore if data gets leaked it wouldn't be a problem at this point.
Here an short overview of using hash algorithms
So ( if the securestring is given) first decrypt the SecureString
String SecureStringToString(SecureString value){
IntPtr valuePtr = IntPtr.Zero;
try{
valuePtr = Marshal.SecureStringToGlobalAllocUnicode(value);
return Marshal.PtrToStringUni(valuePtr);
}
finally{
Marshal.ZeroFreeGlobalAllocUnicode(valuePtr);
}
}
Than hash it for example with SHA256. From this post
using (SHA256 hash = SHA256Managed.Create()) {
Encoding enc = Encoding.UTF8;
//the user id is the salt.
//So 2 users with same password have different hashes.
//For example if someone knows his own hash he can't see who has same password
string input = userInput+userId;
Byte[] result = hash.ComputeHash(enc.GetBytes(input));
foreach (Byte b in result)
Sb.Append(b.ToString("x2")); //You could also use other encodingslike BASE64
}
Store this hashsum. Depending on your encoding it may looke like this:
ac5b208b4d35ec79fa7c14b7a31f9c80392cdab2bc58bc5b79bcfe64b044d899
in your database.
If the user signs on then create the hash from his input and compare it with the hash in the database. if they are equal then the password is correct.
Therefore you never need to have the plaintext user password anywhere stored.
If the client makes the hash then it should absolut should no where exist as a plaintext (except the textbox if it doesnt support the securestring)
PS: this is only one option. But the main thing is to never store plaintextpasswords anywhere. For best never know them and have no change to get them decrypted.
Another strategy would be to use asymmetric encryptions like RSA but this can become more complex. If you need help with that i would recommend a dedicated post on this.
Depending on your requirements and envionment most of the time hashsums should be an acceptable solution. (But thats not an legal advice as i'm not a lawyer)
At the time of registering
string crypt = CryptSharp.Crypter.Sha512.GenerateSalt();
crypt = txtspss.Text.Trim();
crypt = CryptSharp.Crypter.Sha512.Crypt(txtspss.Text, crypt);
At the time of login..
string cpass=dr["strUPass"].ToString();
bool matches = Crypter.CheckPassword(pass,cpass);
if (matches)
{....}
A salt is supposed to be unique. By doing this, someone trying to crack passwords has to do a separate compuation for each password, instead of being able to generate hashes for a million passwords and then check them against the entire stolen password database.
CryptSharp encodes passwords in Modular Crypt Format. Here's the design. Suppose the algorithm is A, the salt is B, and the hash is C. GenerateSalt writes AB, Crypt reads AB and generates C, returning ABC. Underneath, you see, CheckPassword is more or less equivalent to:
Crypter.Crypt(password, crypt) == crypt
Because Crypt reads only AB, if you pass it ABC, it's the same as passing it AB. This is how Crypt does double-duty both generating and checking password hashes.
At registration, GenerateSalt and Crypt, and at log-in, CheckPassword. Many people will tell you this or that about storing salts separately, etc. and this is good general advice, but Modular Crypt Format is designed so everything needed is stored in the same string. It's all taken care of for you.
Oh... Also, in your code, you have a bug. Your line in the middle isn't doing you any good. The following will work correctly:
string crypt = CryptSharp.Crypter.Sha512.GenerateSalt();
crypt = CryptSharp.Crypter.Sha512.Crypt(txtspss.Text.Trim(), crypt);
There is not enough code to say what exactly is wrong, but you should start by using the result of
CryptSharp.Crypter.Sha512.GenerateSalt()
because right now, you just dump it by overwriting the variable in the following line.
SHA512 is a Hashing algorithm, and to make it more secure against attacks like rainbow tables library methods optionally take a salt value.
The same salt value should be present when hashing and when comparing the hash of a new value, and in your code you don't seem to be doing that.
When registering a user; the Salt should be stored in the database and retrieved when logging in so it can be supplied to the CheckPassword function.
byte[] pass = Encoding.Unicode.GetBytes(textBox1.Text);
MD5 md5 = new MD5CryptoServiceProvider();
String password = Encoding.UTF8.GetString(md5.ComputeHash(pass));
Do not modify the code, the code only increases
Decryption variable:password
Tried a lot of methods can not decrypt utf8 string to md5
password value is garbled, how to restore the password: md5?
textBox.text = wooyun
md5.ComputeHash(pass) = F04BC0C32584F9D42817DC6EF8769E9E
Encoding.UTF8.GetString(md5.ComputeHash(pass))=�K��%���(�n�v��
Please consult the services of a security expert instead of attempting to do whatever it is you are trying to do by yourself. In just these 3 example lines of code and without being an expert on security myself, I can already tell that:
you are conflating the ideas of encoding, encryption, and hashing
you are attempting to reverse-lookup a password from a stored hash, presumably from some existing database. In addition to most likely being malicious ethically, this could be illegal in some jurisdictions
the hashed password are likely not salted, therefore the stored passwords are susceptible to brute-force attacks
the hashes were generated with MD5, known to be a weak algorithm for password hashing
Is this exercise for learning purposes? Can you clarify the question?
I'm building a project from the ground up and I want to do things the Right Way™. I've read online about hashes and that's basically turning a password in 64 letters of mumbo jumbo, correct?
What about salting?
My questions are:
How do I hash a string using C#?
What would the field declaration type be in MSSQL? nvarchar(64)?
What is salting and do I need to save that somewhere in my database?
If I intend to let people use Facebook Connect, do I need to worry about creating a hash/salt?
Code examples are preferred. Thanks!
I will skip question 1 as I'm not a C# person.
Question 3:
Salting is adding a string of random data to the password before hashing. Salts are essential because without them it is possible for an attacker to pre-generate a rainbow table of known password hashes. Salting means that rainbow tables cannot be pre-built, and it means each password must be brute-forced separately.
It is important to generate a new salt for each password.
Salt values are not secret and can be stored alongside the hashed password in your database.
Pseudocode for generating and checking a password are as follows:
generatePassword(String user, String password) {
String salt = generateRandomSalt();
String salted = salt + password;
String hash = hexEncode(hash(salted));
store(user, hash, salt);
}
checkPassword(String user, String testPassword) {
String salt = lookupSalt(user);
String salted = salt + testPassword;
String testHash = hexEncode(hash(salted));
return testHash.equals(lookupHash(user));
}
Question 2:
The length of the database field depends on the hash algorithm. SHA1 generates 160-bit output, so that will be 40 characters if hex-encoded. A good rule of thumb is to use a salt that is the same size as the hash output, so you'll have two 40-character columns: one for salt, and one for the hash.
Question 4:
No idea how Facebook Connect works, sorry. I hope the other two answers are helpful.
1) Code
public static string HashStringSha1(string plainText, string salt)
{
using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider())
{
byte[] bb = sha1.ComputeHash(Encoding.UTF8.GetBytes(salt + plainText + plainText));
return Convert.ToBase64String(bb);
}
}
2) Store base64 string in SQLserver varchar
3) Store the salt in a different field with the hash. Salt as plain text.
4) Not sure what you mean. If you use OpenId, you do not need to store passwords.
Hash & salt are used to keep your users password safe. MD5 hash is the most popular algorithm used. Hash functions are irreversible -> you cannot get the password from the hash, but somebody somewhere thought - hey! let's generate a a table that contains example passwords and their hashes then sort that and do simple lookup to check the password. This is why salt was introduced - salt is added to the user password and then hashed. Salt is randomly generated thus should be kept in the db for each hash.
For the details of implementation I suggest you look at live examples like nopCommerce which is open source e-commerce solution. http://www.nopcommerce.com
(this one is very useful because it has a custom membership provider implemented which utilizes the ideas of salt & hash)
How do I hash a string using C#?
Take a look here:
http://support.microsoft.com/kb/307020
What would the field declaration type be in MSSQL? nvarchar(64)?
It is binary data. You might want to format it as string, but thats "extra work"
What is salting and do I need to save that somewhere in my database?
You should use a unique salt per entry. The salt is there to make it impossible to know if 2 times the same password was used. usually a slat is constructed from 2 components... A "shared secret" (Needs to be resonably complex, so it can defeat lookup lists) and a unique part (for example a ID value of the user in the DB or something else.... Just make sure that "shared" + "Unique" + Password is unique
If I intend to let people use Facebook Connect, do I need to worry about creating a hash/salt?
If you can use a 3rd party API, then you dont have to care about hashing salting. As long as you dont save the passwords, there is no need to hash. Hashing is a one way function, so there is no "good" way (Hint: Rainbow tables) to reconstruct the original password. If you let facebook handle the authentication, you wont have to worry about all that base plumbing, since you dont store the passwords.
Hashing is used if you want some information so secure, that even someone that steals your DB cannot access it. BTW: That includes yourself... There is no way to recreate the original password...