Что такое криптография — все знают: берем что-то секретное, зашифровываем его — и без ключа никто ничего не прочитает.
Но есть минус: если кому-то очень хочется почитать — вас могут вежливо попросить поделиться ключиком, и отказаться может быть очень сложно.
Что такое стеганография — тоже многие знают: берем что-то секретное и прячем его среди обычного, оно как бы на виду, но если не знать где именно искать — найти сложно.
Тут минус в другом — оно не должно выделяться и бросаться в глаза.
Что, если попробовать совместить одно с другим?
Вот например, есть LUKS.
Можно зашифровать диск, или сделать файл-криптоконтейнер.
Но LUKS буквально кричит «я — секретный секрет, взломай меня!». Большой бинарный файл с легко определяемой сигнатурой, даже если заныкать его глубоко в каталогах файловой системы — при желании найти несложно, а найдя — пойти с вопросами к хозяину.
Но Linux — интересная штука, и в нем есть разные инструменты.
Например, все знают что можно подключить файл как блочное устройство — но не обязательно ВЕСЬ файл.
Можно подключить кусок внутри файла — тогда файл внешне не изменится, и даже сигнатуры будет показывать правильные — но внутри него будет что-то другое.
Конечно, можно просканировать весь файл, например, в поисках сигнатур того же LUKS — но и это не обязательно, есть инструмент, позволяющий применить прозрачное шифрование напрямую.
В этом случае просто некоторые блоки данных внутри файла будут шифрованными блоками диска — и если не знать какие именно и с каким ключом — найти их становится намного сложнее.
Если еще и размещение блоков будет зависить от ключа — то не зная ключа найти их и расшифровать становится еще сложнее.
По-прежнему можно попросить ключ у хозяина — но для этого надо еще узнать, есть ли что им открывать.
Логика программы
1 — запрос текста пароля
2 — формирование хеша-ключа
3 — формирование смещений внутри файла на основе введенного ключа, точнее, вторичного хеша, чтобы даже выявленные смещения никак не уменьшали стойкость самого ключа
4 — подключение куска файла в качестве блочного устройства с прозрачным шифрованием
5 — если это новый файл — перезапись его случайными данными, форматирование, монтирование
6 — если это уже созданный ранее файл — монтирование
7 — если он уже был ранее смонтирован — отмонтирование
В качестве файла-контейнера можно взять любой достаточно большой файл, например видеозапись или образ DVD — после подключения он будет частично испорчен, но по прежнему будет определяться как видеозапись или образ диска.
Внутри него не появятся никакие распознаваемые сигнатуры, что усложняет автоматический поиск «скрытых дисков»
Реализация
Делаем bash-скрипт:
#!/bin/bash # # if [ $EUID -ne 0 ] ; then exec sudo "$0" "$@" fi file=$1 dir=$2 cipher="serpent-xts-plain64" sha="sha512sum" check_file(){ if [ "x$file" != "x" ] && [ -f "$file" ] ; then file_ok="y" fi } check_map(){ loop=$(losetup -j "$file" -O NAME -n | head -1) if [ "x$loop" != "x" ] ; then is_mapped="y" fi } enter_pass(){ echo -n "Enter password: " read -s pass1 echo if [ "x$pass1" = "x" ] ; then exit 0 fi key=$(echo -n "$pass1" | $sha | awk '{print $1}') tmp=$(echo -n "$key" | $sha | awk '{print $1}') } check_dir(){ dir_ok="n" if [ "x$dir" = "x" ] ; then echo -n "Enter mountpoint: " read dir fi if [ "x$dir" != "x" ] ; then if [ -d "$dir" ] ; then dir_ok="y" else mkdir "$dir" if [ -d "$dir" ] ; then dir_ok="y" fi fi fi } mount_dir(){ mount /dev/mapper/stegano_$name $dir if [ $? -eq 0 ]; then if [ "x$SUDO_USER" != "x" ] ; then chown $SUDO_USER:$SUDO_USER $dir fi mount_ok="y" fi } remove_map(){ if [ -b "/dev/mapper/stegano_$name" ] ; then dmsetup remove stegano_$name if [ $? -ne 0 ] ; then echo "ERROR: Can't remove mapped device" exit 1 fi fi } check_fs(){ blkid /dev/mapper/stegano_$name >/dev/null 2>&1 if [ $? -ne 0 ] ; then return fi e2fsck -n /dev/mapper/stegano_$name >/dev/null 2>&1 if [ $? -ne 0 ] ; then return fi fs_ok="y" return } create_fs(){ if [ $fs_ok != "y" ] ; then echo "Usable size is $usable_size Mb." echo "No filesystem found, create new? (y/N)" read a if [ "$a" = "y" ] ; then echo -n "Cleaning... " dd if=/dev/urandom of=/dev/mapper/stegano_$name bs=512 count=$sectors status=none mkfs.ext4 -F -q /dev/mapper/stegano_$name echo "done" if [ $? -eq 0 ] ; then fs_ok="y" fi fi fi } map_file(){ key="" enter_pass offset=0 nsym=4 while [ $offset -lt 20000000 ] ; do sub=$(echo -n $tmp | head -c $nsym) offset=$((0x$sub)) nsym=$(($nsym + 1)) done while [ $offset -gt 60000000 ] ; do offset=$(($offset / 2)) done tailer=0 nsym=4 while [ $tailer -lt 20000000 ] ; do sub=$(echo -n $tmp | tail -c $nsym) tailer=$((0x$sub)) nsym=$(($nsym + 1)) done while [ $tailer -gt 60000000 ] ; do tailer=$(($tailer / 2)) done filesize=$(stat --format="%s" "$file") usable_size=$(( ($filesize - $offset - $tailer) / 1024 / 1024 )) if [ $usable_size -lt 10 ] ; then echo "Usable size too small! Select other file" exit 1 fi sectors=$(( ($filesize - $offset - $tailer) / 512 )) loop=$(losetup -f --show --offset $offset --size $(($sectors * 512)) "$file") if [ "x$loop" != "x" ] ; then name=$(basename $loop) sectors=$(cat /sys/class/block/$name/size) if [ $sectors -gt 0 ] ; then echo "0 $sectors crypt $cipher $key 0 $loop 0" \ | dmsetup create stegano_$name if [ -b "/dev/mapper/stegano_$name" ] ; then fs_ok="n" check_fs create_fs if [ $fs_ok = "y" ] ; then dir_ok="n" check_dir if [ "$dir_ok" = "y" ] ; then mount_ok="n" mount_dir if [ "$mount_ok" = "y" ] ; then echo "Success: mounted at $dir" exit 0 fi fi remove_map losetup -d $loop exit 0 else unmap_file fi else echo "ERROR: Something wrong" exit 1 fi fi fi } unmap_file(){ name=$(basename $loop) fs=$(mount | grep "/dev/mapper/stegano_$name" | awk '{print $3}') if [ "x$fs" != "x" ] ; then umount $fs if [ $? -ne 0 ] ; then echo "Still mounted as $fs" exit 1 fi fi remove_map losetup -d $loop echo "Unmount device" exit 0 } ################################# file_ok="n" check_file if [ $file_ok = "y" ] ; then is_mapped="n" check_map if [ "$is_mapped" = "n" ] ; then map_file else unmap_file fi fi
При вводе другого пароля скрытый диск будет создан заново, с затиранием данных.
При желании можно отключить запрос согласия на выполнение операции, тогда любая ошибка при вводе пароля приведет к удалению данных и созданию нового, пустого диска.
ЗЫ: закинул на Гитхаб: https://github.com/JBFW/stegodisk
ссылка на оригинал статьи https://habr.com/ru/articles/896236/
Добавить комментарий