Pull to refresh

Сравнение производительности различных систем шифрования под linux

Reading time8 min
Views18K
В данной статье я попытаюсь сравнить производительность различных систем шифрования под linux. В теории, конечно, известно, какая система производительнее, и попытки посчитать производительность разных систем были (например). Truecrypt даже содержит встроенный бенчмарк (который показывает, однако, производительность на RAM, его можно использовать разве что для оценки скорости разных алгоритмов шифрования). Я же сделаю несколько другое — измерю скорость файловой системы, зашифрованной разными средствами, в процентном соотношении по сравнению с обычной нешифрованной файловой системой.
image

Шифровать будем отдельный раздел на отдельном HDD, не содержащий корневую файловую систему, алгоритмом, использующимся по-умолчанию в каждом конкретном случае. Как обычный пользователь, я не разбираюсь в нюансах стандартов шифрования (например, чем отличается хэширование RIPEMD-160 от Whirpool, какой из этих режимов быстрее, какой способствует более высокой защите), поэтому просто положимся на то, что производители каждого программного продукта выбрали достаточно криптостойкие параметры по-умолчанию. Может, это и не совсем корректно, т. к. производительность различных алгоритмов шифрования неодинакова. При желании, конечно можно сменить тип шифрования, но я не уверен, что во всех тестируемых продуктах существует абсолютно идентичный набор алгоритмов. Тестировать будем:

1) LUKS — нативная система шифрования, в теории должна быть самой быстрой. Тома, зашифрованные LUKS можно использовать в Windows через FreeOTFE.

2) Truecrypt — в отличии от LUKS имеет, кроме консольного, и GUI-интерфейс, что делает его на порядок удобнее в использовании. Мультиплатформенное ПО. Обеспечение двух уровней правдоподобного отрицания наличия зашифрованных данных, необходимого в случае вынужденного открытия пароля пользователем. Тома Truecrypt не имеют заголовка, их нельзя отличить от набора случайных данных. В теории медленнее, чем LUKS, т.к. использует FUSE.

3) eCryptfs — система, по умолчанию предлагаемая пользователям Ubuntu для шифрования домашних каталогов, поэтому и включена в данный тест. Работает поверх уже существующей ФС. Шифрует каждый файл отдельно, поэтому всем видны права, даты изменения, количество зашифрованных файлов; по-умолчанию также видны имена файлов, хотя и существует опция для их шифрования. Самое малофункциональное средство из представленных.

4) EncFS — примерный аналог eCryptfs, но использует FUSE.

Итак, для тестов выделена отдельная машина довольно преклонного возраста в следующей конфигурации: ЦП — Intel Celeron 2000Mhz, ОЗУ — 512 Mb DDR PC2700, системный HDD — WD Caviar SE 5400 RPM 80Gb, тестовый HDD — WD Caviar SE 7200 RPM 80Gb.
ОС — Ubuntu 12.04 LTS, версии всего ПО актуальные для репозиториев этой ОС на момент написания статьи (Truecrypt 7.1a-linux-x86 не из репозиториев).

Тестировать будем дефолтную для большинства дистрибутивов файловую систему ext4. Для тестирования производительности будем использовать утилиту iozone3 и написанный «на коленке» shell-скрипт для измерения процентной разницы в тестах.
Скрипт для подсчёта. Особое внимание чистоте кода не уделялось, единственным критерием при написании было наличие правильного результата.
#!/bin/sh

gendifffile () {
#процедура генерирует файл, который удобно анализировать. Во-первых, обрезаются
#не подлежащие анализу строки; во-вторых, в каждой строке обрезаются первых два числа, обозначающие 
#размер файла и размер записи соответственно; в-третьих, весь файл выводится построчно - 
#один результат теста на одну строку
cat $1 | while read LINE ; do
	echo $LINE| grep "^[[:space:]]*[[:digit:]]" | awk '{for (i=3;i<=NF;i++) {print $i}}'
done >> $2
}

getline () {
#процедура выводит строку номер $2 файла $1
	head -n $2 "$1" | tail -n 1	
}

compare () {
#процедура сравнивает построчно файлы $1 и $2, вычисляя процентную разницу каждой пары тестов
#затем вычисляется среднее арифметическое значение, на сколько процентов быстрее или медленнее
#файл, содержащий первую группу тестов, файла, содержащего вторую группу
	P=0
	MAX=0
	L1=`cat "$1" | wc -l` #количество тестов в файле
	L2=`cat "$2" | wc -l`
	if [ $L1 -ne $L2 ]; then #если файлы содержат разное количество тестов, то сравнивать их мы не будем
		echo error
		return
	fi
	STEP=$(( $L1*5/100 ))
	J=0
	for I in `seq 1 $L1`; do
		J=$(( $J+1 ))
		if [ $J -eq $STEP ]; then
			J=0
			echo "$(( 100*$I/$L1 ))% завершено ($I из $L1)"
		fi
		A=`getline "$1" $I`
		B=`getline "$2" $I`
		if [ `echo $A \> $B|bc -l` -eq 1 ]; then
			D=`echo "100-($B*100/$A)"|bc -l`
			if [ `echo $D \> $MAX| bc -l` -eq "1" ]; then
				MAX=$D
				sleep 5
			fi
		else
			D=`echo "100-($A*100/$B)"|bc -l`
			if [ `echo $D \> $MAX| bc -l` -eq "1" ]; then
				MAX=$D
				sleep 5
			fi
			D="-$D" #если значение имеет знак "-", значит, данный тест был выполнен быстрее 
				#во втором файле, а не в первом
		fi
		P=`echo "$P+$D"| bc -l`
	done	
	P=`echo $P/$L1| bc -l` #вычислим среднее арифметическое
	echo PERCENT=$P MAX_PERCENT=$MAX
}

genaverage () {
#процедура генерации подготовленного к анализу файла, каждой строкой которого является
#среднее арифметическое соответствующих строк всех файлов отчётов, лежащих в анализируемой директории
	AVG=`mktemp`	
	F=`ls "$1"|wc -l`	#количество файлов с отчётами в заданной директории
				#при условии, что там хранятся только такие файлы и больше ничего другого 
				#проверять корректность данного допущения мы не будем
	if [ ! -d "$1" -o $F -lt 2 ]; then 
		echo error >/dev/stderr #в этой процедуре будем выводить все сообщения в stderr, т.к.
					#stdout подставляется в другую процедуру
		rm -f $AVG
		exit
	fi
	TMP=`mktemp`
	find "$1" -type f| while read FILE; do	#для каждого файла отчёта iozone, лежащего в заданной директории
		I=`mktemp`			#сгенерируем временный файл, подготовленный для анализа
		gendifffile "$FILE" "$I"	#имена всех таких файлов запишем в "TMP" построчно
		echo "$I">>$TMP			
	done	
	L=`cat \`getline "$TMP" 1\`|wc -l`
	cat "$TMP"| while read LINE; do	#немного проверок не помешает
		L1=`cat "$LINE"| wc -l`	#все ли файлы содержат одинаковое количество тестов
		if [ $L -ne $L1 ]; then
			echo error >/dev/stderr
			exit
		fi
	done	
	STEP=$(( $L*5/100 ))
	J=0
	for I in `seq 1 $L`; do
		J=$(( $J+1 ))
		if [ $J -eq $STEP ]; then
			J=0
			echo "$(( 100*$I/$L ))% завершено ($I из $L)" >/dev/stderr
		fi
		SUMFILE=`mktemp` #таким образом я получаю значение переменной SUM из вложенного цикла
		SUM=0
		cat "$TMP"| while read LINE; do
			SUM=$((	`getline "$LINE" $I`+$SUM )) 
			echo $SUM > "$SUMFILE"
		done
		echo `tail -n 1 "$SUMFILE"`/$F|bc -l >> $AVG 	#получаем среднее арифметическое
								#и запишем его в соответствующее место
								#файла AVG
		rm -f "$SUMFILE"
	done
	cat "$TMP"| while read LINE; do #удалим временныe файлы
		rm -f "$LINE"
	done
	rm -f "$TMP"
	echo $AVG
}

printf %b "\\033[1;31mШаг 1/3\n"
printf %b "\\033[1;37m"
echo Генерируем усреднённый файл для директории \""$1"\"
A=`genaverage "$1"`	
printf %b "\\033[1;31mШаг 2/3\n"
printf %b "\\033[1;37m"
echo Генерируем усреднённый файл для директории \""$2"\"
B=`genaverage "$2"`
printf %b "\\033[1;31mШаг 3/3\n"
printf %b "\\033[1;37m"
echo Сравниваем усреднённые файлы 
compare "$A" "$B"
rm -f $A $B		

Под спойлером расскажу подробнее об алгоритме тестирования, для того, чтобы каждый мог сам провести интересующий его тест.
алгоритм тестирования
1) подключаем тестируемый нешифрованный раздел к точке монтирования, переходим в неё, запускаем серию тестов iozone
i=0
while true; do
i=$(( $i+1 ))
echo i=$i
time iozone -a >report$i
echo sleeping 180
sleep 180
done

Прогоняем столько кругов, сколько не жалко. Чем больше число, тем точнее результат. Для некоторых видов теста (для самых медленных) большое число кругов неважно, хватит 5.
Складываем результаты в отдельную директорию, назовём её, например, unencrypted.
2) шифруем раздел, подключаем к точке монтирования, аналогично прогоняем серию тестов, складываем результаты в другую директорию (например, encrypted).
3) запускаем скрипт подсчёта, передав ему имена обеих директорий в качестве параметров. Скрипт выведет некоторое число, на сколько процентов, в среднем, состоит разница в производительности между отчётами первой и второй директории. Если число >0, значит, отчёты первой директории быстрее на это число процентов; и наоборот, если число <0 — значит, медленнее.

Положимся на режим -a, в котором iozone должен произвести в автоматическом режиме серию тестов, которые покрывают всевозможные операции с файлами разных размеров и разной длиной записи (моя версия произвела 1638 тестов).
В ходе эксперимента выяснилось, что одна серия тестов iozone может отличаться от другой по производительности на 5%, поэтому я не буду рассчитывать на результаты одного-единственного набора тестов и поступлю таким образом: проведу набор тестов несколько раз и сгенерирую файл с усредненными значениями по каждому из тестов (во всех расчётах данной статьи под усредненными значениями понимается среднеарифметическое значение). После этого я сравню усредненный файл, содержащий серию тестов по незашифрованной файловой системе с аналогичным файлом, содержащим серию тестов на зашифрованной ФС таким образом: каждый тест первого файла будет сравнен с соответствующим тестом второго в процентном соотношении, результаты сложим, а сумму разделим на количество тестов, получив среднеарифметическое значение, на сколько процентов первая группа тестов быстрее или медленнее второй.
Также, для простой оценки скорости, в дополнение к вышеописанным вычислениям, проведем простенький тест — копирование средствами dd 500 мегабайт из urandom на зашифрованную ФС блоками, равными размеру кластера ext4 по-умолчанию (4 килобайта). dd if=/dev/urandom of=testfile bs=4k count=128000. Шифровать будет раздел целиком (за исключением eCryptfs, которая этого делать не умеет). Я не буду приводить команды для каждого конкретного случая, покажу только результаты.
Итак, приступим:

1) Система шифрования: нет
Количество проведенных серий тестов: 14
Средняя разница в производительности между одинаковыми сериями тестов: 1,3%
Результат dd: 524288000 bytes (524 MB) copied, 187.823 s, 2.8 MB/s

2) Система шифрования: LUKS. Используя ключи по-умолчанию, наш том будет зашифрован так:
Cipher name: aes
Cipher mode: cbc-essiv:sha256
Hash spec: sha1
Количество проведенных серий тестов: 8
Средняя разница в производительности между одинаковыми сериями тестов: 1,4%
Результат dd: 524288000 bytes (524 MB) copied, 199.505 s, 2.6 MB/s
Падение производительности по сравнению с нешифрованной ФС: 7,9%

3) Система шифрования: Truecrypt. Применяя все параметры по-умолчанию, том будет зашифрован AES с алгоритмом хеширования RIPEMD-160.
Количество проведенных серий тестов: 22
Средняя разница в производительности между одинаковыми сериями тестов: 3,2%
Результат dd: 524288000 bytes (524 MB) copied, 199.719 s, 2.6 MB/s
Падение производительности по сравнению с нешифрованной ФС: 7%

4) Система шифрования: eCryptfs
aes: blocksize = 16; keysize = 16
Количество проведенных серий тестов: 9
Средняя разница в производительности между одинаковыми сериями тестов: 0,9%
Результат dd: 524288000 bytes (524 MB) copied, 199.624 s, 2.6 MB/s
Падение производительности по сравнению с нешифрованной ФС: 49,5%

5) Система шифрования: EncFS
Применяя предустановленный режим paranoia, будут использованы следующие настройки:
Cipher: AES
Key Size: 256 bits
PBKDF2 with 3 second runtime, 160 bit salt
Filesystem Block Size: 1024 bytes
Filename Encoding: Block encoding with IV chaining
Unique initialization vector file headers
Message Authentication Code block headers
External IV Chaining
Количество проведенных серий тестов: 5
Средняя разница в производительности между одинаковыми сериями тестов: 0,7%
Результат dd: 524288000 bytes (524 MB) copied, 293.656 s, 1.8 MB/s
Падение производительности по сравнению с нешифрованной ФС: 94,5%

Итог: EncFS показала самый плохой результат. Производительность eCryptfs по всевозможным файловым операциям оставляет желать лучшего, хотя обычный тест dd с оптимальным размером блока показывает скорость, аналогичную остальным системам шифрования. Шифровать целиком ей домашнюю директорию я бы не стал. Удобно применять лишь при шифровании отдельных поддиректорий. Ожидания меньшей производительности Truecrypt из-за использования FUSE не оправдались, в моём случае он оказался даже немного быстрее LUKS.

В дополнение, как бонус, приведу аналогичный тест dd для Truecrypt и LUKS, но для file-hosted контейнера (все параметры шифрования аналогичны).
1) LUKS
524288000 bytes (524 MB) copied, 207.07 s, 2.5 MB/s
2) Truecrypt
524288000 bytes (524 MB) copied, 205.046 s, 2.6 MB/s
Падение производительности можно объяснить тем, что появляются дополнительные накладные расходы на чтение файла контейтера с уже существующей файловой системы вместо прямого обращения к разделу.

P.S. Добавлена EncFS.
P.P.S. Добавлено подробное описание алгоритма тестирования.
Tags:
Hubs:
+6
Comments24

Articles