I'm trying to get the HMAC SHA256 value(str_signature), I followed the Ruby code from this post, although his example was converting code from Java(with a Hex key).
C#
string strRawSignature = "200123123891:12|11231231|GET|just%20test%20value"
// Convert signature to byte array in order to compute the hash
byte[] bSignature = Encoding.UTF8.GetBytes(strRawSignature);
// Convert ApiKey to byte array - for initializing HMACSHA256
byte[] bSecretKey = Convert.FromBase64String(strApiKey);
string strSignature = "";
using (HMACSHA256 hmac = new HMACSHA256(bSecretKey))
{
// Compute signature hash
byte[] bSignatureHash = hmac.ComputeHash(bSignature);
// Convert signature hash to Base64String for transmission
str_signature = Convert.ToBase64String(bSignatureHash);
}
Ruby
require "openssl"
require "base64"
digest = OpenSSL::Digest.new('sha256')
key = [ 'xiIm9FuYhetyijXA2QL58TRlvhuSJ73FtdxiSNU2uHE=' ]
#this is just a dummy signature to show what the possible values are
signature = "200123123891:12|11231231|GET|just%20test%20value"
hmac = OpenSSL::HMAC.digest(digest, key.pack("m*"), signature)
str_signature = Base64.urlsafe_encode64(hmac)
example result: "B0NgX1hhW-rsnadD2_FF-grcw9pWghwMWgG47mU4J94="
Update:
Changed the pack method to output base64 strings.
Edited variable names for concistency
References:
Used hexdigest, has a different ouput string length.
This example uses the digest method, although I'm not sure what value the key parameter has, hopefully it's a base 64 encoded string.
This uses hexdigest again. I am pretty sure that digest is the method to go vs hexdigest, since hexdigest ouput has a longer string compared to the sample HMAC value I have from C# script.
Finally got the monkey of my back!
I don't really need to create a sha256 digest object after all, I just had to put the 'sha256' parameter.
require 'openssl'
require "base64"
#API_KEY = base64 encoded string
key = Base64.decode64(API_KEY)
hash = OpenSSL::HMAC.digest('sha256', key, "Message")
puts Base64.encode64(hash)
thanks to this link
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've been coming against this for a few hours now and I can't seem to find a solution. I'm trying to encrypt a string using SHA512 and put it in a header for HTTP Request. I know that HTTP Headers only like ASCII characters but everytime I generate the encrypted string I only get nonASCII results, is there any way to force ASCII return? Here's my function generating the encryption:
private static string GenerateSignatureHeader(string data, string timestamp){
//Encode to UTF8 required for SHA512
byte[] encData = ASCIIEncoding.UTF8.GetBytes (data);
byte[] hash;
using (SHA512 shaM = new SHA512Managed ()) {
hash = shaM.ComputeHash (encData);
}
return ASCIIEncoding.Default.GetString (hash);
}
And adding to HTTP Request here:
request.Headers.Add("signature", GenerateSignatureHeader(body, timestamp));
Is what I'm doing here correct? The error is thrown when trying to add the header to the request:
Caused by: md52ce486a14f4bcd95899665e9d932190b.JavaProxyThrowable: System.ArgumentException: invalid header value: 4Ɓj�M�P��hM�$�
�s;��6��1!��,�y��.x;��d�G��2�#1'��1�
Parameter name: headerValue
System.Net.WebHeaderCollection.AddWithoutValidate (string,string)
System.Net.WebHeaderCollection.Add (string,string)
So I'm assuming that it's the nonASCII characters that are causing this?
A hash functions return pseudo-random bytes. Such a byte array very likely doesn't correspond to a valid character encoding such as ASCII. That is why you're getting those unprintable character placeholders.
You need to encode the output. For example using Base64 or Hex.
return System.Convert.ToBase64String(hash);
I have a string that needs to be hashed using a salt in C# and match what it would in PHP. The C# code is as follows:
string stringToHash = "123";
string saltToUse = "321";
byte[] stringBytes = ASCIIEncoding.ASCII.GetBytes(stringToHash);
byte[] saltBytes = ASCIIEncoding.ASCII.GetBytes(saltToUse);
var hmacMD5 = new HMACMD5(saltBytes);
var saltedHash = hmacMD5.ComputeHash(stringBytes);
byte[] hashedBytesNoSalt = MD5CryptoServiceProvider.Create().ComputeHash(stringBytes);
string hashedString = BitConverter.ToString(hashedBytesNoSalt).Replace("-", "").ToLower();
string saltedString = BitConverter.ToString(saltedHash).Replace("-", "").ToLower();
The PHP code to test if the C# is outputting correctly is:
<?php echo md5('123'.'321'); ?>
The C# outputs the correct UNSALTED MD5 hash, which is 202cb962ac59075b964b07152d234b70. However, when I try to salt using C# I get 900011ae860f471561023fba6cc25df6 and with PHP I get c8837b23ff8aaa8a2dde915473ce0991.
I am not sure why it is doing this or if this is even the correct way. The thing to remember is the C# needs to output to what the PHP outputs to.
The C# code is using a better salting mechanism than the PHP code. To match the PHP, all you need to do is run MD5 on stringToHash + saltToUse instead of using the HMACMD5's key feature. In short, do exactly what you did to produce your unsalted MD5 in C#, but pass in stringToHash + saltToUse instead.
A salt is not the same thing as a private key. HMACMD5 uses a private key, when all that you desire is a salted MD5 hash. Just append the salt to the string to generate the correct key... stringToHash + saltToUse.
Read about HMACMD5 here: http://msdn.microsoft.com/en-us/library/yd9e7dt2.aspx
I have something like that written in PHP:
$signature = md5($tosigndata);
Now, I am trying to replicate this in C#:
MD5.Create().ComputeHash(Tools.GetBytes(tosigndata))
But that gives me totally different result. How do I need to change my C# code in order to match PHP hash?
PS. Yeah, I know that .ComputeHash() returns byte[], but that doesn't change anything, i tried decoding it and it's still a different string.
Edit: Tools.GetBytes() returns Encoding.UTF8.GetBytes(tosigndata);
try this in C#:
byte[] asciiBytes = ASCIIEncoding.ASCII.GetBytes(tosigndata); // tosigndata is your string variable
byte[] hashedBytes = MD5CryptoServiceProvider.Create().ComputeHash(asciiBytes);
string hashedString = BitConverter.ToString(hashedBytes).Replace("-", "").ToLower();
// hashString contains your hash data similar to php md5
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))), “-”, “”);
}