Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert C# SHA256 hash to Ruby

Tags:

c#

ruby

sha

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.

Update

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.

like image 406
CWitty Avatar asked Oct 15 '25 20:10

CWitty


2 Answers

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.

like image 132
Wand Maker Avatar answered Oct 17 '25 10:10

Wand Maker


I think you should change new UnicodeEncoding()to new UTF8Encoding() or just use Encoding.UTF8

Unicode is UTF-16 in C#

like image 28
Norgerman Avatar answered Oct 17 '25 10:10

Norgerman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!