PHP and C# MD5 crypt does not give the same output? - c#

This is the encryption I have when people register on my site:
$salt = generateSalt();
$hashedPassword = crypt($userPass, $salt);
and here is my generateSalt function:
function generateSalt() {
$salt = uniqid(mt_rand(), true);
$salt = '$1$' . $salt;
return $salt;
}
When I encrypt a password with this I get for example:
$1$92999442$AK4yZPjnj6BKc9yj4CXKu1
But when I crypt the same password on C# with this function:
hashedPassword = GenerateMD5(uName, salt);
GenerateMD5 function:
public String GenerateMD5(String input, String salt)
{
Byte[] bytes = System.Text.Encoding.UTF8.GetBytes(input + salt);
System.Security.Cryptography.MD5Cng md5hashstring = new System.Security.Cryptography.MD5Cng();
byte[] hash = md5hashstring.ComputeHash(bytes);
string hex = BitConverter.ToString(hash).Replace("-", string.Empty);
return hex;
}
I get a complete different output. With the same password and the same salt I get this output:
9DE11D48C3F7DF1BF89FC76D755A2596
What function should I use in PHP and C# to get the same output?

Because you're using two completely different algorithms. In PHP you're using crypt() which uses DES, and in C# you're using MD5. They're never going to produce the same output. If you want the same output, you should use md5() in PHP instead of crypt()
Also, don't use MD5, it's deprecated. You should be using at least SHA-2 now

http://php.net/md5
http://blogs.msdn.com/b/csharpfaq/archive/2006/10/09/how-do-i-calculate-a-md5-hash-from-a-string_3f00_.aspx
and adding a random salt to your input is part of them problem. you'll end up with a different input every time, hence a different hash output.

If I were you I'd consider using password_hash instead. Does all that crypt work for you in a nice, neat package, complete with random salt.
As to why your function doesn't match, you're using MD5 in your C# code. I'm no expert in C# but you should use some sort of bcrypt hashing system. There is an open source bcrypt for C# that might do the trick for you. In theory, since they use the same system, one should be able to validate the other since they all store the salt in the string. Just pluck the salt from the string and plug the password and salt into the other one and they should match.

This is so called md5crypt by Poul-Henning Kamp, not to be confused with MD5. Md5crypt for first used to protect FreeBSD passwords from bruteforce, but then became more widespread. It was incorporated into GNU libc crypt() and many programs had interfaces to this system call, including PHP, and some PHP developers made use of it. Md5crypt invokes MD5 no less than 1000 times to make brute-force harder (but nowadays md5crypt is considered outdated by its author!). I have seen implementation of md5crypt for many programming languages, this one is for C#.

Related

any way to Decrypt MD5CryptoServiceProvider

hey guys i wanted to know to create a decrypt function for this crypt function :
public static string CreateHash(string unHashed)
{
System.Security.Cryptography.MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] data = System.Text.Encoding.ASCII.GetBytes(unHashed);
data = x.ComputeHash(data);
return System.Text.Encoding.ASCII.GetString(data);
}
there is any way to decrypt function ?
hashes i got is like : ??????7hYkr?4??w
MD5 is a hash function.
So it's only one way: there is no practical way to decrypt it.
Read the introduction of the wikipedia article about cryptographic hash functions to understand how those behave.
However, if you have passwords encrypted with this function, and you want to check that a user provided password matches, you can encrypt the user provided string, and compare the result with the encrypted blob that is in your database (which is the most common use for those function).

C# emulating php crypt

I need to hash passwords with C# in a way that another software understands it .
Originally php's crypt function is doing that. It has the following output
$6$rounds=1000$1f$yeKGQo0b8MqqMpocFla8uKLE6GOpEygSQUH4qMi4msJZsD50Eh00bU4GwoGGPEeLMdG6C17ehl/l8SrcOABdC0
I guess it is SHA512. . How can I achieve php's crypt functionality with C#
original php
$salt = '$6$rounds=1000$'.dechex(rand(0,15)).dechex(rand(0,15)).'$';
$crypted = crypt($password, $salt);
CryptSharp computes this for all common crypt variations.
Generating a SHA-512 salted hash (the default number of rounds for this algorithm is 5000):
using CryptSharp;
string hash = Crypter.SHA512.Crypt(password);
Using a custom number of rounds:
var saltOptions = new CrypterOptions() { { CrypterOption.Rounds, 10000 } };
string salt = Crypter.SHA512.GenerateSalt(saltOptions);
string hash = Crypter.SHA512.Crypt(password, saltOptions);
Verifying a hash:
bool matched = Crypter.CheckPassword(testPassword, hash);
On another note, that original PHP should really be secured. The salt is only 8 bit and generated with rand (use openssl_random_pseudo_bytes instead). The hash specifically chooses a fifth of the default number of rounds.

how to decrypt SHA512 hash value to an actual string in c# [duplicate]

This question already has an answer here:
Vb.net Decrypt sha512 hash
(1 answer)
Closed 8 years ago.
I encrypt the password by following code
HashAlgorithm hashAlgorithm = null;
hashAlgorithm = new SHA512CryptoServiceProvider();
try
{
byte[] byteValue = Encoding.UTF8.GetBytes(source);
byte[] hashValue = hashAlgorithm.ComputeHash(byteValue);
StringBuilder sb = new StringBuilder();
for (int i = 0; i <= hashValue.Length - 1; i++)
{
sb.AppendFormat("{0:x2}", hashValue[i]);
}
return Convert.ToString(sb);
}
catch
{
throw;
}
after that I saved it in database.
now I want to retrieve actual password by decrypting it. please help me
You hash a password and you don't encrypt it. That being said you cannot decrypt it.
Taken from here
Encryption transforms data into another format in such a way that only
specific individual(s) can reverse the transformation. It uses a key,
which is kept secret, in conjunction with the plaintext and the
algorithm, in order to perform the encryption operation. As such, the
ciphertext, algorithm, and key are all required to return to the
plaintext.
while
Hashing serves the purpose of ensuring integrity, i.e. making it so
that if something is changed you can know that it’s changed.
Technically, hashing takes arbitrary input and produce a fixed-length
string that has the following attributes:
The same input will always produce the same output.
Multiple disparate inputs should not produce the same output.
It should not be possible to go from the output to the input.
Any modification of a given input should result in drastic change to the hash.
Hashing is used in
conjunction with authentication to produce strong evidence that a
given message has not been modified. This is accomplished by taking a
given input, encrypting it with a given key, hashing it, and then
encrypting the key with with the recipient’s public key and signing
the hash with the sender’s private key.
then what can I use with which I can convert output to input?
You should decrypt your data and not hash them. Encrypting and Decrypting data is a big subject. A good starting point is to read this. Generally, you have two types of encryoption, symmetric and assymmetric. So initially, read about them and then choose the one you think is suits your needs. Then try to implement it. You will make use of algorithms that are already implemented in .NET and can be used instantiating objects of the corresponding classes and calling specific methods.
However, I have to make a note here. Usually, we hash the passwords and we don't encrypt them. This is more secure. Taken from here:
Though hashing and encryption both provide valuable capabilities, for
the vast majority of situations, there is only one right option for
storing user passwords for an online application: hashing. This is a
one-way function in which a hashed value cannot be reversed to obtain
the original input value (i.e., the password). Symmetric encryption is
based on the use of an encryption key and is a reversible operation.
Anyone possessing the key can decrypt an encrypted value to obtain the
original value.

C# SHA512 / Public Static String

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.

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

Categories