Как я могу сгенерировать GUID для строки? - PullRequest
39 голосов
/ 03 февраля 2010

У меня проблема с генерацией GUID для строки - например:

Guid g = New Guid("Mehar");

Как я могу вычислить GUID для "Mehar"? Я получаю исключение.

Ответы [ 9 ]

96 голосов
/ 06 июня 2011

Довольно старая ветка, но мы решили эту проблему:

Поскольку Guid из .NET Framework имеют произвольные 16 байтов или, соответственно, 128 битов, вы можете вычислить Guid из произвольных строк, применив к строке любую хэш-функцию, которая генерирует 16-байтовый хэш, и затем передает результат в конструктор Guid.

Мы решили использовать хеш-функцию MD5, и пример кода может выглядеть следующим образом:

string input = "asdfasdf";
using (MD5 md5 = MD5.Create())
{
    byte[] hash = md5.ComputeHash(Encoding.Default.GetBytes(input));
    Guid result = new Guid(hash);
}

Обратите внимание, что у этого поколения Guid есть несколько недостатков, поскольку зависит от качества хеш-функции! Если ваша хеш-функция генерирует равные хеш-значения для большого количества используемой строки, это повлияет поведение вашего программного обеспечения.

Вот список самых популярных хеш-функций, которые генерируют 128-битный дайджест:

  • RIPEMD (вероятность столкновения: 2 ^ 18)
  • MD4 (вероятность столкновения: точно)
  • MD5 (вероятность столкновения: 2 ^ 20,96)

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

  • SHA-1
  • SHA-2
  • SHA-3

Сегодня (август 2013 г.) 160-битный хэш SHA1 можно считать хорошим выбором.

18 голосов
/ 03 февраля 2010

Я вполне уверен, что вы спутали System.Guid с желанием хэша (скажем, SHA-256 ) данной строки.

Обратите внимание, что при выборе криптографически-безопасный алгоритм хеширования, MD5, SHA0 и SHA1 все обычно считаются мертвыми .SHA2 и выше все еще можно использовать.

5 голосов
/ 03 февраля 2010

То, что вы ищете, вероятно, генерирует UUID версии 3 или версии 5, которые являются UUID на основе имени. (рекомендуется версия 5). Я не думаю, что .NET Framework имеет встроенную поддержку для этого. Смотри http://en.wikipedia.org/wiki/Universally_Unique_Identifier

Я сделал несколько поисков в Google, чтобы посмотреть, смогу ли я найти что-нибудь в Win32 API, но ничего не вышло. Тем не менее, я уверен, что .NET Framework имеет некоторую реализацию, скрытую где-то, потому что, насколько я знаю, при создании COM-объекта в .NET, и вы не предоставляете явный GUID, то .NET Framework генерирует имя на основе UUID для создания четко определенных ClassID и InterfaceID, то есть UUID, которые не меняются каждый раз, когда вы перекомпилируете (например, VB6). Но это, вероятно, скрыто, поэтому я думаю, вам нужно реализовать алгоритм самостоятельно. К счастью, .NET предоставляет алгоритм MD5 и SHA1, поэтому я не думаю, что реализация UUID версии3 и версии5 будет слишком сложной.

4 голосов
/ 06 августа 2013

Как правило, существует несколько способов сделать универсально уникальный идентификатор (UUID RFC 4122 , он же GUID).Мы могли бы позаимствовать эти четыре из Python и сделать в C # что-то похожее:

uuid.uuid1([node[, clock_seq]])

Создать UUID из идентификатора хоста, порядкового номера и текущего времени.Если узел не указан, getnode () используется для получения аппаратного адреса.Если указано clock_seq, оно используется в качестве порядкового номера;в противном случае выбирается случайный 14-битный порядковый номер.

uuid.uuid3(namespace, name)

Генерация UUID на основе хеша MD5 идентификатора пространства имен (который является UUID)и имя (которое является строкой).

uuid.uuid4()

Создать случайный UUID.

uuid.uuid5(namespace, name)

Создание UUID на основе хэша SHA-1 идентификатора пространства имен (который является UUID) и имени (которое является строкой).

Так что если вам нужноИдентификатор строки как объекта, а не идентификатор значения. Вы должны изменить свой частный UUID с помощью заданной строки. Ваш частный UUID сгенерировать один раз, используя uuid1, а затем использовать его как пространство имен для uuid3 или uuid5.

Эти варианты и версии описаны в Википедии Universally_unique_identifier # Variants_and_versions

4 голосов
/ 03 февраля 2010

Вы не можете использовать GUID таким образом. конструктор Guid ожидает допустимое строковое представление Guid.

То, что вы ищете, называется хэш-функцией. (например: MD5 )

3 голосов
/ 03 февраля 2010

Я думаю, что вы неправильно понимаете, что такое на самом деле Guid. В Guid нет представления строки, такой как "Mehar".

Причина перегрузки new Guid(String s) заключается в том, что вы можете создать guid из типичного строкового представления, такого как "00000000-0000-0000-0000-000000000000".

См. Вики-статью для получения дополнительной информации о том, что такое Guid.

http://en.wikipedia.org/wiki/Globally_Unique_Identifier

2 голосов
/ 19 февраля 2015

Если целью операции является создание UUID (Guid) из какого-либо хеша строки (MD5, SHA-1 и т. Д.), Я нашел этот очень похожий вопрос с таким замечательным ответом:

https://stackoverflow.com/a/5657517/430885

Он имеет ссылку на фрагмент github-кода, основанный на RFC 4122 §4.3, который создаст Guid из строки и пространства имен (которое вы можете выбрать для себя, чтобы гарантировать защиту от столкновений из внешних сред).

Прямая ссылка на фрагмент: https://github.com/LogosBible/Logos.Utility/blob/master/src/Logos.Utility/GuidUtility.cs

0 голосов
/ 12 января 2017

Вот мой собственный подход, я намеренно использую String для шестнадцатеричного дампа, если это возможно - визуально можно увидеть, по крайней мере, насколько велика строка, и, если необходимо, - декодировать с помощью некоторого онлайн-шестнадцатеричного конвертера. Но если строка слишком длинная (более 16 байт) - используйте sha-1 для вычисления хеша и создания из него guid.

/// <summary>
/// Generates Guid based on String. Key assumption for this algorithm is that name is unique (across where it it's being used)
/// and if name byte length is less than 16 - it will be fetched directly into guid, if over 16 bytes - then we compute sha-1
/// hash from string and then pass it to guid.
/// </summary>
/// <param name="name">Unique name which is unique across where this guid will be used.</param>
/// <returns>For example "{706C7567-696E-7300-0000-000000000000}" for "plugins"</returns>
static public String GenerateGuid(String name)
{
    byte[] buf = Encoding.UTF8.GetBytes(name);
    byte[] guid = new byte[16];
    if (buf.Length < 16)
    {
        Array.Copy(buf, guid, buf.Length);
    }
    else
    {
        using (SHA1 sha1 = SHA1.Create())
        {
            byte[] hash = sha1.ComputeHash(buf);
            // Hash is 20 bytes, but we need 16. We loose some of "uniqueness", but I doubt it will be fatal
            Array.Copy(hash, guid, 16);
        }
    }

    // Don't use Guid constructor, it tends to swap bytes. We want to preserve original string as hex dump.
    String guidS = "{" + String.Format("{0:X2}{1:X2}{2:X2}{3:X2}-{4:X2}{5:X2}-{6:X2}{7:X2}-{8:X2}{9:X2}-{10:X2}{11:X2}{12:X2}{13:X2}{14:X2}{15:X2}", 
        guid[0], guid[1], guid[2], guid[3], guid[4], guid[5], guid[6], guid[7], guid[8], guid[9], guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]) + "}";

    return guidS;
}
0 голосов
/ 03 февраля 2010

Направляющие являются случайными, им не присваиваются никакие строки или другие значения.

Если вам нужна такая ссылка, сохраните направляющие в словаре и проверьте сначала существующий, прежде чем создавать новый.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...