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

от автора

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

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

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

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

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

Итак, для тестов выделена отдельная машина довольно преклонного возраста в следующей конфигурации: ЦП — 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		 

Положимся на режим -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%

Итог: производительность 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
Падение производительности можно объяснить тем, что появляются дополнительные накладные расходы на чтение файла контейтера с уже существующей файловой системы вместо прямого обращения к разделу.

ссылка на оригинал статьи http://habrahabr.ru/post/201694/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *