Password hashing in UWP - c#

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);
}

Related

Telerik Sitefinity Password Hash function

I have a table with login credentials for a Telerik Sitefinity system. I want to use the same login credentials, but with a different application that doesn't have Sitefinity libraries. I'm struggling with the password encoding, which is set to Hash (Default is SHA1 algorithm).
I tried using the following code to encode passwords, but it doesn't match up with what Sitefinity generated.
public string EncodePassword(string pass, string salt)
{
byte[] bytes = Encoding.Unicode.GetBytes(pass);
byte[] src = Convert.FromBase64String(salt);
byte[] dst = new byte[src.Length + bytes.Length];
Buffer.BlockCopy(src, 0, dst, 0, src.Length);
Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
byte[] inArray = algorithm.ComputeHash(dst);
return Convert.ToBase64String(inArray);
}
EXAMPLE:
PASSWORD: password111
SALT: 94EBE09530D9F5FAE3D002A4BF262D2F (as saved in the SF user table)
Hash with function above: 8IjcFO4ad8BdkD40NJcgD0iGloU=
Hash in table generated by SF:A24GuU8OasJ2bicvT/E4ZiKfAT8=
I have searched online if SF generates the encoded password differently, but can't find any results. How can I use the login credentials created by SF without SF libraries?
You right, Sitefinity is using SHA1 algorithm, but you need to use additional ValidationKey from configuration settings.
Here the working example of code for you:
private static bool CheckValidPassword(string password)
{
//from sf_users column [salt]
var userSalt = "420540B274162AA093FDAC86894F3172";
//from sf_users column [passwd]
var userPassword = "a99j8I0em8DOP1IAJO/O7umQ+H0=";
//from App_Data\Sitefinity\Configuration\SecurityConfig.config attribute "validationKey"
var validationKey = "862391D1B281951D5D92837F4DB9714E0A5630F96483FF39E4307AE733424C557354AE85FF1C00D73AEB48DF3421DD159F6BFA165FF8E812341611BDE60E0D4A";
return userPassword == ComputeHash(password + userSalt, validationKey);
}
internal static string ComputeHash(string data, string key)
{
byte[] hashKey = HexToBytes(key);
HMACSHA1 hmacshA1 = new HMACSHA1();
hmacshA1.Key = hashKey;
var hash = hmacshA1.ComputeHash(Encoding.Unicode.GetBytes(data));
return Convert.ToBase64String(hash);
}
public static byte[] HexToBytes(string hexString)
{
byte[] numArray = new byte[hexString.Length / 2];
for (int index = 0; index < numArray.Length; ++index)
numArray[index] = Convert.ToByte(hexString.Substring(index * 2, 2), 16);
return numArray;
}

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;
}

Creating a function in .net for login

I have salt and encrypted password in my db. and want to create a login function. I created a login function but it always returns false.
My function for conversion is here, is it right or not?
public static String HashPassword(String password, String salt)
{
var combinedPassword = String.Concat(password, salt);
var sha256 = new SHA256Managed();
var bytes = UTF8Encoding.UTF8.GetBytes(combinedPassword);
var hash = sha256.ComputeHash(bytes);
return Convert.ToBase64String(hash);
}
public static Boolean ValidatePassword(String enteredPassword, String storedHash, String storedSalt)
{
// Consider this function as an internal function where parameters like
// storedHash and storedSalt are read from the database and then passed.
var hash = HashPassword(enteredPassword, storedSalt);
return String.Equals(storedHash, hash);
}

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

md5 hash confusion

My company uses the following algorithm to hash passwords before store it in the database:
public static string Hash(string value)
{
byte[] valueBytes = new byte[value.Length * 2];
Encoder encoder = Encoding.Unicode.GetEncoder();
encoder.GetBytes(value.ToCharArray(), 0, value.Length, valueBytes, 0, true);
MD5 md5 = new MD5CryptoServiceProvider();
byte[] hashBytes = md5.ComputeHash(valueBytes);
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < hashBytes.Length; i++)
{
stringBuilder.Append(hashBytes[i].ToString("x2"));
}
return stringBuilder.ToString();
}
To me it sounds like a trivial md5 hash, but when I tried to match a password (123456) the algorithm gives me ce0bfd15059b68d67688884d7a3d3e8c, and when I use a standard md5 hash it gives me e10adc3949ba59abbe56e057f20f883e.
A iOS version of the site is being build, and the users needs to login, the password will be hashed before sent. I told the iOS team to use a standard md5 hash, but of course it don't worked out.
I can't unhash the password and hash it again using the standard md5 (of course), and I don't know what exactly tell to the iOS team, in order to get the same hash.
Any help?
You need to use the same encoding on both ends (probably UTF8).
If you replace your code with
byte[] hashBytes = md5.ComputeHash(Encoding.UTF8.GetBytes("123456"));
, you'll get e10adc3949ba59abbe56e057f20f883e.
You need to use UTF8 instead of Unicode. The following code works exactly like the PHP md5() function:
public static string md5(string value)
{
byte[] encoded = ASCIIEncoding.UTF8.GetBytes(value);
MD5CryptoServiceProvider md5Provider = new MD5CryptoServiceProvider();
byte[] hashCode = md5Provider.ComputeHash(encoded);
string ret = "";
foreach (byte a in hashCode)
ret += String.Format("{0:x2}", a);
return ret;
}

Categories

Resources