Некоторое время назад я работал над веб-приложением, где пользователи могли покупать билеты. Из-за того, как работали наши клиентские процессы, то, что вы получили в результате вашей покупки, было 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 миллионов лет).