Релиз cryptsetup 2.0 в декабре прошлого года прошел тихо и незаметно, что довольно-таки странно, если вспомнить фишки, которые он принес. В сегдошняшней статье мы постораемся разобраться, что в нем нового и какие проблемы существуют на данный момент, на деле попытаемся реализовать полное шифрование диска с использованием LUKS2, а также рассмотрим доступные коммерческие и свободные инструменты для его взлома.
Значимость и проблема FDE
Дела с шифрованием запоминающих устройств обстоят забавным образом: оно повсюду и нигде одновременно. Начиная от мобильных устройств, где оно играет особо важную роль (причем большинство пользователей об этом даже не догадываются), и заканчивая большими дата-центрами. В то же время исследования, проведенные за последние десять лет в разных странах, включая Великобританию, Германию и США, показывают, что не только обычные пользователи, но и корпорации не сильно пекутся о личных данных.
К сожалению, на этом проблемы не заканчиваются. Большинство нынешних систем полнодискового шифрования (Full Disk Encryption — FDE) обеспечивают конфиденциальность данных, но не их целостность. Это означает, что злоумышленник может физически изменить байт информации на диске и пользователь не сможет обнаружить, что и где изменилось и откуда сбои. Все потому, что сектор открытого текста равняется сектору шифротекста, а метаинформацию хранить негде.
Искажение данных может произойти не только в результате прямого воздействия злоумышленником, но и по чистой случайности: неплотно воткнутый кабель, перезапись данных утилитой, которая не распознает формат LUKS, и так далее.
Проблему целостности данных решает аутентифицированное шифрование (Authenticated Encryption with Associated Data — AEAD). Это не новая тема, и активные исследования вместе с конкурсами на лучший алгоритм (см. CAESAR) ведутся десятки лет. Но для реализации AEAD в полнодисковом шифровании нужно придумать, где хранить дополнительные данные (те самые AD).
Зачем шифровать
Если вы еще сомневаетесь, что полнодисковое шифрование — нужная штука, то подумайте вот о чем: оно не только помогает сохранить в тайне вашу очень важную инфу и пикантные фоточки, защищая вас от разного рода мошенничества и шантажа, но и предохраняет диск от изменений. Например, вас могут на какое-то время разлучить с вашим компьютером, и речь не только о «маски-шоу», но и, например, о дотошном погранконтроле. Как в таких случаях убедиться, что на диске не появилось чего-то нового? Ну и последний, чисто эмоциональный аргумент: просто представьте, какой неистовый баттхерт будет у кого-то, когда он не сможет получить доступ к вашим данным, — даже если там нет ничего интересного!
РЕКОМЕНДУЕМ:
Оценка защищенности UEFI
Решение
Ребята из Чехии несколько лет разрабатывали решение для Linux, которое сможет предоставить FDE с функцией AEAD. Главными критериями для этого были:
- обеспечить работу без дополнительного оборудования;
- сделать возможным применение на самых обычных дисках, которые доступны в магазине, а не по спецзаказу;
- использовать родной размер сектора;
- реализовать возможность восстановления данных в случае перебоя питания;
- использовать (и писать) только свободный код и алгоритмы.
Результатом разработки стали новые объекты (targets) для device mapper: dm-integrity, обновленный dm-crypt с аутентифицированным шифрованием и формат LUKS2. Их поддержка включена в ядро Linux начиная с версии 4.12, а новые шифры AEGIS и MORUS (финалисты CAESAR) доступны с 4.18.
Подробнее о dm-integrity, dm-crypt и LUKS2
dm-integrity
Эмулирует блочное устройство с дополнительными тегами в каждом секторе и использует их для хранения метаинформации. Поддерживает журналирование, которое можно опционально включить — например, чтобы можно было восстановить данные после сбоя питания.
Применяется как в паре с dm-crypt для предоставления AEAD, так и отдельно — для контроля целостности данных без шифрования. Управляется утилитами cryptsetup, если нужно шифрование, или integritysetup, соответственно, без него.
dm-crypt
Здесь добавили поддержку режимов AEAD для шифров и рандомизацию вектора инициализации (Initialization Vector). На каждую запись в сектор ядром генерируется случайный Initialization Vector.
К примеру, в режиме XTS вектор шифруется хитрым образом, что позволяет брать для него предсказуемый номер сектора (plain или plain64).
LUKS2
Это вторая версия формата LUKS с расширенными возможностями. Были устранены некоторые проблемы и ограничения, однако большинство идей LUKS1 остались. Среди новых возможностей:
- поддержка затратных для памяти функций формирования ключа (key derivation function — KDF);
- новый вид заголовка (бинарный + JSON), добавлен механизм контрольных сумм, дублирован (кроме области ключей);
- ключам можно назначать приоритет;
- JSON позволяет расширять возможности формата, не модифицируя бинарную структуру;
- в заголовке реализованы токены, которые связаны со слотами для ключей и описывают, где взять пароль. Токены могут быть использованы для поддержки механизмов внешнего хранения ключей.
Посмотреть формат заголовка LUKS2 полностью и изучить каждое поле можно в спецификации.
Argon2 — та самая, затратная для памяти и центрального процессора KDF. В Linux доступны два варианта: Argon2i и Argon2id.
На данный момент шифры AEAD, которые есть в ядре (AES-GCM и ChaCha20-Poly1305), имеют короткий (96-bit) одноразовый код (nonce). Это означает, что вероятность коллизии слишком большая (с точки зрения криптографии) и ее нельзя игнорировать, так как использование одноразового кода дважды (nonce reuse) фатально для AES-GCM. На всякий случай отмечу, что это не касается шифрования информации, передаваемой по сети.
Для обеспечения AEAD в FDE сейчас стоит использовать новые AEGIS или MORUS. Или же AES-XTS + HMAC, если нет доступа к 4.18. Проблема этой конструкции в том, что нужно хешировать сектор, а хеширование 4 Кбайт данных занимает какое-то время. Другими словами: это долго.
Поддержка dm-integrity включается в ядре опцией CONFIG_DM_INTEGRITY. В Arch Linux проверить, включена ли она у тебя, можно командой
1 2 3 |
$ zgrep -E "CONFIG_DM_INTEGRITY|CONFIG_BLK_DEV_INTEGRITY" /proc/config.gz CONFIG_BLK_DEV_INTEGRITY=y CONFIG_DM_INTEGRITY=m |
В Ubuntu список конфигов ядра находится в разделе /boot, файл config-версия_ядра — грепай его, и узнаешь всю правду.
Стоит упомянуть, что авторы не пытаются переизобрести велосипед и придумать невиданную ранее концепцию. Подобное решение, но с другим подходом существует во FreeBSD и называется GELI. Здесь для обеспечения целостности данных используется HMAC.
Полнодисковое шифрование с LUKS2 на практике
Итак, у нас в арсенале скоро появятся новые алгоритмы и новые фичи. Но попробовать их не терпится уже сейчас, чем я и занялся.
Работа над форматом LUKS2 еще не завершена, так что не рекомендуется использовать его в продакшене!
Тут же нас встречает первая проблема: поддержки со стороны загрузчиков просто-напросто нет. На данный момент ни GRUB, ни другие не умеют работать с LUKS2.
Отсутствие возможности грузиться с раздела LUKS2 при этом не конец света: /boot зашифруем в LUKS1. Кто-то возразит, что /boot — главный раздел и злоумышленнику, который получил доступ к нему, уже все равно, что у тебя в /. И это правда. Но к сожалению, пока что приходится работать с тем, что есть. LUKS1, конечно же, неплох, но мы сюда пришли новые фичи тестить. В любом случае LUKS2 находится в стадии допила напильником развития и модификации, поэтому о деплое в продакшен речи в любом случае не идет.
Тем временем сзади подкрался второй подвох: это ядро 4.18, которое, как ты помнишь, нужно для AEGIS и MORUS и которого на момент написания статьи нет ни в одном live-установщике. Единственная идея, которая мне приходит в голову, — это кастомный archiso, так как ежемесячный билд содержит только версию 4.17.11.
Модификация archiso
Процесс хорошо описан в Arch Wiki. В двух словах: нужно скачать официальный образ live-установщика, распаковать, внести свои изменения и запаковать обратно.
Если ты читаешь статью, когда на свете уже есть установщик с ядром 4.18, пропускай эту подглаву — ты живешь в прекрасном будущем и тебе все это не пригодится.
На странице загрузки выбирай наиболее подходящее зеркало и качай:
1 |
$ curl -q -OL "http://mir.archlinux.fr/iso/2018.08.01/archlinux-2018.08.01-x86_64.iso{,.sig}" |
Не забудь проверить целостность файла .iso:
1 |
$ gpg --recv-keys 9741E8AC && gpg --verify archlinux-2018.08.01-x86_64.iso.sig |
1 2 |
# mkdir /mnt/archiso # mount -t iso9660 -o loop archlinux-2018.08.01-x86_64.iso /mnt/archiso |
Так как образы ISO монтируются в режиме только для чтения, скопируй содержимое в другую директорию. Перед копированием удостоверься, что директории ~/customiso не существует, и выполни
1 |
$ cp -a /mnt/archiso ~/customiso; sync |
Далее нужно распаковать airootfs.sfs утилитой unsquashfs, она есть в составе пакета squashfs-tools ( $ sudo pacman -S squashfs-tools):
1 2 |
$ cd ~/customiso/arch/x86_64/ $ unsquashfs airootfs.sfs |
Для обновления ядра понадобится… ядро. Копируй:
1 |
$ cp ../boot/x86_64/vmlinuz squashfs-root/boot/vmlinuz-linux |
Теперь можно делать chroot в систему, для этого используй скрипт arch-chroot из пакета arch-install-scripts:
1 |
$ sudo arch-chroot squashfs-root /bin/bash |
Для установки пакетов нужно сначала инициализировать ключи для pacman внутри chroot:
1 2 |
# pacman-key --init # pacman-key --populate archlinux |
Обнови все пакеты:
1 |
# pacman -Syu --force archiso linux |
В файле /etc/mkinitcpio.conf замени HOOKS=(...) на
1 |
HOOKS=(base udev memdisk archiso_shutdown archiso archiso_loop_mnt archiso_pxe_common archiso_pxe_nbd archiso_pxe_http archiso_pxe_nfs archiso_kms block filesystems keyboard) |
Пересобери initramfs:
1 |
# mkinitcpio -p linux |
По окончании нужно создать список пакетов, почистить кеш менеджера пакетов и выйти из окружения chroot:
1 2 3 |
# LANG=C pacman -Sl | awk '/\[installed\]$/ {print $1 "/" $2 "-" $3}' > /pkglist.txt # pacman -Scc # exit |
Перенеси свежее ядро и список пакетов, а также удали запасной образ (fallback), так как он не используется установщиком:
1 2 3 4 |
$ mv squashfs-root/boot/vmlinuz-linux ~/customiso/arch/boot/x86_64/vmlinuz $ mv squashfs-root/boot/initramfs-linux.img ~/customiso/arch/boot/x86_64/archiso.img $ rm squashfs-root/boot/initramfs-linux-fallback.img $ mv squashfs-root/pkglist.txt ~/customiso/arch/pkglist.x86_64.txt |
Создай новый airootfs.sfs, почисти мусор и сгенерируй контрольную сумму:
1 2 3 4 |
$ rm airootfs.sfs $ mksquashfs squashfs-root airootfs.sfs $ sudo rm -r squashfs-root $ sha512sum airootfs.sfs > airootfs.sha512 |
Чтобы можно было грузиться в режиме UEFI, надо обновить загрузочный образ:
1 2 3 4 5 |
$ mkdir mnt ## Для монтирования FAT файловых систем нужен пакет dosfstools $ sudo mount -t vfat -o loop ~/customiso/EFI/archiso/efiboot.img mnt $ sudo cp ~/customiso/arch/boot/x86_64/vmlinuz mnt/EFI/archiso/vmlinuz.efi $ sudo cp ~/customiso/arch/boot/x86_64/archiso.img mnt/EFI/archiso/archiso.img |
Последнее, что нужно, — это запаковать все в новый ISO. Читай метку старого .iso при помощи lsblk -f или blkid.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$ iso_label="ARCH_201808" ## xorriso есть в пакете libisoburn (sudo pacman -S libisoburn) $ xorriso -as mkisofs \ -iso-level 3 \ -full-iso9660-filenames \ -volid "${iso_label}" \ -eltorito-boot isolinux/isolinux.bin \ -eltorito-catalog isolinux/boot.cat \ -no-emul-boot -boot-load-size 4 -boot-info-table \ -isohybrid-mbr ~/customiso/isolinux/isohdpfx.bin \ -eltorito-alt-boot \ -e EFI/archiso/efiboot.img \ -no-emul-boot -isohybrid-gpt-basdat \ -output arch-custom.iso \ ~/customiso $ sudo umount mnt $ sudo rm -r mnt |
Все готово, записывай arch-custom.iso на диск или флешку и грузись:
1 |
$ sudo dd if=arch-custom.iso of=/dev/xxx bs=1M status=progress |
Установка Arch Linux на LUKS2
Если модификации прошли успешно и удалось загрузиться, то первая строчка на экране сообщит версию ядра.
Подробно расписывать, как устанавливать Arch Linux, нет смысла — этой информации полно в интернете. Затрону главные моменты, которые касаются LUKS2 и «прикручивания» шифрования в целом.
Установка проводится на чистый, новый или пустой диск, желательно SSD. Если у тебя есть другие разделы, то придется их нюкнуть. Также нужен UEFI, который, скорее всего, твоя машинка поддерживает.
Если ставишь на виртуалку, то главное — включить поддержку EFI и пробросить флешку.
Данные ОПАСНОСТЕ!!1 Единственный способ расшифровать их — это ключ-файл на флешке. Выбирай понадежней или оставь возможность ввести пароль.
Чтобы в один прекрасный день не лишиться данных из-за испорченной или утерянной флешки, сразу добавлю возможность открывать парольной фразой. Из-за этого у меня будут задействованы два слота в заголовке: пароль (слот 0) и ключ-файл (слот 1), который я добавлю потом. Если любишь риск, то можешь парольный слот уничтожить после добавления файла.
Топология диска у меня:
- /dev/sda1 — раздел для образов .efi, не зашифрован, FAT32;
- /dev/sda2 — раздел /boot, зашифрован, LUKS1;
- /dev/sda3 — /, зашифрован, LUKS2.
GPT — таблица разделов. Отдельный /boot нужен, как ты помнишь, из-за того, что загрузчики пока не умеют открывать LUKS2. По большому счету можно избавиться от sda1 и хранить образ GRUB в файле .efi на той же флешке: для этого нужен раздел с FAT (по спецификации UEFI), и вспомнить кое-какие дополнительные ключи ( --removable) для grub-install.
Смотрю диск:
1 2 3 4 5 6 7 8 9 10 11 12 |
root@archiso ~ # fdisk -l Disk /dev/sda: 119.2 GiB, 128035676160 bytes, 250069680 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: gpt Disk identifier: BA18A20B-089C-47EC-A88C-096FE6A5A7EE Device Start End Sectors Size Type /dev/sda1 2048 411647 409600 200M EFI System /dev/sda2 411648 821247 409600 200M Linux filesystem /dev/sda3 821248 21792767 20971520 10G Linux filesystem |
И создаю LUKS2 на /dev/sda3:
1 |
# cryptsetup luksFormat --type luks2 --pbkdf argon2id --cipher aegis256-random --integrity aead --integrity-no-journal /dev/sda3 |
Чтобы использовать контроль целостности данных ( --integrity), на устройство сначала нужно записать контрольные суммы. Поэтому, если у тебя большой диск, придется запастись терпением.
А вот сравнение скорости работы алгоритмов на SSD, приведенное разработчиками. Линейная запись и чтение.
В качестве PBKDF я использую Argon2id. Если установка идет на одном железе, а система будет использоваться на другом, то дополнительно можно указать, сколько памяти, процессорных потоков и итераций использовать. Ключи:
- --pbkdf-memory <number>;
- --pbkdf-parallel <number>;
- --pbkdf-force-iterations <num>.
Если не указывать их, то будет проведен бенчмарк текущего железа и цифры взяты оттуда.
Шифр — aegis256-random. Для LUKS2 доступны следующие алгоритмы AEAD:
- aegis128-random;
- aegis256-random;
- morus640-random;
- morus1280-random.
Суффикс -random здесь указывает на вектор инициализации. Более подробное сравнение смотри в спецификации и магистерской диссертации.
Как видно из графиков, журнал уменьшает скорость, поэтому отключаю его. На ноутбуке он, в принципе, не нужен, так как внезапная потеря питания в большинстве случаев ему не грозит.
Смотрю, что получилось, и открываю:
1 2 3 |
# cryptsetup luksDump /dev/sda3 # cryptsetup open /dev/sda3 crypto_root # lsblk -f |
То самое эмулированное промежуточное устройство crypto_root_dif, с дополнительным местом под метаданные. Для пользователя оно прозрачно, и работа проходит с обычным блочным устройством, в данном случае crypto_root.
Подготовлю раздел
/boot в LUKS1 и также открою его:
1 2 3 |
# cryptsetup luksFormat -h whirlpool -i 5555 /dev/sda2 # cryptsetup luksDump /dev/sda2 # cryptsetup open /dev/sda2 crypto_boot |
Тут ничего нового: любимая хеш-функция и чуть больше итераций.
Окей, разделы готовы. Обрати внимание: после открытия я работаю только с эмулированными устройствами
/dev/mapper/crypto_boot и
/dev/mapper/crypto_root, а не с физическими
/dev/sda2 и
/dev/sda3.
Создаю файловые системы:
1 2 3 |
# mkfs.vfat -F32 -n "ESP" /dev/sda1 # mkfs.ext2 -L "arch_boot" /dev/mapper/crypto_boot # mkfs.ext4 -L "arch_root" /dev/mapper/crypto_root |
Монтирую:
1 2 3 4 5 |
# mount /dev/mapper/crypto_root /mnt # mkdir /mnt/boot # mount /dev/mapper/crypto_boot /mnt/boot # mkdir /mnt/boot/efi # mount /dev/sda1 /mnt/boot/efi |
Всегда используй только свежие зеркала:
1 2 3 4 5 |
## Переименовать список старых # mv /etc/pacman.d/mirrorlist{,.old} ## Скачать новые ## FR в ссылке можешь заменить на код своей страны или той, что рядом # curl -q -sSL 'https://archlinux.org/mirrorlist/?country=FR&protocol=https' | sed -e 's/^#S/S/g' >/etc/pacman.d/mirrorlist |
Для аутентификации по флешке нужно добавить дополнительный ключ. Ты можешь сделать его из последовательности битов на ней и указать GRUB использовать их при помощи следующего параметра ядра: cryptkey=device:offset:size, где
- device — блочное устройство, на котором хранится ключ;
- offset — смещение, по которому считывать байты;
- size — сколько байтов считать.
В качестве device можно использовать как /dev/sdX, так и UUID=, например:
1 |
cryptkey=/dev/sda:0:512` или `cryptkey=UUID=1234-5678:0:512 |
В моем случае это будет обычный файл. Поэтому воспользуюсь немного другим форматом: cryptkey=device:fstype:path и просто укажу путь к нему.
- fstytpe — тип файловой системы, можно использовать auto;
- path — путь к файлу.
Если флешка чистая, без разделов, то придется их создать. Какую именно файловую систему использовать — дело твое. Для экономии времени воспользуюсь установочной флешкой. Создам директорию и примонтирую в нее:
1 2 |
# mkdir /flash # mount /dev/sdb2 /flash |
Сгенерирую ключ-файл:
1 |
[crayon-65f90a125f2ad503907587 inline="true" ]<span class="com"># dd if=/dev/urandom of=/flash/root_key.bin bs=1024 count=2</span> |
[/crayon]
Статья и интересное обсуждение для тех, кто думает, что чуть выше я совершил акт кощунства.
Добавлю ключ:
1 |
# cryptsetup luksAddKey --pbkdf argon2id /dev/sda3 /flash/root_key.bin |
Экстремалы могут удалить парольный слот командой cryptsetup luksKillSlot /dev/sda3 0, где 0 — номер слота.
Все готово к установке:
1 |
# pacstrap /mnt base base-devel vim grub efibootmgr dialog wpa_supplicant |
Генерирую fstab:
1 |
# genfstab -U /mnt >> /mnt/etc/fstab |
Далее буду проводить настройки системы изнутри. Для этого использую chroot: arch-chroot /mnt. Первым делом — GRUB. В файле /etc/default/grub раскомментируй GRUB_ENABLE_CRYPTODISK=y и замени строки
1 2 |
GRUB_CMDLINE_LINUX_DEFAULT="quiet" GRUB_CMDLINE_LINUX="" |
на вот такие:
1 2 |
GRUB_CMDLINE_LINUX_DEFAULT="verbose" GRUB_CMDLINE_LINUX="cryptdevice=UUID=7a40a90f-2533-41e0-bb94-fd30f4026544:crypto_root cryptkey=UUID=5F6A-991B:auto:/root_key.bin root=/dev/mapper/crypto_root" |
Обрати внимание, что GRUB_CMDLINE_LINUX="..." — одна строка, никаких переносов нет.
Идентификаторы UUID смотри через
# blkid.
Примерная схема работы:
- GRUB запросил пароль от раздела /boot.
- Пароль подходит? Открыл, прочитал его, нашел initramfs, передал ему управление.
- Закончил работу, все закрыл и забыл.
Параметр ядра cryptkey=UUID=5F6A-991B:auto:/root_key.bin указывает initramfs, где взять ключ от / — корневого раздела (LUKS2). Если флешка недоступна, он об этом сообщит и запросит пароль. А если ты удалил слот с паролем, то загрузиться не получится.
Файл /etc/crypttab работает схожим с /etc/fstab образом, только для зашифрованных дисков. В нем указываются все разделы (кроме корневого), которые должны быть открыты при загрузке системы. Конфиг crypttab читается перед fstab, но автомонтирование (уже открытых) разделов производит второй. Таким образом, crypttab — это то, что нужно для открытия /boot во время загрузки системы, так как GRUB, передав управление initramfs, его закрыл и забыл все ключи.
Чтобы не вводить пароль от него дважды (для GRUB и для crypttab), создай и добавь ключ-файл и для раздела /boot:
1 2 3 |
# mkdir /root/keys # dd if=/dev/urandom of=/root/keys/boot_key.bin bs=1024 count=2 # chmod -R 0 /root/keys/ |
Добавляй, как обычно:
1 |
# cryptsetup luksAddKey /dev/sda2 /root/keys/boot_key.bin |
И теперь используй его для автоматического открытия. В конец
/etc/crypttab допиши:
1 |
crypto_boot UUID=4d053fc0-ded6-4390-9e7c-a8abfa503cd5 /root/keys/boot_key.bin luks,timeout=15 |
Для большей надежности перепроверь UUID в
/etc/fstab. Для корневого раздела и для
/boot они должны соответствовать
crypto_root и
crypto_boot, а не
sda2 и
sda3.
Осталось добавить компоненты для initramfs с помощью скрипта mkinitcpio. Для этого подредактируй файл
/etc/mkinitcpio.conf и в строку
1 |
HOOKS=(base udev autodetect modconf block filesystems keyboard fsck) |
добавь encrypt, чтобы получилось
1 |
HOOKS=(base udev autodetect modconf block encrypt filesystems keyboard fsck) |
В MODULES=() допиши dm_integrity и vfat:
1 |
MODULES=(dm_integrity vfat) |
Иначе при загрузке получишь ошибку Kernel doesn’t support dm-integrity mapping. Модуль vfat нужен, так как раздел флешки с ключом — в FAT.
Пересобери initramfs:
1 |
# mkinitcpio -p linux |
Последнее, что нужно сделать, — это установить GRUB и сгенерировать для него .cfg-файл командами
1 2 |
# grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=crypto_arch # grub-mkconfig -o /boot/grub/grub.cfg |
1 2 3 4 5 6 7 8 |
## Задай пароль для root # passwd ## Выйди из chroot # exit ## Отмонтируй все # umount -R /mnt ## Последний раз все проверь и пиши # reboot |
Поздравляю, твой свежий Arch Linux установлен на раздел LUKS2 с включенным контролем целостности данных!
Парочка топорных тестов скорости дешевого SSD.
Проверка на прочность
Это все замечательно, но, если твой диск попадет в руки злоумышленнику, насколько тяжело (или легко) тому будет достать данные? Сейчас проверим.
Стоит понимать, что есть множество способов похитить нужную инфу. LUKS защищает данные в офлайне — то есть диск (раздел, контейнер) или закрыт, или отключен от питания вовсе. Иными словами, не думай, что, установив LUKS, ты волшебным образом навсегда обезопасишь данные. Если оставляешь компьютер без присмотра с открытым разделом или пароль записан на стикере, то извини: никакой LUKS тут не поможет.
Для тестов я выбрал четыре продукта: два открытых и два коммерческих. Открытые — это John the Ripper и hashcat. Из коммерческих я знаю продукт ElcomSoft, но он не поддерживает даже LUKS1, поэтому сразу отпадает. Второй найденный мной вариант — это Passware. Никогда не слышал об этой конторе, нашел через поисковик. Список клиентов серьезный: NASA, министерства обороны и юстиции США и другие.
Все инструменты поддерживают GPU. Фермы для майнинга, к сожалению (или к счастью), у меня нет, и в качестве GPU использовалась моя GTX 1050 Ti. Посмотрим, что может эта старушка против LUKS и LUKS2. Для взлома не нужен диск или раздел полностью, достаточно заголовка. Извлекаю их на флешку:
1 2 |
# cryptsetup luksHeaderBackup /dev/sda2 --header-backup-file /flash/boot_header.bin # cryptsetup luksHeaderBackup /dev/sda3 --header-backup-file /flash/root_header.bin |
John the Ripper
Ставлю свежую версию и смотрю, что есть в арсенале:
1 |
$ ./john --list=formats --format=opencl | grep -i luks |
Нет вывода. Окей, как насчет CPU?
1 2 |
$ ./john --list=formats --format=cpu | grep -i luks lotus5, lotus85, LUKS, MD2, mdc2, MediaWiki, monero, money, MongoDB, scram, |
Что поделать, придется довольствоваться CPU. Пробую:
1 |
$ ./luks2john.py /tmp/boot_header.bin |
Как видно из скриншота, даже формат AES-XTS не поддерживается, LUKS2 нет смысла пробовать. Это было быстро, идем дальше.
hashcat
1 2 3 4 |
$ ./hashcat --version v4.2.1-25-gfe04ccc1 $ ./hashcat --help | grep -i luks 14600 | LUKS | Full-Disk Encryption (FDE) |
Есть только LUKS первой версии. Хотя бы умеет работать с AES-XTS, проведу бенчмарк:
1 2 3 4 5 6 7 |
$ ./hashcat -m 14600 -b --quiet Hashmode: 14600 - LUKS (Iterations: 163044) Speed.Dev.#1.....: 3157 H/s (22.86ms) @ Accel:2 Loops:1024 Thr:1024 Vec:1 Started: Wed Aug 22 21:41:42 2018 Stopped: Wed Aug 22 21:42:01 2018 |
3217 хешей в секунду для 163 044 итераций — неплохо. У меня, если посмотреть на скриншот luksDump, — 2 941 833 для парольного слота и 2 137 768 для файла. Для hashcat недостаточно просто сделать luksHeaderBackup, нужно писать
1 |
$ dd if=/dev/XXXX of=header.luks bs=512 count=4097 |
Все шло хорошо, но тут меня ждал сюрприз в виде ошибки hashcat/OpenCL/m14651-pure.cl: No such file or directory. Как оказалось, hashcat не поддерживает хеш-функцию whirlpool. Иногда нужно читать доки до конца. На той же странице форума английскими буквами написано:
1 2 3 |
There’s two things missing (at the moment) in order to make hashcats LUKS support "full featured": Support for Keyfiles Support for Whirlpool |
Чтобы не перебивать раздел /boot с использованием дефолтной SHA-256, создам отдельный криптоконтейнер и возьму заголовок с него, от этого ничего не поменяется.
1 2 3 4 |
## Создам файл $ truncate -s 100M sha_container ## Сделаю из него криптоконтейнер $ cryptsetup luksFormat -i 5555 sha_container |
И еще очень важная деталь: в контейнере должна быть файловая система, иначе пароль не подберется никогда, даже если он есть в списке. Это тоже упоминается на форуме по ссылке выше.
1 2 3 4 5 6 7 8 |
## Открою $ sudo cryptsetup open sha_container sha_cont ## Создам ФС $ mkfs.ext4 /dev/mapper/sha_cont ## Закрою $ sudo cryptsetup close /dev/mapper/sha_cont ## Извлекаю заголовок $ dd if=sha_container of=sha_header_hashcat.bin bs=512 count=4097 |
В этом заголовке другое количество итераций — 9 756 846.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
$ cryptsetup luksDump sha_header_hashcat.bin LUKS header information for sha_header_hashcat.bin Version: 1 Cipher name: aes Cipher mode: xts-plain64 Hash spec: sha256 Payload offset: 4096 MK bits: 256 MK digest: f6 f7 78 2e 00 be 93 6a d9 01 c1 d6 12 d2 1f 28 58 e5 52 e9 MK salt: b2 0b 2f bd 4b cb d6 38 b3 71 45 48 62 e0 2f e6 ea 84 16 c3 28 c7 ba 5d 5a ad 16 37 26 61 e5 c0 MK iterations: 220288 UUID: cf458e89-9e5a-4fa8-bf1c-ee9045bc4d5d Key Slot 0: ENABLED Iterations: 9756846 Salt: 5b 7c 16 4b d4 b5 a8 eb da 6c d4 ea f8 2c 32 6c 01 0c ed c1 3e 0d 87 14 5d d8 e0 d6 ce fb b2 ab Key material offset: 8 AF stripes: 4000 |
Пробую и вижу один хеш в минуту и четыре секунды:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$ ./hashcat -m 14600 -a 0 sha_header_hashcat.bin pwdd Session..........: hashcat Status...........: Exhausted Hash.Type........: LUKS Hash.Target......: sha_header_hashcat.bin Time.Started.....: Wed Aug 22 22:56:35 2018 (1 min, 4 secs) Time.Estimated...: Wed Aug 22 22:57:39 2018 (0 secs) Guess.Base.......: File (pwdd) Guess.Queue......: 1/1 (100.00%) Speed.Dev.#1.....: 0 H/s (0.40ms) @ Accel:2 Loops:64 Thr:512 Vec:1 Recovered........: 0/1 (0.00%) Digests, 0/1 (0.00%) Salts Progress.........: 1/1 (100.00%) Rejected.........: 0/1 (0.00%) Restore.Point....: 1/1 (100.00%) Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:9756800-9756845 Candidates.#1....: 112233 → 112233 HWMon.Dev.#1.....: Temp: 35c Fan: 45% Util: 96% Core:1860MHz Mem:3504MHz Bus:8 |
Наблюдается проблема: hashcat начинает перебирать количество итераций, пока не дойдет до нужного, а не читает его прямо с заголовка. Делает он это для каждого пароля в файле, поэтому тест для одного пароля занимает долгое время.
РЕКОМЕНДУЕМ:
Безопасность JavaScript или как написать безопасный код на JS
Passware
Из доступных на сайте продуктов я выбрал Passware Kit Forensic, полная версия стоит 995 долларов. Взял триалку, в которой время взлома ограничено одной минутой. В принципе, этого должно хватить, чтобы оценить скорость работы. Запускаю, смотрю список доступных форматов FDE.
Есть LUKS1, нет LUKS2, пробую.
Ситуация та же, что и с hashcat, — нет поддержки whirlpool. Беру криптоконтейнер с SHA-256, добавляю брутфорс-атаку. Чтоб сократить время ожидания до минимума, явно указываю только цифры и длину пароля.
В результате получаю тринадцать паролей в минуту. Если верить программе, брутфорс шестизначного цифрового пароля займет месяц и 26 дней.
Итоги
Наивно было надеяться, что формат, который сейчас на стадии постоянной доработки, будет поддерживаться хоть каким-нибудь продуктом. На его реализацию нужно потратить время и ресурсы, а спецификация формата может измениться в следующем релизе.
Удивило отсутствие поддержки whirlpool. Она в LUKS давно, видимо разработчики не любят париться и отдают предпочтение дефолтным настройкам.
По результатам видно, что стандартная PBKDF2 неплохо справляется с задачей. Возможно, перед парой сотен или тысяч GPU она не устоит, но для этого есть новый Argon2.
exit()
Радует энтузиазм разработчиков: они делают современную крипту доступной каждому и бесплатно. LUKS2 — интересный формат с кучей фишек. К сожалению, сложность конфигурации и отсутствие поддержки со стороны загрузчиков замедляет его появление на сцене. Использовать его с включенным контролем целостности данных стоит только на SSD.
Пройдет несколько лет, пока LUKS2 окрепнет и сможет полностью заменить своего предшественника. Это было с файловыми системами ext и должно произойти с LUKS2. Что до LUKS1, то он по-прежнему хорош и пока что никуда не уходит. Прекращать его поддержку не намечается, поэтому нет поводов для беспокойства.
Замечательная статья!
Браво автору! У меня нет образования в сфере технологий, но читать было приятно и, в общих чертах, всё понятно.
Спасибо!