Что такое криптография - все знают: берем что-то секретное, зашифровываем его - и без ключа никто ничего не прочитает.
Но есть минус: если кому-то очень хочется почитать - вас могут вежливо попросить поделиться ключиком, и отказаться может быть очень сложно.
Что такое стеганография - тоже многие знают: берем что-то секретное и прячем его среди обычного, оно как бы на виду, но если не знать где именно искать - найти сложно.
Тут минус в другом - оно не должно выделяться и бросаться в глаза.
Что, если попробовать совместить одно с другим?
Вот например, есть 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