В мире программирования генерация случайных чисел — это частая задача, особенно в таких областях, как криптография, игровая логика и статистическое моделирование. Однако не все случайные числа одинаково полезны — в некоторых случаях требуется криптографически безопасная генерация (CSPRNG), которая гарантирует защиту от предсказуемости.
В этой статье мы рассмотрим:
- Почему стандартный randomize в Delphi и Free Pascal не всегда подходит
- Как использовать /dev/urandom в Linux (для ядер версии 4.8+)
- Альтернативные методы для Windows и macOS
- Примеры кода на Object Pascal
Почему Randomize не всегда достаточно
Стандартная функция Randomize в Delphi и Free Pascal инициализирует генератор псевдослучайных чисел (PRNG) с использованием системного времени:
procedure Randomize;
begin
RandSeed := GetTickCount;
end;
Хотя этого достаточно для многих задач (например, генерации случайных карт в играх), такой подход не подходит для криптографии, так как:
1. Предсказуемость: Если злоумышленник знает временной интервал запуска программы, он может воспроизвести последовательность.
2. Ограниченная энтропия: GetTickCount возвращает миллисекунды с момента запуска системы, что дает около 58 миллионов возможных начальных значений в день.
Когда можно использовать Randomize?
В играх (например, процедурная генерация уровней).
В тестах, где важна повторяемость (если RandSeed фиксирован).
В задачах, где безопасность не критична.
Криптографически безопасные генераторы (CSPRNG)
1. /dev/urandom в Linux (ядра 4.8+)
Начиная с версии 4.8, ядро Linux гарантирует, что /dev/urandom безопасен для криптографии, так как энтропия накапливается еще во время загрузки системы.
Пример чтения случайных данных:
function LinuxCSPRNG(var Buffer; Bytes: LongWord): Boolean;
var
f: File;
begin
Result := False;
Assign(f, '/dev/urandom');
Reset(f, 1);
try
BlockRead(f, Buffer, Bytes);
Result := True;
finally
Close(f);
end;
end;
Преимущества:
- Не требует вызова Randomize.
- Очень быстрый (в среднем ~12 мкс на байт при блочном чтении).
- Доступен на всех современных дистрибутивах Linux.
2. Windows: BCrypt API
В Windows рекомендуется использовать API BCrypt вместо устаревшего CryptGenRandom.
Пример кода:
function WinCSPRNG(var Buffer; Bytes: LongWord): Boolean;
var
hAlgorithm: BCRYPT_ALG_HANDLE;
begin
Result := False;
if BCryptOpenAlgorithmProvider(@hAlgorithm, BCRYPT_RNG_ALGORITHM, nil, 0) = STATUS_SUCCESS then
try
if BCryptGenRandom(hAlgorithm, @Buffer, Bytes, 0) = STATUS_SUCCESS then
Result := True;
finally
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
end;
end;
3. macOS
На macOS также можно использовать /dev/urandom, так как он работает аналогично Linux.
Альтернативные генераторы
Если вам не нужна криптографическая стойкость, но важна скорость, можно использовать XorShift:
var
x, y, z, w: Cardinal;
procedure XorShiftRandomize;
begin
x := Random(MaxInt);
y := Random(MaxInt);
z := Random(MaxInt);
w := Random(MaxInt);
end;
function XorShift: Single;
var
t: Cardinal;
begin
t := x;
t := t xor (t shl 11);
t := t xor (t shr 8);
x := y;
y := z;
z := w;
w := w xor (w shr 19);
w := w xor t;
Result := w / MaxInt / 2;
end;
Плюсы:
- В 3 раза быстрее стандартного Random на 64-битных системах.
- Подходит для игр и симуляций.
Минусы:
- Не криптографически безопасен.
Вывод
Для криптографии используйте: - /dev/urandom в Linux (если ядро ≥ 4.8). - BCryptGenRandom в Windows.
Для игр и симуляций подойдут: - Randomize + стандартный Random. - XorShift для большей скорости.
Пример универсальной функции для CSPRNG:
function SystemRandom(var Buffer; Bytes: LongWord): Boolean;
begin
{$IFDEF WINDOWS}
Result := WinCSPRNG(Buffer, Bytes);
{$ELSE}
Result := UnixCSPRNG(Buffer, Bytes); // Работает на Linux и macOS
{$ENDIF}
end;
Таким образом, выбор метода зависит от задачи. Если нужна безопасность — используйте системные CSPRNG, если важна скорость — оптимизированные алгоритмы вроде XorShift.
Статья описывает методы генерации криптографически-безопасных случайных данных в Delphi и Free Pascal, включая стандартные и альтернативные алгоритмы для разных операционных систем.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.