Как стать автором
Обновить
1294.25
OTUS
Цифровые навыки от ведущих экспертов

Генерация надёжных псевдослучайных чисел с ChaCha8Rand в Go

Время на прочтение4 мин
Количество просмотров1.7K

Привет, Хабр!

В версии Go 1.22 пакет math/rand/v2претерпел значительные изменения, а в частности - переход на ChaCha8Rand. Этот новый генератор представляет собой модификацию широко известного и проверенного временем шифра ChaCha8, который используется в протоколах TLS и SSH.

Немного про сам генератор

ChaCha8Rand основывается на алгоритме ChaCha8, который сам по себе является облегченной версией шифра ChaCha20. ChaCha8 выполняет восемь раундов перестановок и замен ключа и блока данных, что гарантирует высокий уровень энтропии и защиту от различных криптографических атак.

ChaCha8Rand принимает 32-байтный ключ, его называют семенем, который используется в качестве начальной точки для генерации случайных чисел. Ключ устанавливает начальное состояние алгоритма, которое затем преобразуется в псевдослучайное состояние для генерации последовательности чисел.

ChaCha8Rand генерирует 64-битные псевдослучайные числа путем прямого вызова алгоритма ChaCha8. Внутри он инициализирует ChaCha8 с заданным ключом и использует блоки данных, которые алгоритм создает при каждом запросе нового случайного значения. Процесс итеративный: каждый вызов генератора ChaCha8Rand изменяет внутреннее состояние и формирует новое случайное число.

ChaCha8Rand поддерживает функции сериализации и десериализации состояния, что позволяет сохранять и восстанавливать текущее состояние генератора.

Реализация ChaCha8Rand в Go

В пакете math/rand/v2, ChaCha8 представлен структурой ChaCha8, которая хранит внутреннее состояние генератора и предоставляет методы для управления им. Состояние инициализируется 32-байтным семенем, передаваемым в функцию NewChaCha8, а сам процесс генерации числа осуществляется методом Uint64(), который возвращает следующее 64-битное псевдослучайное число.

Основные функции и методы, которые используют ChaCha8Rand, включают:

  1. IntN и Int64N: функции генерируют псевдослучайное целое число в заданном диапазоне. Например, IntN(n int) int возвращает случайное число от 0 до n-1. Они обеспечивают равномерное распределение значений в указанном диапазоне.

  2. Float64: генерирует псевдослучайное число с плавающей точкой между 0.0 и 1.0, не включая 1.0.

  3. Perm: создаёт случайную перестановку чисел от 0 до n-1.

Кроме того, в math/rand/v2 реализованы новые методы MarshalBinary и UnmarshalBinary для объектов, которые реализуют интерфейс Source, включая ChaCha8.

Генератор создается путем вызова NewChaCha8 с 32-байтным массивом начальных значений. Если массив не заполнен случайными данными, генератор не сможет обеспечить криптографическую стойкость.

После инициализации генератора метод Uint64() возвращает следующее псевдослучайное 64-битное число на основе внутреннего состояния. Этот метод использует ChaCha8 для выполнения восемь раундов перестановок и замен.

Примеры

Инициализация генератора и генерация чисел:

package main

import (
    "fmt"
    "math/rand/v2"
)

func main() {
    // создаем 32-байтное семя для инициализации генератора
    seed := [32]byte{'s', 'o', 'm', 'e', 'k', 'e', 'y', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'a', 'b', 'c', 'd', 'e', 'f'}
    
    // инициализируем новый генератор ChaCha8
    generator := rand.NewChaCha8(seed)

    // получаем несколько случайных чисел
    fmt.Println(generator.Uint64())
    fmt.Println(generator.Uint64())
}

Генерация криптографически безопасного случайного числа:

package main

import (
    "fmt"
    "math/rand/v2"
)

func main() {
    seed := [32]byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v'}
    generator := rand.NewChaCha8(seed)
    fmt.Println("Secure random number:", generator.Uint64())
}

Генерация случайной строки для токенов или сессий:

package main

import (
    "fmt"
    "math/rand/v2"
)

func randomBytes(n int) []byte {
    seed := [32]byte{'s', 'e', 'e', 'd', 'p', 'h', 'r', 'a', 's', 'e', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'}
    generator := rand.NewChaCha8(seed)
    b := make([]byte, n)
    for i := range b {
        b[i] = byte(generator.Uint32() % 256)
    }
    return b
}

func main() {
    fmt.Println("Random session token:", randomBytes(16))
}

Использование в шифровании:

package main

import (
    "crypto/cipher"
    "fmt"
    "golang.org/x/crypto/chacha20"
    "math/rand/v2"
)

func main() {
    seed := [32]byte{'k', 'e', 'y', 'p', 'h', 'r', 'a', 's', 'e', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'}
    generator := rand.NewChaCha8(seed)
    nonce := [12]byte{} // нормально было бы использовать случайные значения
    key := [32]byte{}
    for i := range key {
        key[i] = byte(generator.Uint32() % 256)
    }

    cipher, err := chacha20.NewUnauthenticatedCipher(key[:], nonce[:])
    if err != nil {
        panic(err)
    }

    plaintext := []byte("This is a secret message.")
    ciphertext := make([]byte, len(plaintext))
    cipher.XORKeyStream(ciphertext, plaintext)

    fmt.Println("Encrypted:", ciphertext)
    fmt.Println("Decrypted message:")
    cipher.XORKeyStream(ciphertext, ciphertext) // расшифровка производится тем же способом
    fmt.Println(string(ciphertext))
}

Сравнение ChaCha8Rand с другими генераторами

Составили табличку:

Критерий

ChaCha8Rand

PCG

Rand (Go)

Криптографическая безопасность

Высокая (256 бит)

Подходит не для всех задач и в целом низкая

Низкая

Производительность

Высокая на

Высокая, особенно в микробенчмарках

Средняя

Универсальность

Подходит для криптографических приложений

Ограниченное использование в криптографии

Не рекомендуется для криптографических приложений

Методы ускорения

Не требуется

Доступны методы "jump ahead" для быстрого пропуска значений

Отсутствуют

Размер состояния

512 бит

64 или 128 бит

Зависит от реализации


Ожидается, что сообщество Golang предложит дополнительные стратегии использования этого инструмента, будем следить за новостями!

Больше про языки программирования эксперты OTUS рассказывают в рамках практических онлайн-курсов. С полным каталогом курсов можно ознакомиться по ссылке.

Теги:
Хабы:
Всего голосов 10: ↑9 и ↓1+12
Комментарии7

Публикации

Информация

Сайт
otus.ru
Дата регистрации
Дата основания
Численность
101–200 человек
Местоположение
Россия
Представитель
OTUS