I have the C# code:
byte[] bytes = new UnicodeEncoding().GetBytes(input);
return Convert.ToBase64String(new SHA256Managed().ComputeHash(bytes));
that encodes a string to an SHA2 hash, which is then base 64 encoded. I need to convert this into Ruby.
I tried several ways. This is one of them:
hash = Digest::SHA256.digest(val.encode('utf-8'))
encoded = Base64.urlsafe_encode64(hash)
My code all produce the same result that doesn't match. I cannot get them to work. Any help on converting this would be appreciated.
After some messing around I was able to get it working with a hard coded array, the issue is that the C# code adds a 0 after every element in the array. Here is the working ruby code (with the hard coded array):
Digest::SHA256.base64digest([99,0,104,0,97,0,100,0].pack('C*').force_encoding('utf-16'))
I suppose I could iterate through the array but that seems unnecessary.
Solution:
You need to use UTF-16LE
encoding to get same SHA-256 Hash
p hash = Digest::SHA256.base64digest("Hello".encode('UTF-16LE'))
How did I find that?
I used Online C# Tool to create the hash of a string "Hello"
using the code below:
using System.IO;
using System;
using System.Text;
using System.Security.Cryptography;
class Program
{
static void Main()
{
byte[] bytes = new UnicodeEncoding().GetBytes("Hello");
String s = Convert.ToBase64String(new SHA256Managed().ComputeHash(bytes));
Console.WriteLine(s);
}
}
Above program produced the output oH5Pc0MkbIKybzLlb4VBjVGNiy8trnfx1W/nr1Dbl68=
Then, I wrote a Ruby Program to compute Base64-encoded SHA-256 hash of string "Hello"
, by encoding the string in all the supported char encodings of Ruby to figure out which char encoding will give exact same result.
require "digest/sha2"
require "base64"
s = "Hello"
Encoding.list.each { |e| puts "Encoding: #{e.to_s} => Hash: #{Digest::SHA256.base64digest(s.encode(e)) rescue "error"}"}
After running the program, I came to conclude that if you use UTF-16LE
encoding, you will get exact same output.
p hash = Digest::SHA256.base64digest("Hello".encode('UTF-16LE'))
As per documentation of UnicodeEncoding
, it:
Represents a UTF-16 encoding of Unicode characters.
I think you should change new UnicodeEncoding()
to new UTF8Encoding()
or just use Encoding.UTF8
Unicode is UTF-16 in C#
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With