Некоторое время назад я работал над веб-приложением, где пользователи могли покупать билеты. Из-за того, как работали наши клиентские процессы, то, что вы получили в результате вашей покупки, было URL с номером билета в нем.
Это были билеты на покупку недвижимости на Ближнем Востоке, и каждый билет стоил около 3 000 000 долларов. Четкое изложение последовательных целых чисел было бы плохой идеей. Мы использовали GUID, поскольку они в основном неопознаны, но мой вопрос: достаточно ли они защищены?
Как я понимаю, GUID.NET производит полностью псевдослучайные (за исключением нескольких не изменяющихся битов). Однако я не знаю, какой алгоритм используется для их создания.
Документация MSDN сообщает нам, что Random работает быстро и небезопасно, а RNGCryptoServiceProvider работает медленно и безопасно. То есть разумно предположить, что кто-то может приложить достаточно усилий, чтобы предсказать результат Random, но не RNGCryptoServiceProvider.
Если бы вы видели достаточно длинную последовательность GUID, можно было бы прогнозировать фьючерсы? Если да, то сколько вам нужно увидеть?
[В нашем конкретном случае позже были проверки физической безопасности - вы должны были представить паспорт, который вы использовали для покупки вашего билета, - поэтому было бы не так уж плохо, если бы кто-то догадался о другом GUID, t потеть его в то время. Удобство использования GUID в качестве ключа базы данных помогло использовать полезный тип данных.]
Edit:
Таким образом, ответ "недостаточно".
Используя 0xA3 ниже, и следуя ссылкам из question, с которыми он связан, следующий код будет генерировать криптографически случайный идентификатор GUID, действительный по Раздел 4.4 RFC 4122:
static Guid MakeCryptoGuid()
{
// Get 16 cryptographically random bytes
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] data = new byte[16];
rng.GetBytes(data);
// Mark it as a version 4 GUID
data[7] = (byte)((data[7] | (byte)0x40) & (byte)0x4f);
data[8] = (byte)((data[8] | (byte)0x80) & (byte)0xbf);
return new Guid(data);
}
Это создает GUID гораздо медленнее, чем Guid.NewGuid(), но с 122 бит "очень случайных" данных они безопасно непредсказуемы.
Конечно, любой криптографически случайный текст сделал бы для номера билета, но GUID очень удобны.: -)
Как и в других версиях 4 GUID, нет абсолютной гарантии уникальности, но шансы впечатляют. Если у вас меньше 326 915 130 309 135 855 (т.е. sqrt (-2 * 2 ^ 122 * ln (0.99))) GUID в игре одновременно, вы может быть более чем на 99% уверен, что нет столкновений. Иначе говоря: если мое приложение будет иметь ошибки переполнения по всему месту, если у вас больше чем int.MaxValue почти ничего, вы можете быть более 99.999999999999999999% уверенности в отсутствии столкновений (т.е. e ^ - (((2 ^ 31-1) ^ 2)/(2 * 2 ^ 122))). Это примерно в тысячу раз больше уверенности, чем вы можете сказать, что метеорит не уничтожит большую часть жизни на Земле в течение одной секунды от приложения, идущего вживую (т.е. один на 100 миллионов лет).