Правильный генератор,
правильный язык.
Не все генераторы паролей одинаковы — и язык, на котором написано ваше хранилище, не является второстепенной инженерной деталью. Разбираем энтропию, режимы генерации и то, почему Rust все чаще оказывается под капотом.
Когда менеджер “генерирует надежный пароль”, возникают два вопроса: действительно ли он непредсказуем (качество случайности), и что происходит с ним в памяти после отображения? Первый вопрос относится к режимам генерации. Второй — к языку, на котором работает приложение. В этой статье рассматриваются оба аспекта.
01 / ОСНОВЫЭнтропия: единственная метрика, которая имеет значение
Надежность пароля измеряется не ощущаемой “сложностью”, а его энтропией: числом bits неопределенности для атакующего. Чем больше возможных комбинаций, тем резче растет стоимость brute-force-атаки. Пароль из 16 символов, выбранных из полного ASCII-алфавита, достигает примерно 100 bits — уровня “очень надежный”.
Критически важный момент, о котором часто забывают: энтропия имеет смысл только если источником случайности является CSPRNG (криптографически стойкий псевдослучайный генератор). Обычный Math.random() предсказуем и обесценивает все остальное. Хорошие реализации получают энтропию от операционной системы: /dev/urandom или getrandom(2) в Unix, CNG в Windows.
02 / РЕЖИМЫЧетыре семейства генераторов
Хороший менеджер предлагает не “один” генератор, а несколько режимов под разные сценарии. Правило простое: запоминаемость оплачивается длиной. Вот четыре семейства — от самого плотного к самому удобному для человека.
Полностью случайный
j7$kQ!mP2#xR9vL@Passphrase (Diceware / EFF)
Granite-Bicycle-Phantom-Violet-9Запоминаемый / произносимый
Crimson7!Falcon$ReefЦифровой PIN
8392 4471Правильный рефлекс: подбирать энтропию под сценарий
Для веб-аккаунта, защищенного страницей входа с ограничением частоты, атакующий ограничен несколькими сотнями попыток в секунду: даже 50 bits выдерживают геологические масштабы времени. Избыточная энтропия имеет смысл прежде всего для офлайн-секретов (ключ шифрования, seed crypto-кошелька), где атаку можно массово распараллелить. Для таких секретов очень высокой ценности бросание настоящих физических костей (Diceware в буквальном смысле) остается предельным вариантом: оно устраняет любую зависимость от качества CSPRNG или от скомпрометированного браузера.
03 / ПОД КАПОТОМПочему Rust меняет правила игры
Сгенерировать хороший пароль — это половина задачи. Вторая половина: не оставить его лежать где попало. После отображения или расшифровки пароль живет в оперативной памяти — и именно здесь язык приложения становится решающим.
Microsoft сообщала, что 70 % уязвимостей безопасности, с которыми она сталкивается, являются ошибками памяти (buffer overflow, use-after-free и т. д.). Google наблюдала ту же пропорцию в Chrome и Android. Именно эти классы ошибок Rust устраняет на этапе компиляции через модель владения (ownership) и заимствования (borrowing), без garbage collector.
Цифры Google показательны: уязвимости памяти в Android снизились с 223 в 2019 году до менее чем 50 в 2024, впервые опустившись ниже 20 % от общего числа. Новый код Rust показывает плотность ошибок памяти до 1000× ниже, чем исторический код C/C++, а также дает в 4× меньше rollback и на 25 % меньше времени review.
1. Безопасность памяти без garbage collector. Такие языки, как Java или Python, memory-safe, но их garbage collector освобождает память недетерминированно: секрет может сохраняться в ней неопределенно долго, оставаясь доступным для memory dump или cold-boot-атаки. Rust освобождает память детерминированно, как только данные больше не используются.
2. Явное стирание с zeroize. Rust не гарантирует, что освобожденная память будет перезаписана. Crate zeroize закрывает этот пробел: оборачивая секрет в Zeroizing, мы гарантируем перезапись нулями — через volatile write, которую компилятор не может оптимизировать, — ровно в момент выхода из области видимости.
3. Система типов, заставляющая правильно использовать crypto. Строгая система типов Rust позволяет ограничить, как чувствительные данные могут использоваться — и сколько раз. Например, можно смоделировать ключ, который разрешено применить только один раз; компилятор отклонит любое повторное использование.
Автоматическое стирание в памятиuse zeroize::Zeroizing;
fn unlock_vault(master: &str) {
let dek = Zeroizing::new(derive_key(master));
// ... déchiffrement du coffre ...
} // `dek` est écrasé par des zéros ici, automatiquementУЯЗВИМОСТИ ПАМЯТИ — ANDROID (% ОТ ОБЩЕГО ЧИСЛА)
ВНЕДРЕНИЕ RUST
Техническая честность: Rust не волшебная палочка
Код unsafe и сторонние зависимости остаются поверхностью атаки — Google, например, исправила уязвимость (CVE-2025-48530) в блоке unsafe Rust-парсера еще до вывода в production. Безопасность памяти — это слой, а не самоцель: она сочетается с defense in depth (надежный KDF вроде Argon2id, zero-knowledge-архитектура, автоблокировка, MFA).
Язык с garbage collector
- Недетерминированное освобождение памяти
- Секреты остаются в памяти неизвестное время
- Явное стирание затруднено или невозможно
- Подверженность dumps & cold-boot
Rust
- Детерминированное освобождение (ownership)
- Немедленное стирание через zeroize
- Нет buffer overflow и use-after-free
- Ошибки crypto ловятся на этапе компиляции
04 / ЧТО ЗАПОМНИТЬЧего требовать от менеджера
При выборе — или оценке — менеджера паролей стоит задать четыре конкретных вопроса:
Checklist
- 1. Использует ли генератор системный CSPRNG и показывает ли энтропию в bits?
- 2. Есть ли режим passphrase Diceware/EFF для мастер-пароля?
- 3. Выполняется ли генерация локально (client-side), без передачи через сервер?
- 4. Написано ли чувствительное ядро на memory-safe языке с явным стиранием секретов?
Безопасная генерация. Хранилище, рассчитанное на долгий срок.
Пароли с высокой энтропией, запоминаемые passphrases и ядро, созданное с учетом безопасности памяти.
Узнать о нашем подходе