Как создать детерминированные гуиды

В нашем приложении мы создаем XML-файлы с атрибутом, который имеет значение Гуида. Это значение должно было быть последовательным между обновлениями файла. Таким образом, даже если все остальное в изменениях файла, значение гуида для атрибута должно остаться тем же.

Одно очевидное решение состояло в том, чтобы создать статический словарь с именем файла и Гуидами, которые будут использоваться для них. Затем каждый раз, когда мы генерируем файл, мы ищем словарь для имени файла и используем соответствующий гуид. Но это не выполнимо, потому что мы могли бы масштабироваться к 100's файлов и не хотели вести большой список гуидов.

Таким образом, другой подход должен был сделать Гуид тем же на основе пути файла. Так как наши пути к файлам и структура каталога приложения уникальны, Гуид должен быть уникальным для того пути. Так каждый раз, когда мы выполняем обновление, файл получает тот же гуид на основе своего пути. Я нашел один прохладный способ генерировать такие 'Детерминированные Гуиды' (Спасибо Elton Stoneman). Это в основном делает это:

private Guid GetDeterministicGuid(string input) 

{ 

//use MD5 hash to get a 16-byte hash of the string: 

MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider(); 

byte[] inputBytes = Encoding.Default.GetBytes(input); 

byte[] hashBytes = provider.ComputeHash(inputBytes); 

//generate a guid from the hash: 

Guid hashGuid = new Guid(hashBytes); 

return hashGuid; 

} 

Так, учитывая строку, Гуид всегда будет тем же.

Есть ли какие-либо другие подходы или рекомендуемые пути к выполнению этого? Каковы профессионалы или недостатки того метода?

96
задан Charlie Salts 15 April 2010 в 01:48
поделиться

3 ответа

MD5 слабый, я считаю, что вы можете сделать то же самое с SHA-1 и получить лучшие результаты.

Кстати, это личное мнение, но использование хэша md5 в качестве GUID не делает его хорошим GUID. GUID по самой своей природе недетерминированы. это похоже на чит. Почему бы просто не назвать вещи своими именами и просто сказать, что это строковый хэш ввода. вы можете сделать это, используя эту строку, а не новую строку guid:

string stringHash = BitConverter.ToString(hashBytes)
5
ответ дан 24 November 2019 в 05:37
поделиться

Вам необходимо различать экземпляры класса Guid и идентификаторы, которые являются глобально уникальными. «Детерминированный гид» на самом деле является хешем (о чем свидетельствует ваш звонок в provider.ComputeHash ). Хэши имеют гораздо более высокий шанс коллизий (две разные строки создают один и тот же хеш), чем Guid, созданный с помощью Guid.NewGuid .

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

Попытка втиснуть что-то, что не является чистым GUID, в тип данных GUID может привести к проблемам с обслуживанием в будущем ...

3
ответ дан 24 November 2019 в 05:37
поделиться

Как упоминает Роб, ваш метод не генерирует UUID, он генерирует хэш, который выглядит как UUID.

RFC 4122 по UUID специально допускает детерминированные (основанные на имени) UUID - версии 3 и 5 используют md5 и SHA1 (соответственно).Большинство людей, вероятно, знакомы с версией 4, которая случайна. Википедия дает хороший обзор версий. (Обратите внимание, что использование слова «версия» здесь, кажется, описывает «тип» UUID - версия 5 не заменяет версию 4).

Кажется, существует несколько библиотек для генерации UUID версии 3/5, включая модуль uuid python , boost.uuid (C ++) и OSSP UUID . (Я не искал .net)

18
ответ дан 24 November 2019 в 05:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: