Насколько надежно угадываются GUID?
Некоторое время назад я работал над веб-приложением, где пользователи могли покупать билеты. Благодаря тому, как работали процессы нашего клиента, в результате вашей покупки вы получили URL с номером билета.
Это были билеты на покупку недвижимости на Ближнем Востоке, и каждый билет мог стоить около 3 000 000 долларов. Очевидно, что выводить последовательные целые числа было бы плохой идеей. Мы использовали GUID, так как они в основном неосуществимы, но мой вопрос: достаточно ли они безопасны?
Насколько я понимаю, GUID, которые создает .NET, полностью псевдослучайны (за исключением нескольких неизменяемых битов). Однако я не знаю, какой алгоритм используется для их генерации.
Документация MSDN говорит нам, чтоRandom
быстрый и ненадежный, иRNGCryptoServiceProvider
медленный и безопасный. То есть разумно предположить, что кто-то может приложить достаточно усилий, чтобы предсказать исходRandom
, но не изRNGCryptoServiceProvider
.
Если бы вы увидели достаточно длинную последовательность GUID, можно ли было бы прогнозировать фьючерсные? Если так, сколько вам нужно увидеть?
[В нашем конкретном случае позже были проведены проверки физической безопасности - вам нужно было предъявить паспорт, который вы использовали для покупки билета, - чтобы этого не былотоже плохо, если кто-то угадал чужой GUID, поэтому мы не потели в то время. Удобство использования GUID в качестве ключа базы данных сделало его полезным для использования.]
Редактировать:
Так что ответ «недостаточно».
С помощью0xA3ответ ниже, и следующие ссылки отвопрос он связался с, следующий код будет генерировать криптографически случайный 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 довольно удобны. :-)
Как и в случае других GUID версии 4, нет абсолютной гарантии уникальности, но шансы впечатляют. Пока у вас есть меньше, чем 326 915 130 069 135 865 (т.е.SQRT (-2 * 2 ^ 122 * Ln (0,99))) GUID в игре одновременно, вы можете быть более чем на 99% уверены, что нет столкновений. Другими словами, если у вас в приложении возникнут ошибки переполнения, если у вас болееint.MaxValue
практически ничего, вы можете быть более чем на 99,99999999999999999% уверенными в отсутствии столкновений (т.е.е ^ - (((2 ^ 31-1) ^ 2) / (2 * 2 ^ 122))). Это примерно в тысячу раз увереннее, чем вы можете предположить, что метеорит не уничтожит большую часть жизни на Земле в течение одной секунды после запуска приложения (т.е.один на 100 миллионов лет).