Why C# sha512 hash value is different with PHP crypt method? - c#

I am using the same salt and password, but the hash value is different in C# and PHP. Why is that?
string password = "password";
string salt = "salt";
C# :
HMACSHA512 hmac = new HMACSHA512(Encoding.UTF8.GetBytes(salt));
byte[] bithash = Encoding.UTF8.GetBytes(password);
for (int i = 0; i < 7778;i++){
bithash = hmac.ComputeHash(bithash);
}
Console.WriteLine( Convert.ToBase64String(bithash) );
uQobtR+v8PovsSOjCZ9tZyOsfUYWw+xZSOMEuljCzXdezVs8LiM85I1JRQsVpKGSalrC5xTu5sU2f127Bw3DoA==
PHP:
crypt('password','$6$rounds=7778$salt$');
QVysRURDsOGt7/ig9jE7JNutVD2XWO5h9gmBmvC5HtEUFUtVNugF3GWJe6CwFkVNq91kJY8yL5QVPQYXUzhoM1

finanly I found a method with library: https://www.zer7.com/software.php?page=cryptsharp
string password = "password";
string salt = "$6$rounds=7777$salt";
CryptSharp.Sha512Crypter sha512Crypter = new Sha512Crypter();
var hash = sha512Crypter.Crypt(password, salt);
Console.WriteLine(hash);
Console.ReadLine();

Related

C# & NodeJS PBKDF Encryption

im making a website and a desktop application, they both will use the same database but i need them to generate the same hashes, how can i do this with NodeJS and C#?
const crypto = require('crypto');
const key = crypto.pbkdf2Sync('pass', 'saltsaltsaltsalt', 100000, 64, 'sha256').toString('base64');
console.log(key);
Output: lLRnCThEdyMUjj6QazuIBvI/hRv7bT4r9Z5FKJ39NOOmFvI+5V5YhqTxInWCi3D8rOB1eMGV/Yn71m597/bzWw==
using System;
using System.Security.Cryptography;
public class Program
{
private const int HashIterations = 100000;
public static void Main()
{
var password = "pass";
var salt = "saltsaltsaltsalt";
var xx = GeneratePasswordHash(password, salt);
Console.WriteLine(xx);
}
public static string GeneratePasswordHash(string password, string salt, int hashIterations = HashIterations)
{
byte[] hash;
using (var crypto = new Rfc2898DeriveBytes(password, Convert.FromBase64String(salt), hashIterations))
{
hash = crypto.GetBytes(64);
}
return Convert.ToBase64String(hash);
}
}
Output: 0Nj5NJWM8dtAFFUU8T3UUQhmdNIbKTLndqjqXzkulEXRVsjlIb28C00daPi96pDk+evKY3CLbkLOGVZUuNiimQ==
what im expecting and need is both these programs to output the same hash.
According to this answer there is a nuget package that enables the use of PBKDF2 in c#.
According to the documentation you can use it like this:
using System.Security.Cryptography;
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
var password = "pass";
var salt = "saltsaltsaltsalt";
string hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2(
password: password,
salt: Convert.FromBase64String(salt),
prf: KeyDerivationPrf.HMACSHA1,
iterationCount: 10000,
numBytesRequested: 64));
Console.WriteLine(hashed);
I can currently not verify that this gives you the same hash as your NodeJS code.

Encrypted password ans salt does not match when I validate them

I use the following code to Encrypt and protect the password and I add salt to it, but when I try to validate it when the user login they don't match, I don't know why.
public static class Encrypt
{
public static string saltValue { get; set; }
public static string hashValue { get; set; }
public static void SecurePassword(string password)
{
// Create a truly random salt using RNGCryptoServiceProvider.
RNGCryptoServiceProvider csprng = new RNGCryptoServiceProvider();
byte[] salt = new byte[32];
csprng.GetBytes(salt);
// Get the salt value
saltValue = Convert.ToBase64String(salt);
// Salt the password
byte[] saltedPassword = Encoding.UTF8.GetBytes(saltValue + password);
// Hash the salted password using SHA256
SHA512Managed hashstring = new SHA512Managed();
byte[] hash = hashstring.ComputeHash(saltedPassword);
// Save both the salt and the hash in the user's database record.
saltValue = Convert.ToBase64String(salt);
hashValue = Convert.ToBase64String(hash);
}
public static void ValidateLogin(string password, string username)
{
// Read the user's salt value from the database
string saltValueFromDB = saltValue;
// Read the user's hash value from the database
string hashValueFromDB = hashValue;
byte[] saltedPassword = Encoding.UTF8.GetBytes(saltValueFromDB + password);
// Hash the salted password using SHA256
SHA512Managed hashstring = new SHA512Managed();
byte[] hash = hashstring.ComputeHash(saltedPassword);
string hashToCompare = Convert.ToBase64String(hash);
if (hashValueFromDB.Equals(hashToCompare))
Console.WriteLine("User Validated.");
else
Console.WriteLine("Login credentials incorrect. User not validated.");
}
}
Please advise. Thank you in advance
Changed your code a bit but this works:
public class Encrypt
{
public HashedCredential SecurePassword(string password, string salt = "")
{
var saltValue = salt;
if (string.IsNullOrEmpty(salt))
{
saltValue = GenertateSalt();
}
// Salt the password
byte[] saltedPassword = Encoding.UTF8.GetBytes(saltValue + password);
// Hash the salted password using SHA256
SHA512Managed hashstring = new SHA512Managed();
byte[] hash = hashstring.ComputeHash(saltedPassword);
return new HashedCredential(saltValue, Convert.ToBase64String(hash));
}
private string GenertateSalt()
{
RNGCryptoServiceProvider csprng = new RNGCryptoServiceProvider();
byte[] salt = new byte[32];
csprng.GetBytes(salt);
return Convert.ToBase64String(salt);
}
}
public class HashedCredential
{
public string SaltValue { get; }
public string HashValue { get; }
public HashedCredential(string saltValue, string hashValue)
{
SaltValue = saltValue;
HashValue = hashValue;
}
}
[TestMethod]
public void GenerateSalt()
{
// Arrange
var sut = new Encrypt();
// Act
var result = sut.SecurePassword("Test");
var resultB = sut.SecurePassword("Test", result.SaltValue);
// Assert
Console.WriteLine($"resultA:'{result.HashValue}'");
Console.WriteLine($"resultB:'{resultB.HashValue}'");
Assert.AreEqual(result.HashValue, resultB.HashValue);
}

Password hashing in UWP

I have the following code in .net framework.
public string GetHashedPassword(string password, string salt)
{
byte[] saltArray = Convert.FromBase64String(salt);
byte[] passArray = Convert.FromBase64String(password);
byte[] salted = new byte[saltArray.Length + passArray.Length];
byte[] hashed = null;
saltArray.CopyTo(salted, 0);
passArray.CopyTo(salted, saltArray.Length);
using (var hash = new SHA256Managed())
{
hashed = hash.ComputeHash(salted);
}
return Convert.ToBase64String(hashed);
}
I'm trying to create an equivalent in .net core for a UWP application. Here's what I have so far.
public string GetHashedPassword(string password, string salt)
{
IBuffer input = CryptographicBuffer.ConvertStringToBinary(password + salt, BinaryStringEncoding.Utf8);
var hashAlgorithm = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
var hash = hashAlgorithm.HashData(input);
//return CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8, hash);
}
The last line, converting the buffer back to a string doesn't work. I get this exception:
No mapping for the Unicode character exists in the target multi-byte code page.
How can I convert the buffer back into a string?
I am assuming, that you want to get the hashed password in a base64-format, because you did that in your .net example.
To get this, change:
CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8, hash);
to:
CryptographicBuffer.EncodeToBase64String(hash);
So the complete method looks like this:
public string GetHashedPassword(string password, string salt)
{
IBuffer input = CryptographicBuffer.ConvertStringToBinary(password + salt, BinaryStringEncoding.Utf8);
var hashAlgorithm = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
var hash = hashAlgorithm.HashData(input);
return CryptographicBuffer.EncodeToBase64String(hash);
}

myBB Passwords c# client

I'm working on a loader / client where my forum users will use their myBB information to login to my application. I know it's not good to have the database connection in the application. But I am also going to store their hwid on the database so I would need to connect to it anyway.
However, they store the passwords like this:
$hashedpsw = md5(md5($salt).md5($plainpassword));
And my attempt to recreate that passwords looks like this:
string salt = "D4UFUd6U"; // get salt from db
string password = "test!";// get password from user
MD5 md5 = new MD5CryptoServiceProvider();
// Create md5 hash of salt
byte[] saltBytes = Encoding.Default.GetBytes(salt);
byte[] saltHashBytes = md5.ComputeHash(salt);
string saltHash = System.BitConverter.ToString(saltHashBytes);
// Create your md5(password + md5(salt)) hash
byte[] passwordBytes = Encoding.Default.GetBytes(password + saltHash);
byte[] passwordHashBytes = md5.ComputeHash(salt);
string passwordHash = BitConverter.ToString(passwordHashBytes);
But I get the following error:
cannot convert from 'string' to 'System.IO.Stream'
ComputeHash wants an IO.Stream or a Byte[] as input, and as the error specifies, can't convert from your strings to IO.Stream implicitly.
The following is an example of how you can convert a string to a stream (stolen from this answer):
public Stream GenerateStreamFromString(string s)
{
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
This would alter your code to the following:
string salt = "D4UFUd6U"; // get salt from db
string password = "test!";// get password from user
MD5 md5 = new MD5CryptoServiceProvider();
// Create md5 hash of salt
byte[] saltBytes = Encoding.Default.GetBytes(salt);
byte[] saltHashBytes;
using( Stream saltStream = GenerateStreamFromString(salt))
{
salteHashBytes = md5.ComputeHash(saltStream);
}
string saltHash = System.BitConverter.ToString(saltHashBytes);
// Create your md5(password + md5(salt)) hash
byte[] passwordBytes = Encoding.Default.GetBytes(password + saltHash);
byte[] passwordHashBytes;
using( Stream saltStream = GenerateStreamFromString(salt))
{
passwordHashBytes = md5.ComputeHash(saltStream);
}
string passwordHash = BitConverter.ToString(passwordHashBytes);
You use the MD5CryptoServiceProvider class to encrypt using md5 hash algorithm. First add the following namespaces:
using System.Text;
using System.Security.Cryptography;
Second, try a function like this.
public static string Encrypt(string content)
{
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
byte[] bytes = Encoding.ASCII.GetBytes(content);
bytes = md5.ComputeHash(data);
string result = Encoding.ASCII.GetString(bytes);
return result;
}

hashing "SHA256" with two parameters

I must convert a JAVA function that Hashing a string.
this is a function:
private static String hmacSha256(String value, String key) throws NoSuchAlgorithmException, InvalidKeyException {
byte[] keyBytes = key.getBytes();
SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(signingKey);
byte[] rawHmac = mac.doFinal(value.getBytes());
return String.format("%0" + (rawHmac.length << 1) + "x", new BigInteger(1, rawHmac));
}
My doubt is: this function take 2 parameters:
String value: It is the string to crypt
String Key: It is another key
I already used the Sha256, but I always use it with only one parameter (one string to encrypt)
please, how can I wrote this function in c# or is there anyone who can explain to me the logical?
thank you
You can use HMACSHA256 class to make it work:
private static string ComputeHash(string key, string value)
{
var byteKey = Encoding.UTF8.GetBytes(key);
string hashString;
using (var hmac = new HMACSHA256(byteKey))
{
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(value));
hashString = Convert.ToBase64String(hash);
}
return hashString;
}
This is not plain SHA256, this is HMACSHA256 and there is allready a class in .Net.
HMACSHA256

Categories

Resources