Одинаковые хеши для guid в C # и javascript - PullRequest
2 голосов
/ 18 августа 2010

У меня есть проблема, когда мне нужно иметь возможность генерировать идентичные равномерно распределенные числовые хеши для GUID как в JavaScript, так и в C #.Я предполагаю, что это помешало бы мне использовать Guid.GetHashCode() в C #, так как я не могу воспроизвести поведение в JS без обратного инжиниринга C #.

Есть ли быстрый способ получения хэшейиз направляющих / строк в JS?Все ли цифры строки равномерно распределены в сгенерированном .NET GUID?Должен ли я просто разыграть / преобразовать висячие символы в int?

Ответы [ 3 ]

5 голосов
/ 19 августа 2010

Байты, по-видимому, распределены неравномерно.

Я собрал некоторый код для выборки руководств .NET и построил график распределения:

Прежде всего, тестовый код, это создает миллионНаправляет и подсчитывает количество различных значений для каждого байта в байтовом массиве.Он выводит все это в матрицу, которую я строю в 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 в байтовом массиве: The value distribution for the positions 0-6 in the byte array
Распределение значений для позиции 7 в байтовом массиве:
The value distribution for the position 7 in the byte array
Распределение значений для позиции 8 в байтовом массиве:
The value distribution for the position 8 in the byte array
Распределение значений для позиций 9-15 в байтовом массиве: The value distribution for the positions 9-15 in the byte array

Для байтовых позиций 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).
Остальные байты распределены равномерно.

Примечание: Тесты проводились в .NET4 на 32-разрядной машине с Windows 7.

Урок: не принимайте во внимание, тестируйте.

Ответ: Чтобы использовать .NET Guids для расчета балансировки нагрузки, вы можете использовать любую деталь, кроме позиций, отмеченных 7 и 8 в Руководстве выше.

Вопрос: Кто-нибудь знает, ПОЧЕМУ распределение не распределяется равномерно?

2 голосов
/ 18 августа 2010

вы можете создать веб-сервис для генерации хеш-значения на стороне сервера, используя любой язык, который вы хотите.на стороне клиента простой вызов веб-службы сделает свое дело.

1 голос
/ 18 августа 2010

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 определены в конструкторе, принимающем массив байтов [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];
}
...