C# 和 javascript 中 guid 的哈希值相同

发布于 2024-09-14 19:21:04 字数 251 浏览 9 评论 0原文

我有一个问题,我需要能够在 javascript 和 C# 中为 GUID 生成相同的均匀分布的数字哈希值。我想这会阻止我在 C# 中使用 Guid.GetHashCode(),因为如果不对 C# 进行逆向工程,我就无法在 JS 中重现该行为。

有没有一种快速的方法来从 JS 中的 guid/strings 生成哈希值?字符串的所有数字是否均匀分布在 .NET 生成的 GUID 中?我应该将尾随字符转换/转换为 int 吗?

I have a problem where I need to be able to generate identical uniformly distributed numeric hashs for a GUID in both javascript and C#. I guess that would prevent me from using Guid.GetHashCode() in C#, since I can't reproduce the behavior in JS without reverse engineering the C#.

Is there a fast way to produce hashes from guids/strings in JS? Are all digits of the string uniformly distributed in a .NET generated GUID? Should I just cast/convert the trailing chars into an int?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情深如许 2024-09-21 19:21:04

字节显然分布不均匀。

我整理了一些代码来对 .NET Guid 进行采样并绘制分布图:

首先是测试代码,这将创建一百万个 Guid,并计算字节数组中每个字节的不同值的数量。它将所有内容输出到我在 Scilab 中绘制的矩阵中。

int[,] counter = new int[16, 256];
for (int i = 0; i < 1000000; i++)
{
    var g = Guid.NewGuid();
    var bytes = g.ToByteArray();
    for (int idx = 0; idx < 16; idx++)
    {
        counter[idx, bytes[idx]]++;
    }
}
StringBuilder sb = new StringBuilder();
sb.AppendLine("x = [");
for (int idx = 0; idx < 16; idx++)
{
    for (int b = 0; b < 256; b++)
    {
        sb.Append(counter[idx, b]);
        if (idx != 255)
        {
            sb.Append(" ");
        }
    }
    if (idx != 15)
    {
        sb.AppendLine(";");
    }
}
sb.AppendLine("]");

File.WriteAllText("plot.sce", sb.ToString());

以下是分布,图表绘制了字节数组中每个位置的每个不同值的数量:

字节数组中位置 0-6 的值分布:
字节数组中位置0-6的值分布
字节数组中位置7的值分布:
字节数组中位置7的值分布
字节数组中位置8的值分布:
字节数组中位置8的值分布
字节数组中位置 9-15 的值分布:
字节数组中位置 9-15 的值分布

对于字节位置 0-6 和 9-15 的分布值似乎是偶数,但对于字节位置 7 和 8,分布相当有限。

也就是说,对于 guid(下面是字节位置的开头,请注意奇怪的顺序),

{1369ea05-b9f9-408b-ac7c-7ebd0f35d562}
                         1 1 1 1 1 1
 3 2 1 0  5 4  7 6  8 9  0 1 2 3 4 5

位置 7 可以采用从 64 (0x40) 到 79 (0x4F) 的值。
位置 8 的取值范围为 128 (0x80) 到 191 (0xBF)。
其余字节均匀分布。

注意:测试在 32 位 Windows 7 计算机上的 .NET4 上运行。

教训:不要假设,测试。

答案:要使用 .NET Guid 来计算负载平衡,您可以使用除上面 Guid 中标记为 7 和 8 的位置之外的任何部分。

问题:有人知道为什么分布不均匀吗?

The bytes are apparently not evenly distributed.

I put together some code to sample the .NET Guids and plot the distribution:

First of all the test code, this creates one million Guids and counts the number of different values for each byte in the byte array. It outputs it all into a matrix that I plot in Scilab.

int[,] counter = new int[16, 256];
for (int i = 0; i < 1000000; i++)
{
    var g = Guid.NewGuid();
    var bytes = g.ToByteArray();
    for (int idx = 0; idx < 16; idx++)
    {
        counter[idx, bytes[idx]]++;
    }
}
StringBuilder sb = new StringBuilder();
sb.AppendLine("x = [");
for (int idx = 0; idx < 16; idx++)
{
    for (int b = 0; b < 256; b++)
    {
        sb.Append(counter[idx, b]);
        if (idx != 255)
        {
            sb.Append(" ");
        }
    }
    if (idx != 15)
    {
        sb.AppendLine(";");
    }
}
sb.AppendLine("]");

File.WriteAllText("plot.sce", sb.ToString());

Here are the distributions, the graphs plot the number of each distinct value for each of the positions in the byte array:

The value distribution for the positions 0-6 in the byte array:
The value distribution for the positions 0-6 in the byte array
The value distribution for the position 7 in the byte array:
The value distribution for the position 7 in the byte array
The value distribution for the position 8 in the byte array:
The value distribution for the position 8 in the byte array
The value distribution for the positions 9-15 in the byte array:
The value distribution for the positions 9-15 in the byte array

For byte positions 0-6 and 9-15 the distribution of values seems to be even, but for byte position 7 and 8 the distribution is fairly limited.

That is, for the guid (with the beginning of the byte positions below, note strange ordering)

{1369ea05-b9f9-408b-ac7c-7ebd0f35d562}
                         1 1 1 1 1 1
 3 2 1 0  5 4  7 6  8 9  0 1 2 3 4 5

The position 7 can take the values from 64 (0x40) to 79 (0x4F).
The position 8 can take the values from 128 (0x80) to 191 (0xBF).
The rest of the bytes are evenly distributed.

Note: The tests was run on .NET4 on a 32 bit Windows 7 machine.

Lesson: don't assume stuff, test.

Answer: To use the .NET Guids for calculating your load balancing, you can use any part except the positions marked 7 and 8 in the Guid above.

Question: Does anybody know WHY the distribution is not evenly spread?

失眠症患者 2024-09-21 19:21:04

您可以创建一个 Web 服务来在服务器端生成哈希值,使用您想要的任何语言。在客户端,一个简单的 Web 服务调用就可以解决问题。

you can create a web service to generate the hash value on the server side, use whatever language you want. on client side, a simple web service call will do the trick.

我不吻晚风 2024-09-21 19:21:04

Reflector 说 .NET Guid.GetHashCode() 是这样实现的

public override int GetHashCode()
{
    return ((this._a ^ ((this._b << 0x10) | ((ushort) this._c))) ^ ((this._f << 0x18) | this._k));
}

_a、_b、_c 和 _f 在构造函数中定义,采用 byte[16] 数组

public Guid(byte[] b)
{
    if (b == null)
    {
        throw new ArgumentNullException("b");
    }
    if (b.Length != 0x10)
    {
        throw new ArgumentException(Environment.GetResourceString("Arg_GuidArrayCtor", new object[] { "16" }));
    }
    this._a = (((b[3] << 0x18) | (b[2] << 0x10)) | (b[1] << 8)) | b[0];
    this._b = (short) ((b[5] << 8) | b[4]);
    this._c = (short) ((b[7] << 8) | b[6]);
    this._d = b[8];
    this._e = b[9];
    this._f = b[10];
    this._g = b[11];
    this._h = b[12];
    this._i = b[13];
    this._j = b[14];
    this._k = b[15];
}

Reflector says the .NET Guid.GetHashCode() is implemented like this

public override int GetHashCode()
{
    return ((this._a ^ ((this._b << 0x10) | ((ushort) this._c))) ^ ((this._f << 0x18) | this._k));
}

_a, _b, _c and _f is defined in the constructor taking a byte[16] array

public Guid(byte[] b)
{
    if (b == null)
    {
        throw new ArgumentNullException("b");
    }
    if (b.Length != 0x10)
    {
        throw new ArgumentException(Environment.GetResourceString("Arg_GuidArrayCtor", new object[] { "16" }));
    }
    this._a = (((b[3] << 0x18) | (b[2] << 0x10)) | (b[1] << 8)) | b[0];
    this._b = (short) ((b[5] << 8) | b[4]);
    this._c = (short) ((b[7] << 8) | b[6]);
    this._d = b[8];
    this._e = b[9];
    this._f = b[10];
    this._g = b[11];
    this._h = b[12];
    this._i = b[13];
    this._j = b[14];
    this._k = b[15];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文