C# SHA512 / Public Static String - c#

an annoying question today, i should know this but for the life of me i can't figure it out. I am trying to hash a password before querying the sql database. I have the hash code working fine however its inside a public static string:
public static string GetCrypt(string text)
{
string hash = "";
SHA512 alg = SHA512.Create();
byte[] result = alg.ComputeHash(Encoding.UTF8.GetBytes(text));
hash = Encoding.UTF8.GetString(result);
return hash;
}
I have two questions, one.. once it is hashed, how do i go about getting that result as when i try to access the variable "hash" it gives the error does not exist in current context. I suspect this is due to public and private classes?
Also, my other question, to have a more effective program, can i or is this already, a code where by i type it once, then can call it passing variables back and forth. sort of like, enter a password, it hashes, then passes it back.. then in another textbox pass new variable to the same hash code and get new hashed variable back?
Thanks in advance guys!

To use this method you would store the return value, like this:
string hashedString = GetCrypt(inputString);
Then use hashedString as appropriate.
However, you have some problems:
The result of alg.ComputeHash() is not a UTF-8 encoded string, so Encoding.UTF8.GetString() is very likely to throw an exception, and won't even do what you want. Consider using Convert.ToBase64String() (or convert the byte array to a hex string).
You don't salt the input string, at least not within this method. This means your database of passwords is vulnerable to rainbow table attacks. Consider using salted hashes or (better yet) an algorithm design specifically for hashing passwords, such as bcrypt, scrypt, or PBKDF2 which is built in to the framework itself.

Related

Get the plain text back from hash code in C#

I have some simple code but I need to get back my plain text from my hash code.
private string Hash(string ToHash)
{
// First we need to convert the string into bytes,
// which means using a text encoder.
Encoder enc = System.Text.Encoding.ASCII.GetEncoder();
// Create a buffer large enough to hold the string
byte[] data = new byte[ToHash.Length];
enc.GetBytes(ToHash.ToCharArray(), 0, ToHash.Length, data, 0, true);
// This is one implementation of the abstract class MD5.
MD5 md5 = new MD5CryptoServiceProvider();
byte[] result = md5.ComputeHash(data);
return BitConverter.ToString(result);
}
As far as I am aware, you can't un-hash something. It simply goes against the idea of hashing. Are you sure you are not thinking about 'encrypting'? As with a symmetric or asymmetric key?
Are you trying to compare a password someone entered to the stored hash of their password? If so, then instead of trying to unhash the stored password, you just need to hash the password they enter and then compare the two hashes to see if they match.
You should not be able to reverse a hash - it is by definition a one-way function. You might be able to guess what the plaintext of an md5 hash is by using a rainbow table or brute force guessing but it is expensive and not really what you're looking for.

BCrypt generating different hashes given the same salt, string, and factor

Using one of the C# implementations of BCrypt to hash passwords and store them into a SQL database. However when I return to validate against the hash string BCrypt generates a different hash than the one in the database to compare to. The salts are visibly the same as well as the factors.
Here is what I know
$2a$12$vF/1s3MqIzHwnDshyzH/rOYUelofrj4UWv./vzWqk4o2K0uwhix7W is actually "Qwerty123" and its stored in a column which is initialized to be [nvarchar] (200).
When I use the BCrypt.Verify() or BCrypt.CheckPassword() depending on the implementation, I trace it until just before it makes the comparison and the hash that it is about to compare to the before mentioned one is $2a$12$vF/1s3MqIzHwnDshyzH/rOKVRePZSXFXaIpDv6.IPkbPEoOxZgSEe
If you look close you can see that the salts and the factor parts are the same. Any idea what could be causing this?
The explicit implementation I am working with can be found here http://bcrypt.codeplex.com/
My question could be related to ASP.NET MVC 3 app, BCrypt.CheckPassword failing
Suggestion for testing
private void FindWhatsFailing(string password) //password = Whatever you're passing in to verify BCrypt is working
{
const string expectedpassword = "Qwerty123";
if(expectedpassword != password)
{
Debug.WriteLine("My password isn't what I thought it was");
return;
}
string hashed = BCrypt.HashPassword(expectedpassword , BCrypt.GenerateSalt(12));
if(!BCrypt.Verify(expectedpassword , hashed))
{
Debug.WriteLine("Something is wrong with BCrypt");
return;
}
/// ... Test hashing password, compare to hash of expectedpassword, verify password against hash of itself and expectedpassword
Debug.WriteLine("Everything worked, maybe the database storage is off?");
}
If the Bcrypt.Verify isn't working in this example for you, I have no idea what's wrong, but I'm guessing Bcrypt isn't actually the issue here.
The problem was the input to Bcrypt. I was using a Multiview and MultiViewPanels to collect user data(of which a password), allow user to verify all the data, then on the last MultiViewPanel add the user to the DB and in that process there were postbacks. After some research I found that password fields do not retain their text property after postbacks for security reasons and because I was passing txtPassword.text to Bcrypt this was the problem. This makes a new problem for me to look into.

Encode password to MD5 using keys

At the moment I do this:
public static class Crypto
{
public static string Encode(string original)
{
var md5 = new MD5CryptoServiceProvider();
var originalBytes = Encoding.Default.GetBytes(original);
var encodedBytes = md5.ComputeHash(originalBytes);
return BitConverter.ToString(encodedBytes);
}
}
I hear that I should use some key to encode stuff. Should I? Is it needed here? How to do this?
I ended up doing this http://encrypto.codeplex.com/ (sha1managed + random salt)
what you're talking about is called a "salt" this is a sequence of random data which you append to the original plain text string. This is commonly used for passwords, preventing rainbow table / dictionary attacks.
Read up on this on: http://en.wikipedia.org/wiki/Salt_%28cryptography%29
For C# there's a good article: http://www.aspheute.com/english/20040105.asp
You should use Base64 encoding for representation. I.e.:
StringBuilder hash = new StringBuilder();
for (int i = 0; i < encodedBytes.Length; i++)
{
hash.Append(encodedBytes[i].ToString("X2"));
}
This represents a string, rather than using a bit converter, which is the string representation of bytes directly (and cannot be reversed back to bits easily).
A couple of notes (please read this):
MD5 is a non-reversible hashing function (and not a great one at that)
If you are actually wanting to encrypt passwords using key-based encryption, such as AES, don't. Use the hashing method, but use a stronger one. Have a look at this answer here for more information on stengthening passwords.
Another note, in your implementation you can access the IDisposable interface, I.e.:
public static string Encode(string original)
{
byte[] encodedBytes;
using (var md5 = new MD5CryptoServiceProvider())
{
var originalBytes = Encoding.Default.GetBytes(original);
encodedBytes = md5.ComputeHash(originalBytes);
}
return Convert.ToBase64String(encodedBytes);
}
Since SHA is considered more safe than MD5 I would recommend using it.
byte[] data = new byte[SALT_SIZE+DATA_SIZE];
byte[] result;
SHA256 shaM = new SHA256Managed();
result = shaM.ComputeHash(salt+data);
MD5 isn't an encryption algorithm, but a hashing algorithm and as such doesn't require a key. It also means that you can't reverse (/de-hash) the process. Hashing only works one way and is usefull when you have to original (unhashed) data to compare the hash to.
edit: if you do want to really encrypt your data in a reversable way. Try to look into AES encryption for example.
I posted this link in a comment to sled's answer, but worth its own post.
http://codahale.com/how-to-safely-store-a-password/
It sounds like you've been given advice to salt your password hashes (I think you're calling the salt a "key"). This is better than just a hash, since it makes rainbow tables useless. A rainbow table takes a wide range of possible passwords (eg, a range of passwords, like a rainbow has a range of colours) and calculates their md5 hashes up-front. Then, to reverse an md5, simply look the md5 up in the table.
However, the advice is rapidly getting out of date. Hardware is now fast enough that rainbow tables are unnecessary: you can compute hashes really quickly, it's fast enough to just brute force the password from scratch every time, especially if you know the salt. So, the solution is to use a more computationally expensive hash, which will make a brute force much much slower.
The gold-standard tool to do this is bcrypt.
Here are a couple points that expand on the ones in #Kyle Rozendo's answer.
You should avoid using the default encoding Encoding.Default. Unless you have a good reason to do otherwise, always use UTF-8 en/de-coding. This is easy to do with the .NET System.Text namespace.
MD5 output is unconstrained binary data and cannot be reliably converted directly to a string. You must use a special encoding designed to convert from binary output to valid strings and back. #Kyle Rozendo shows one method; you can also use the method in the System.Convert class.
Class example:
using System.Security.Cryptography;
using System.Text;
private static string MD5(string Metin)
{
MD5CryptoServiceProvider MD5Code = new MD5CryptoServiceProvider();
byte[] byteDizisi = Encoding.UTF8.GetBytes(Metin);
byteDizisi = MD5Code.ComputeHash(byteDizisi);
StringBuilder sb = new StringBuilder();
foreach (byte ba in byteDizisi)
{
sb.Append(ba.ToString("x2").ToLower());
}
return sb.ToString();
}
MessageBox.Show(MD5("isa")); // 165a1761634db1e9bd304ea6f3ffcf2b

How to salt and hash a password value using c#?

Hai guys,
I came to know that storing hash value of a password is a safe one from Preferred Method of Storing Passwords In Database...
How to salt and hash a password value using c#?
How to compare both the values stored in DB and the one given by the user?
The most popular way to do this is using a hashing algorithm. There's an excellent blog post here about how to use the MD5 algorithm to hash a string, but there are many other examples in the System.Cryptography namespace.
As for #2, the general step-by-step guide to how this would work would be the following:
On registration:
Hash a user's password using your specified algorithm and store it in the database
Salt this hash (optional, but preferred)
On login / user & password check:
Look up in the database for the username
If it exists, retrieve the hashed password
Hash and salt the entered password and compare it to the retrieved password
It's all relatively long-winded, but it's very secure.
There's another extremely in-depth guide on hashing and salting here.
Simple hash:
public string GetSHA256Hash(string s)
{
if (string.IsNullOrEmpty(s))
{
throw new ArgumentException("An empty string value cannot be hashed.");
}
Byte[] data = System.Text.Encoding.UTF8.GetBytes(s);
Byte[] hash = new SHA256CryptoServiceProvider().ComputeHash(data);
return Convert.ToBase64String(hash);
}
Strictly speaking, you should salt the password then hash it, to avoid a dictionary attack. You can use any of the implementations of the HashAlgorithm abstract class in the System.Cryptography namespace to calculate the hash - current best choice would probably be one of the SHA-2 algorithms.
You store the hash not the password, and compare the hash values to authenticate the user.
Like the others have said, there are many options.
Here is some sample code (using MD5 instead of SHA) from Microsoft that might help get you get started
using System;
using System.Security.Cryptography;
using System.Text;
string sSourceData;
byte[] tmpSource;
byte[] tmpHash;
sSourceData = "MySourceData";
//Create a byte array from source data.
tmpSource = ASCIIEncoding.ASCII.GetBytes(sSourceData);
//Compute hash based on source data.
tmpHash = new MD5CryptoServiceProvider().ComputeHash(tmpSource);
For hashing you have several supported algorithms in System.Security.Cryptography, for your usecase you probably want to choose an SHA based hash or something similar.
Regarding the comparison: You don't compare the DB value and the one the user gave to you. You use the same encryption/hashing function that you used to store the password in the DB in the first place, this time with the user input. If the result is equal to the hash in the DB the password was (probably) correct.
The intention is that no one that has access to the DB can retrieve the passwords in clear text and not even your program needs to know about it (only the part that accepts the user input will have it for a short time).
Links (maybe even duplicates):
Secure Password Hashing
https://stackoverflow.com/questions/1841595/secure-password-hashing
System.Security.Cryptography.MD5

C# Reading back encrypted passwords

I'm using the code below to save a password to the registry, how do I convert it back? The code below isn't mine but it encrypts well.
Thanks
using System.Security.Cryptography;
public static string EncodePasswordToBase64(string password)
{ byte[] bytes = Encoding.Unicode.GetBytes(password);
byte[] dst = new byte[bytes.Length];
byte[] inArray = HashAlgorithm.Create("SHA1").ComputeHash(dst);
return Convert.ToBase64String(inArray);
}
SHA1 is a hash algorithm, not an encryption algorithm. A hash algorithm is a one-way function which transforms data into a hash of that data, but the original data cannot be gotten back from the hash. An encryption algorithm is a two-way function which transforms data into encrypted data, and the encrypted data can then be transformed back into the original data.
To securely store a password so that it can be read back, use the ProtectedData class.
public static string ProtectPassword(string password)
{
byte[] bytes = Encoding.Unicode.GetBytes(password);
byte[] protectedPassword = ProtectedData.Protect(bytes, null, DataProtectionScope.CurrentUser);
return Convert.ToBase64String(protectedPassword);
}
public static string UnprotectPassword(string protectedPassword)
{
byte[] bytes = Convert.FromBase64String(protectedPassword);
byte[] password = ProtectedData.Unprotect(bytes, null, DataProtectionScope.CurrentUser);
return Encoding.Unicode.GetString(password);
}
Take whatever the user enters as a password to gain access to the system, encrypt it the same way and then compare the encrypted values, that's the normal approach. I'm pretty sure that SHA1 is a trapdoor encryption, i.e. can't be back-tracked.
You don't.
SHA1 is a hash, not encryption. It is a one-way operation; conversion back is not possible.
(Ok this is not strictly true; if you have a table of possible SHA1 values and plain text values, a rainbow table then you might be luck)
Also you should be salting your hashes, because you are, right now, vulnerable to rainbow table attacks. Jeff talks about this a little more on his blog
Okay, so I know this isn't answering your specific Q, but why do you want to convert it back?
If it's to compare in order to provide authentication, the standard approach is to encrypt this text ALSO, and compare the stored password to the supplied password.
This is more secure as it means that the original password never needs to be decrypted.
I think one of the points of using hashes is that they can't be computed back.
As someone else said, calculate the hash from the user's password and compare to the stored hash value.
In order to use the System.Security.Cryptography.ProtectedData class, you must add a reference to System.Security to your project.
(Right mouse click on the References folder, choose "Add Reference...", find System.Security on the .NET Tab)
Um, just curious but wouldn't that return the same hash for all passwords of the same length?
Using your own code snippet above, what you want to do is call that method when the user initially chooses a password - but add to the password what is called a salt somewhere in the password string (usually at the beginning or end). Then, when the user is attempting to authenticate later, they enter their password, you run that one along with the hash through this same method and if the two hashes are equal, it's a statistically excellent chance the passwords are equal and valid.
This being said, SHA1 is known to have weaknesses and you should choose a stronger algorithm. If you want to stay in the SHA family, SHA512 is pretty good.
You want to use encryption not hashing. SHA is fine but use the encryption methods for it. The problem with encryption is always where to put the key for it. You didn't mention whether this was a workstation or server you were doing this on. On a server, I find it better to just use ACL's to restrict access to the reg key. Admins can usually access the encryption key anyway...you have to have some trust somewhere. On a workstation then you can go with encryption and store the key in code or use a certificate and restrict access to it at least in a corp environment...not for sale software).
You can use the ProtectedData class but be aware that it uses user profiles for its key usage and as such you have to make sure you are impersonating the user who has the profile with the key you need. This may or may not be trivial and may or may not cause headaches and security issues.
I noticed the recent addition of the XMLEncryptedData class. For encrypting data to an XML file, is the XMLEncryptedData method more desirable than the DPAPI method?

Categories