【问题标题】:Convert C# SHA256 hash to Ruby将 C# SHA256 哈希转换为 Ruby
【发布时间】:2015-08-23 19:05:30
【问题描述】:

我有 C# 代码:

byte[] bytes = new UnicodeEncoding().GetBytes(input);
return Convert.ToBase64String(new SHA256Managed().ComputeHash(bytes));

将字符串编码为 SHA2 哈希,然后进行 base 64 编码。我需要把它转换成 Ruby。

我尝试了几种方法。这是其中之一:

hash = Digest::SHA256.digest(val.encode('utf-8'))
encoded = Base64.urlsafe_encode64(hash)

我的代码都产生了不匹配的相同结果。我不能让他们工作。任何有关转换的帮助将不胜感激。

更新

经过一番折腾,我能够让它与硬编码数组一起工作,问题是 C# 代码在数组中的每个元素后添加了一个 0。这是工作的 ruby​​ 代码(带有硬编码数组):

Digest::SHA256.base64digest([99,0,104,0,97,0,100,0].pack('C*').force_encoding('utf-16'))

我想我可以遍历数组,但这似乎没有必要。

【问题讨论】:

    标签: c# ruby sha


    【解决方案1】:

    解决方案:

    您需要使用UTF-16LE 编码来获得相同的SHA-256 Hash

    p hash = Digest::SHA256.base64digest("Hello".encode('UTF-16LE'))
    

    我是怎么发现的?

    我使用Online C# Tool 使用下面的代码创建了字符串"Hello" 的哈希:

    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);
        }
    }
    

    上面的程序产生了输出oH5Pc0MkbIKybzLlb4VBjVGNiy8trnfx1W/nr1Dbl68=

    然后,我编写了一个 Ruby 程序来计算字符串 "Hello" 的 Base64 编码的 SHA-256 哈希值,方法是在 Ruby 的所有支持的 char 编码中对字符串进行编码,以确定哪种 char 编码将给出完全相同的结果。

    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"}"}
    

    运行程序后,我得出结论,如果你使用UTF-16LE编码,你将得到完全相同的输出。

    p hash = Digest::SHA256.base64digest("Hello".encode('UTF-16LE'))
    

    根据documentation of UnicodeEncoding,它:

    表示 Unicode 字符的 UTF-16 编码。

    【讨论】:

      【解决方案2】:

      我认为您应该将 new UnicodeEncoding() 更改为 new UTF8Encoding() 或只使用 Encoding.UTF8

      Unicode 在 C# 中是 UTF-16

      【讨论】:

      • 以上代码是在反编译用于密码哈希的 dll 后获取的。也许如果我在 ruby​​ 端尝试 utf-16 就可以了
      • 我认为也许使用 utf-16le 会起作用(我对 ruby​​ 了解不多)....utf-16 会将每个字符编码为 2 或 4 个字节...使用 GetBytes C# 中的方法不会放 BOM,我认为 mybe 使用 little edian 会起作用
      【解决方案3】:

      K 所以它有很多项目。在 C# UnicodeEncoding().GetBytes(str) 中,显然在字节数组的每个字符后添加了一个 0。所以我不得不在 Ruby 中解决这个问题。幸运的是,我能够使用一点红宝石魔法来做到这一点。完整的工作解决方案如下。

      byte_array = input.bytes.zip(input.bytes.map{|b| 0}).flatten.compact
      Digest::SHA256.base64digest(byte_array.pack('C*').force_encoding('utf-16'))
      

      这给了我一个与数据库中的值匹配的相同哈希输出。

      【讨论】:

        猜你喜欢
        • 2011-12-10
        • 2019-08-26
        • 1970-01-01
        • 1970-01-01
        • 2013-07-08
        • 1970-01-01
        • 1970-01-01
        • 2021-01-17
        • 2011-06-29
        相关资源
        最近更新 更多