How to convert php's mb_convert_encoding() to C# equivalent - c#

I have tried rather unsuccessfully , to convert the following php code to C#
and require help please.
php code is
$string="012014Te$ting#501834502014060007400";
$salt = "Cli3ntH#sah";
$utfString=mb_convert_encoding($string.$salt,ÄSCII");
$hashTag=sha1($utfString,true);
$Hash = base64_encode($hashTag);
with C# code
byte[] ascii = Encoding.ASCII.GetBytes(objtohash);
byte[] utf8 = Encoding.Convert(Encoding.ASCII, Encoding.UTF8, ascii);
byte[] hashBytes2 = sha1.ComputeHash(utf8);
var Hash = Convert.ToBase64String(hashBytes2);
also tried this, where objtohash = $string.$salt (i.e. concatenated)
var sha1 = new System.Security.Cryptography.SHA1Managed();
//convert to ascii byte array
byte[] AScii = EncodeAscii(objtohash);
//Hash it
byte[] hashBytes = sha1.ComputeHash(AScii);
//convert it to base 64
var Hash = Convert.ToBase64String(hashBytes);
I have tried several other ways as per SO, but I cannot get the same hashed value as the php sample.Hopefully someone can do it and hopefully give explanation as to why.
Thanks

The syntax error was finger trouble.
The answer it turns out, ..basically by trying any and all combinations of what i could find by googling is:
var objtohashArry = Encoding.ASCII.GetBytes(objtohash);
var HashSharresult = SHA1.Create().ComputeHash(objtohashArry);
var requestHash = Convert.ToBase64String(HashSharresult);
RequestHash = requestHash;

Related

Getting issue when convert c# code to PHP as below

I am running this code:
var timeStamp = DateTime.UtcNow;
var sharedSecret = "xx";
var saltedString = timeStamp.ToString("2021-01-07T16:42:33.619667Z") + sharedSecret;
//Encoding saltedString using Unicode little-endian byte order
byte[] encodedSaltedString = Encoding.Unicode.GetBytes(saltedString);
//Hashing Algorithm used is SHA512
HashAlgorithm hash = new SHA512Managed();
//Compute Hash of encodedSaltedString
byte[] hashedEncodedString = hash.ComputeHash(encodedSaltedString);
//Convert hashed array to base64-encoded string
string signature = Convert.ToBase64String(hashedEncodedString);
I am then getting this result in C#:
"gQhjrLnY6fo44EeaaWaUBE1PY/8oEIRsUcK3AMSCVUCYMM4vRfxvQEEggXaHTF0GQbw4w2HbWArX1k6NnkzJFg=="
I converted to this code as below, but I am getting an issue. Can I get some help on this?
$timestamp = "2021-01-07T16:42:33.619667Z";
$sharedSecret = 'xx';
$saltedString = $timestamp.$sharedSecret;
$utf=mb_convert_encoding($saltedString, "UTF-16LE");
$signature = base64_encode(hash('sha512', $utf));
IN PHP I am getting this result:
ODEwODYzYWNiOWQ4ZTlmYTM4ZTA0NzlhNjk2Njk0MDQ0ZDRmNjNmZjI4MTA4NDZjNTFjMmI3MDBjNDgyNTU0MDk4MzBjZTJmNDVmYzZmNDA0MTIwODE3Njg3NGM1ZDA2NDFiYzM4YzM2MWRiNTgwYWQ3ZDY0ZThkOWU0Y2M5MTY=
But both should be same. The c# one is correct, I want the same in the php code as well.
From the PHP docs for hash:
hash ( string $algo , string $data , bool $binary = false ) : string|false
binary
   When set to true, outputs raw binary data. false outputs lowercase hexits.
You're not passing a value for $binary, so it's returning a string of hexadecimal characters.
The C# HashAlgorithm.ComputeHash method on the other hand binary data.
Since you're base64-encoding the result, you're presumably expecting the hash function to return binary data. You therefore need to pass true as the value for $binary:
$signature = base64_encode(hash('sha512', $utf, true));

Unable to encode byte array to UTF8 then decode it back to bytes

I'm trying to convert a byte array to a string, then at a later time convert those strings back to a byte array, but I'm getting some inconsistent results.
var salt = System.Text.Encoding.UTF8.GetString(encryptedPassword.Salt);
var key = System.Text.Encoding.UTF8.GetString(encryptedPassword.Key);
...
var saltBytes = System.Text.Encoding.UTF8.GetBytes(salt);
var keyBytes = System.Text.Encoding.UTF8.GetBytes(key);
In this case, the original salt and key are both byte[20], but the new ones are not equal (salt being a byte[36], key a byte [41], both with totally different values).
Basically what #DourHighArch said. You can go string->binary->string, but you can't expect to be able to go binary->string->binary using text encoding.
For what you are doing, you probably want to use something like base64 encoding. So you could write it like this:
var salt = Convert.ToBase64String(encryptedPassword.Salt);
var key = Convert.ToBase64String(encryptedPassword.Key);
...
var saltBytes = Convert.FromBase64String(salt);
var keyBytes = Convert.FromBase64String(key);

Convert C# to Ruby - MD5 and Base 64 a String

I have this code that I need to convert to ruby, this snippet is to create a security key used for a particular API. The string that I am encrypting is a JSON object.
Should I use Digest::MD5.hexdigest() or Digest::MD5.digest()?
C# Code
string strResponse = "[{\"Key\":\"BookNumber\", \"Value\"=>\"BJAK123\"},{\"Key\"=>\"AuthorCode\", \"Value\"=>\"BNA123\"}]";
using (MD5 md5 = MD5.Create())
{
byte[] bPayload = Encoding.UTF8.GetBytes(strPayload);
byte[] bPayloadHash = md5.ComputeHash(bPayload);
strPayloadBase64 = Convert.ToBase64String(bPayloadHash);
}
Ruby Code
payload = [{"Key"=>"BookNumber", "Value"=>"BJAK123"},{"Key"=>"AuthorCode", "Value"=>"BNA123"}]
utf8_params = payload.to_json.force_encoding("iso-8859-1").force_encoding("utf-8")
payload_base64 = Base64.encode64(Digest::MD5.hexdigest(utf8_params))
Use
payload_base64 = Digest::MD5.base64digest(utf8_params)
as Digest::MD5.hexdigest produces a hex string of digest, whereas C# code is performing base64 encoding of the digest.

C# vs PHP - They return different HMACSHA256

This is my PHP code:
<?php
$sig_string = "GET&https%3A%2F%2Fapi.pinterest.com%2Fv3%2Fusers%2Farchimede%2Fboards%2F&client_id=987654&timestamp=1391761866";
$secret = "123456";
$sig = hash_hmac("sha256", $sig_string, $secret);
echo $sig;
?>
which returns (correctly) a7918aec50919915f3cefed8622ddbe35448c8f71a54ad115828f07a05930f4c
Now, I want to translate this function inside C#. Code:
signature_base_string = "GET&https%3A%2F%2Fapi.pinterest.com%2Fv3%2Fusers%2Farchimede%2Fboards%2F&client_id=987654&timestamp=1391761866";
signing_key = "123456";
var encoding = new System.Text.ASCIIEncoding();
byte[] keyByte = encoding.GetBytes(signing_key);
byte[] messageBytes = encoding.GetBytes(signature_base_string);
using (var hmacsha256 = new HMACSHA256(keyByte))
{
byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
Response.Write(Convert.ToBase64String(hashmessage));
}
but it retuns p5GK7FCRmRXzzv7YYi3b41RIyPcaVK0RWCjwegWTD0w=
Why two different results? Whats wrong in the C# code?
PHP encodes the result in hexadecimal and c# encodes that in base64. But the are same.
Change this line:
Response.Write(Convert.ToBase64String(hashmessage));
To this:
Response.Write(BitConverter.ToString(hashmessage).Replace("-", "").ToLower());
to have the result in hexadecimal encoding.
They are the same:
The result from .NET C# is p5GK7FCRmRXzzv7YYi3b41RIyPcaVK0RWCjwegWTD0w=. This is a base64 string.
You can convert it to hexadecimal using this tool for example. And you'll get the same as PHP after converting:
A7918AEC50919915F3CEFED8622DDBE35448C8F71A54AD115828F07A05930F4C

Generate a PHP UTF-16 SHA1 hash to match C# method

I'm trying to replicate some C# code in PHP5 and am having some difficulties.
The C# code is as following, and it is important to note that it cannot be changed:
string s = strToHash;
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] bytes = encoding.GetBytes(s);
SHA1Managed managed = new SHA1Managed();
bytes = encoding.GetBytes(Convert.ToBase64String(managed.ComputeHash(bytes)) + "Space");
return Convert.ToBase64String(managed.ComputeHash(bytes));
The PHP code I've written to replicate this is as follows:
utfString = mb_convert_encoding($strToHash,"UTF-16");
hashTag = sha1($utfString,true);
base64Tag = base64_encode($hashTag);
encodedBase64Tag = mb_convert_encoding($base64Tag."Space","UTF-16");
base64EncodedAgain = base64_encode($encodedBase64Tag);
echo $base64EncodedAgain
However, the two outputs don't match up.
I believe this is because the SHA1 method in PHP works on ASCII encoded strings, not the encoding actually used by the passed in string.
I would like to get this to work, and I can't achieve it by altering the c# code (although no-doubt that would be the easiest fix).
Please can any advise on some ideas?
OK, I have altered the code following Artefacto's advice, and it still isn't working as expected.
The PHP Code now looks like this:
$utfString = "\xFF\xFE".mb_convert_encoding($strToHash,"UTF-16LE");
$hashTag = sha1($utfString,true);
$base64Tag = base64_encode($hashTag);
$encodedBase64Tag = "\xFF\xFE".mb_convert_encoding($base64Tag."Space","UTF-16LE");
$hashedAgain = sha1($encodedBase64Tag,true);
$base64EncodedAgain = base64_encode($hashedAgain);
echo $base64EncodedAgain."<Br/>";
And the outputed value of this method is:
1/Y5MCzI8vDJqc456YIicpwoyy0=
However, from the C# code, the value is this:
VPf7BhT1ksAfWbzeJw35g+bVKwY=
Well, try this code:
$utfString = mb_convert_encoding($strToHash,"UTF-16");
$hashTag = sha1($utfString,true);
$base64Tag = base64_encode($hashTag);
$encodedBase64Tag = mb_convert_encoding($base64Tag."Space","UTF-16");
$base64EncodedAgain = base64_encode(sha1($encodedBase64Tag, true));
echo $base64EncodedAgain
Because you miss one sha1 call.
Update
Now this code should work:
$utfString = mb_convert_encoding($strToHash,"UTF-16LE");
$hashTag = sha1($utfString,true);
$base64Tag = base64_encode($hashTag);
$encodedBase64Tag = mb_convert_encoding($base64Tag."Space","UTF-16LE");
$hashedAgain = sha1($encodedBase64Tag,true);
$base64EncodedAgain = base64_encode($hashedAgain);
echo $base64EncodedAgain . "<br />";
The docs for the no-arg constructor of UnicodeEncoding say this:
This constructor creates an instance that uses the little endian byte order, provides a Unicode byte order mark, and does not throw an exception when an invalid encoding is detected.
Now, mb_convert_encoding assumes "UTF-16" as "UTF-16BE" (big-endian). It also does not provide a BOM. Therefore, you must do instead:
$utfString = "\xFF\xFE" . mb_convert_encoding($strToHash,"UTF-16LE");
/* ...*/
$encodedBase64Tag = "\xFF\xFE" . mb_convert_encoding($base64Tag."Space","UTF-16LE");
As Paja pointed out, you're also missing a call to sha1.
This code should work...
$utfString = mb_convert_encoding($strToHash,"UTF-16LE");
$hashTag = sha1($utfString,true);
$base64Tag = base64_encode($hashTag);
echo $base64Tag;

Categories

Resources