How do I convert a C# function to a PHP function? The C# code is below:
internal string EncodePassword(string password, string salt)
{
// Get the Unicode bytes of the plain text password.
byte[] bytes = System.Text.Encoding.Unicode.GetBytes(password);
// The salt is a Base64 encoded string, convert back to a byte array.
byte[] src = Convert.FromBase64String(salt);
// Concat both byte buffers.
byte[] dst = new byte[src.Length + bytes.Length];
byte[] inArray = null;
System.Buffer.BlockCopy(src, 0, dst, 0, src.Length);
System.Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
// Compute the SHA1-hash from the concatenated buffer.
System.Security.Cryptography.SHA1 algorithm = System.Security.Cryptography.SHA1Managed.Create();
inArray = algorithm.ComputeHash(dst);
// Return the result as a Base64-string.
return Convert.ToBase64String(inArray);
}
I know its too late to answer this question. But i think it will be helpful for someone who is trying to convert C# code to PHP. I had a similar kind of requirement recently
<?php
$password ='test123';
$salt = '5Br2nXb56EpliGXmfHdWWw==';
$password = mb_convert_encoding($password,'UTF-16LE');
echo base64_encode(sha1(base64_decode($salt).$password,true));
I'd say it's something like this:
function encodePassword($password, $salt){
return base64_encode(sha1($password . base64_decode($salt), true));
}
You can use the PHP SHA1 function to do the encryption.
Related
I want to re-create the MyBB hashing process so I can use its database to authenticate users on a 3rd party app (written on C#).
MyBB uses:
md5(md5($salt).password)
My problem is that the result I get on C# is nowhere similar to the one MyBB gets.
What I've done on C#:
public string HashPass(string password, string salt)
{
MD5 md5 = new MD5CryptoServiceProvider();
byte[] saltHash =md5.ComputeHash(System.Text.Encoding.ASCII.GetBytes(salt));
string passwordAndSalt = password + System.Text.Encoding.ASCII.GetString(saltHash);
byte[] finalHash = md5.ComputeHash(System.Text.Encoding.ASCII.GetBytes(passwordAndSalt));
string final = System.Text.Encoding.ASCII.GetString(finalHash);
return final;
}
The result I get from using that function for password "Test123" and salt "0fYR6mEE" (gathered from MyBB db) is: "??R?????s??" while the actual result should look like "VaHffsyzJeEa4dB3bbMWeUlJObAfN5I9rf1CuNRXCa6xPJTzXL".
Most likely I'm missing something obvious, sorry about that.
There are unknowns here. Which encoding does MyBB use to the password bytes? It could be ASCII, ANSI, or UTF8 or it could get the string bytes directly, i.e., without encoding. So I will write it partly as pseudo code
byte[] passwordBytes = GetBytes(password); // Where you have to define GetBytes
byte[] saltBytes = System.Convert.FromBase64String(salt); // Assuming it is given as base64
// Merge the password bytes and the salt bytes
var mergedBytes = new byte[passwordBytes.Length + saltBytes.Length];
Array.Copy(passwordBytes, mergedBytes, passwordBytes.Length);
Array.Copy(saltBytes, 0, mergedBytes, passwordBytes.Length, saltBytes.Length);
var md5 = new MD5CryptoServiceProvider();
byte[] finalHash = md5.ComputeHash(mergedBytes);
string final = System.Convert.ToBase64String(finalHash);
Note that I'm merging the password bytes and the salt bytes, not the password string and the salt string. Then the MD5 it taken only once from these merged bytes.
But I'm not sure what md5(md5($salt).password) does. Is md5() returning the the hash as base64 string already? Maybe you would have to convert the salt from base64 to bytes[], then get the MD% hash, convert it into a base64 string and then concatenate it with the password string. Then get the bytes from this combined string, do the hash again and convert the result to a base64 string again.
You would have to dig deeper into the source code of MyBB to be sure.
I have to replicate C# hash from the code below into PHP. I have been searching but didn't find a solution so far.
From this article on creating an md5 hash string:
using System;
using System.Text;
using System.Security.Cryptography;
// Create an md5 sum string of this string
static public string GetMd5Sum(string str)
{
// First we need to convert the string into bytes, which
// means using a text encoder.
Encoder enc = System.Text.Encoding.Unicode.GetEncoder();
// Create a buffer large enough to hold the string
byte[] unicodeText = new byte[str.Length * 2];
enc.GetBytes(str.ToCharArray(), 0, str.Length, unicodeText, 0, true);
// Now that we have a byte array we can ask the CSP to hash it
MD5 md5 = new MD5CryptoServiceProvider();
byte[] result = md5.ComputeHash(unicodeText);
// Build the final string by converting each byte
// into hex and appending it to a StringBuilder
StringBuilder sb = new StringBuilder();
for (int i=0;i<result.Length;i++)
{
sb.Append(result[i].ToString("X2"));
}
// And return it
return sb.ToString();
}
For input = "123", the above code gives me "5FA285E1BEBE0A6623E33AFC04A1FBD5"
I have tried the following PHP code but it does not give the same output.
From the SO question PHP MD5 not matching C# MD5:
$str = "123";
$strUtf32 = mb_convert_encoding($str, "UTF-32LE");
echo md5($strUtf32);
This code has the result = "a0d5c8a4d386f15284ec25fe1eeeb426". By the way, changing UTF-32LE to utf-8 or utf-16 still does not give me the same result.
Can anyone help?
Yep, as CodesInChaos suggests, you got the encodings wrong.
On php side try this:
$str = "123";
$strUtf32 = mb_convert_encoding($str, "UTF-16LE");
echo md5($strUtf32);
This will give you 5FA285E1BEBE0A6623E33AFC04A1FBD5. This will match System.Text.Encoding.Unicode on the c# side.
Otherwise change System.Text.Encoding.Unicode to System.Text.Encoding.UTF32 on the c# side. This will give you A0D5C8A4D386F15284EC25FE1EEEB426.
Uhh, the C# code creates a MD5 hash and the PHP mb_convert_encoding function just encodes the string...
Plus, this is NOT THE FULL CODE from the link you gave. You are missing the important MD5 function:
$str = "123";
$strUtf32 = mb_convert_encoding($str, "UTF-16");
echo md5($strUtf32); <=====
If that code matches there should be NO REASON why that shouldn't work, as the MD5 algorithm is still the same and does not vary from language to language.
Why aren't these the same?
php:
$hash = hash('sha256', $userData['salt'] . hash('sha256', $password) );
c#
public static string ComputeHash(string plainText, string salt)
{
// Convert plain text into a byte array.
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
byte[] saltBytes = Encoding.UTF8.GetBytes(salt);
SHA256Managed hash = new SHA256Managed();
// Compute hash value of salt.
byte[] plainHash = hash.ComputeHash(plainTextBytes);
byte[] concat = new byte[plainHash.Length + saltBytes.Length];
System.Buffer.BlockCopy(saltBytes, 0, concat, 0, saltBytes.Length);
System.Buffer.BlockCopy(plainHash, 0, concat, saltBytes.Length, plainHash.Length);
byte[] tHashBytes = hash.ComputeHash(concat);
// Convert result into a base64-encoded string.
string hashValue = Convert.ToBase64String(tHashBytes);
// Return the result.
return hashValue;
}
C# is outputting a base64 ecoded string, and PHP is outputting a number in hex. A better comparison might be to pass the parameter true to the end of the hash function of PHP and base64 the result:
$hash = base64_encode(
hash('sha256', $userData['salt'] . hash('sha256', $password), true )
);
Because they're different. Your C# code encodes the computed hash in Base64 encoding at the end. PHP just returns a string of hexadecimal digits.
First suspect:
Encoding.UTF8.GetBytes(plainText);
C# uses UTF-8, your PHP probably doesn't, but you could be lucky if you use strictly letters from the US-ASCII subset.
Second suspect:
Convert.ToBase64String(tHashBytes);
There's nothing about Base64 in your PHP.
Since PHP will give you a hex-encoded result, you should switch to Hex in your C#, too. See this answer for solutions.
Well I'm no C# programmer, but one thing that leaps out at me is this:
// Convert result into a base64-encoded string.
string hashValue = Convert.ToBase64String(tHashBytes);
Are you base64-encoding the final output in C#? Because you're not in PHP...
C#
string toHash = "abcdefg";
SHA256Managed hash = new SHA256Managed();
byte[] signatureData = hash.ComputeHash(new UnicodeEncoding().GetBytes(toHash));
string hashResult = System.Convert.ToBase64String(signatureData);
PHP
print base64_encode(hash("sha256",mb_convert_encoding("abcdefg","UTF-16LE"),true));
Write like top code,They are the same
C#
string toHash = "abcdefg";
SHA256Managed hash = new SHA256Managed();
byte[] signatureData = hash.ComputeHash(new UnicodeEncoding().GetBytes(toHash));
string hashResult = System.Convert.ToBase64String(signatureData);
PHP
print base64_encode(hash("sha256",mb_convert_encoding("abcdefg","UTF-16LE"),true));
Works for me.
I am converting my Java code to C#. I am not able to convert the following function from Java to C#. The fumction is calling the Update method twice. I have tried the C# code in following manner
SHA256 sh = SHA256.Create();
Encoding shEncoding = Encoding.UTF7;
byte[] data = shEncoding.GetBytes(sn);
byte hash = sh.ComputeHash(data);
But I don't know how to convert two consecutive update function call in C#.
String getSHA(byte[] sf,String sn,byte[] mac) throws NoSuchAlgorithmException
{
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(sf);
md.update(sn.getBytes());
byte[] hash = md.digest(mac);
StringBuilder sb = new StringBuilder();
for(byte b : hash) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
Thanks in Advance.
Your help/guidance will help me lot.
You can use TransformBlock and TransformFinalBlock on SHA256 (~update and digest in Java) and retrieve the hash using the Hash property.
i have a hashing algorithm in C#, in a nutshell, it is:
string input = "asd";
System.Security.Cryptography.MD5 alg = System.Security.Cryptography.MD5.Create();
System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
byte[] hash = alg.ComputeHash(enc.GetBytes(input));
string output = Convert.ToBase64String(hash);
// outputs: eBVpbsvxyW5olLd5RW0zDg==
Console.WriteLine(output);
Now I need to replicate this behaviour in php,
$input = "asd";
$output = HashSomething($input);
echo $output;
How can I achieve it?
I checked
md5
utf8_decode
utf8_encode
base64_encode
base64_decode
url_decode
but i noted the php md5 doesn't get the == on the end... what am I missing?
NOTE: I cannot change C# behaviour because it's already implemented and passwords saved in my db with this algorithm.
The issue is PHP's md5() function by default returns the hex variation of the hash where C# is returning the raw byte output that must then be made text safe with base64 encoding. If you are running PHP5 you can use base64_encode(md5('asd', true)). Notice the second parameter to md5() is true which makes md5() return the raw bytes instead of the hex.
Did you remember to base64 encode the md5 hash in php?
$result = base64_encode(md5($password, true));
The second parameter makes md5 return raw output, which is the same as the functions you're using in C#
Your C# code takes the UTF8 bytes from the string; calculates md5 and stores as base64 encoded. So you should do the same in php, which should be:
$hashValue = base64_encode(md5(utf8_decode($inputString)))
it should be like as below for php
php -r "echo base64_encode(md5(utf8_encode('asd'),true));"
I had the same issue...using just md5($myvar) it worked. I am getting the same result C# and PHP.
Gavin Kendall posted helped me. I hope this helps others.
http://jachman.wordpress.com/2006/06/06/md5-hash-keys-with-c/
public static string MD5Hash(string text)
{
System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
return System.Text.RegularExpressions.Regex.Replace(BitConverter.ToString(md5.ComputeHash(ASCIIEncoding.Default.GetBytes(text))), “-”, “”);
}