我有以下 C# 代码:
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
public class Program
{
public static void Main()
{
string profileId = "TEST";
using (MD5 md5 = MD5.Create())
{
string playerGroup;
byte[] inputBytes = Encoding.UTF8.GetBytes(profileId);
byte[] hashBytes = md5.ComputeHash(inputBytes);
long hashCode = BitConverter.ToInt64(hashBytes, 0);
Console.WriteLine(hashCode);
}
}
}
结果:-1956981089572930813
我想在 SQL (Amazone Redshift) 中复制相同的过程。 但我得到了不同的结果。 如果我这样做:
select from_hex(substring(md5('TEST'), 1, 16))::bigint
结果:233018722177570788
有什么方法可以在 SQL (Redshift) 上重现 C# 流程吗?
我尝试过:
select from_hex(substring(md5('TEST'), 1, 16))::bigint
我期待的是:-1956981089572930813 我得到:233018722177570788
这里可能会出现很多问题。
您正在处理 128 位 md5 哈希的两种不同表示形式 - C# 采用 16 字节二进制数组,而 Redshift 是 32 个十六进制数字字符串。 正如 C# 文档所述:
“MD5 类的 ComputeHash 方法将哈希值返回为 16 字节的数组。请注意,某些 MD5 实现会生成 32 个字符的十六进制格式的哈希值。要与此类实现进行互操作,请将 ComputeHash 方法的返回值格式化为十六进制值。”
我的第一个建议是将 MD5 函数的结果作为十六进制字符串进行比较。 这会让您了解第一步中情况是否相同。由于多种原因,这些可能会有所不同,其中最大的原因是字节顺序(硬件处理位级数据的顺序)。
由于十六进制是每个存储字节 16 个值(4 位),而字节数组数据每个存储字节有 256 个值(8 位),因此数据密度是一半。 (看起来这对您的代码来说并不是什么新闻。)在从字节数据转换为十六进制时,您可能会看到字符对翻转 - 位 0-3 是在位 4-7 之前还是之后? 这就是字节顺序问题。 您将需要再次单独查看这些函数,以了解它们的行为方式以及是否需要进行数据操作才能产生等效结果。
您的代码在快速审查中看起来不错,因此我倾向于将字节序问题作为原因。 逐步进行调试过程将有助于解决此类问题,但也可以显示是否存在其他问题。处理字节顺序可能很痛苦,但您可以找到一些代码片段来帮助解决这些问题。 您的 C# 代码甚至可以运行字节序测试来确定要运行的 MD5 进程。 您是否发现在不同计算机架构上运行时 C# MD5 结果存在差异?