Как я шифрую файлы в облаке

Некоторое время назад, читая хабр, натолкнулся на статью, в которой автор говорит о необходимости шифрования файлов, загружаемых в облако. Будучи тем, кому неприятна одна только мысль о том, что «дядя», предоставляющий услугу облачного хранения данных, имеет возможность использовать по своему усмотрению мои файлы, я стал размышлять об их шифровании. Подталкивало к этим размышлениям и то, что облако предоставляется бесплатно. Разумеется, использование архива с паролем было жутко неудобным решением, когда речь шла о большом количестве загружаемых файлов. Давно как раз для этой цели создал себе специальную утилиту, и сейчас, коли был поднял вопрос, решил об этом рассказать.

В самом начале использования облачного хранилища я хотел использовать простое XOR-шифрование. Реализация этого алгоритма не представляет никакой сложности (Фридман А., Кландер Л. и др.: «С/С++. Архив программ» — М.: ЗАО «Издательство БИНОМ», 2001 г. — 640с.), для его выполнения не нужно никаких серьезных вычислений. Однако, у данного метода шифрования есть только один плюс — он сравнительно быстро выполняется. На выходе у нас файл, содержимое которого отпугнет лишь непрофессионала. XOR-шифрование дает не настолько серьезную защиту, как может показаться на первый взгляд. Во-первых, если вы весело шифруете много файлов одним ключом, то злому дядьке достаточно где-то получить хотя бы один оригинал какого-то из файлов этой серии, чтобы вскрыть ключ и так же весело расшифровать всю серию файлов:

Key = 01101001
Text = 10010001
Encoded = 01101001^10010001 = 11111000

Key = Encoded^Text = 11111000^10010001 = 01101001

С другой стороны, алгоритм имеет слишком уж простое математическое описание, в связи с чем, вскрыть ключ можно и не имея оригинала файла, о чем написано, например, здесь.

В связи с этим мы не будем использовать эту бяку, но ссылку на исходник я все-таки выложу для полноты картины. Одним из наиболее простых и достаточно криптостойких алгоритмов является стандарт AES-256. Вокруг него было множество споров, однако в США его допустили к шифрованию сведений, относящихся к государственной тайне (смотри архив википедии), сегодня не существует способов успешной атаки на этот алгоритм за разумный промежуток времени. Над программной реализацией этого алгоритма уже поработал один добрый человек и разрешил свободно использовать свои наработки (сайт разработчика). Целесообразно было воспользоваться этим решением. Исходники утилит:

github.com/asu2010/crypt — XOR-шифратор/дешифратор
github.com/asu2010/crypt_AES-256 — AES-256 — шифратор/дешифратор

Обе программы консольные (разумеется) и сделаны для Windows. В программах предусмотрен ключ по умолчанию, созданный программой-генератором паролей. Он хранится в макросах DEFAULT_KEY, что позволяет его легко изменить. Для удобства использования я назвал исполняемый файл программы «crypt++.exe» и добавил путь к этому файлу в переменную окружения PATH. Шифрование с ключом по умолчанию из CMD выглядит следующим образом:

>crypt++ example.jpg enc


Дешифровка:
>crypt++ enc_example.jpg dec


Если нужно использовать другой ключ, то его можно указать после параметра enc/dec:
>crypt++ photo.jpg enc Ajk45BZ972pr


Возможно, этот инструмент не очень-то удобный, однако не безнадежно. Напишем небольшой bat-ник:
@echo off

echo Все файлы в папке после шифрования/дешифрования будут удалены
echo Путь к папке с файлами:
set /P FoldPath=
cd %FoldPath%
for /f %%i in ('dir %FoldPath%\*.* /b') do (
	crypt++ "%%i" enc
	del "%%i"
)


Теперь мы можем шифровать массив файлов в какой-нибудь папке, удаляя оригиналы. Для дешифровки файлов таким же образом напишем подобный командник, в котором наш crypt++ будет вызываться с параметром dec. В этих командниках можно указать пароль, который не потребуется запоминать. Путь к этому командному файлу также можно указать в переменной PATH и пользоваться утилитой для большого количества файлов будет удобней. Теперь справедливости ради расскажу о неприятных моментах.

  • В AES-256 файлы шифруются блоками по 16 байт и размер зашифрованного файла всегда кратен этому числу. Если в вашем исходном файле число байт не кратно 16-ти, то в дешифрованном файле в конец допишутся байты со значением NUL. Хотя это не является повреждением файла. Это относится только к утилите, использующей AES-256.
  • Не был реализован шифратор/дешифратор для мобильных гаджетов. При скачивании файлов на другой ПК из облака, необходимо их дешифровывать.
  • Предложенный bat-ник не способен рекурсивно вызываться для подкаталогов указанной ему папки. К тому же имена файлов в целевой папке не должны содержать пробелов.
  • Шифрование AES-256 выполняется очень медленно. На моем Celeron скорость шифрования составила примерно 40 кб/с. Но вряд ли на более мощной машине можно получить сколь-нибудь удовлетворительную цифру.


Первые три проблемы вполне можно решить, если вдруг появится сильное желание.

Данные инструменты разрабатывались небрежно кодились в течении двух дней для личного пользования. Пользуюсь уже почти год и особых неудобств не испытываю.
Share post

Comments 18

    +6
    А не проще воспользоваться популярным encfs?
      0
      Учитывая, что речь тут идёт о Windows, — не проще. (Или предлагается экспериментальный encfs4win?)
        +1
        Для Windows есть boxcryptor. На работе использую linux и encfs, дома windows и boxcryptor — проблем с совместимостью не замечено.
          0
          BoxCryptor давно уже есть под Windows. Храню всё зашифрованно в дропбоксе и без всяких бубнов с батниками.
            0
            Насколько увеличивается трафик при использовании BoxCryptor + дропбокс?
              0
              Не замерял. Зашифрованный файл по объёму примерно такой же, как исходный.
        +5
        Линчую:
        for(int i=0; i<32; i++) AES256_Key[i] = 0;
        

        -Мммм… memset?
        -Чаво это?
        -Для забивки памяти рекомендуется функция memset!

        for(int i=0; i<strlen(argv[3]); i++) AES256_Key[i] = argv[3][i];
        

        Ба-тю-шки, потенциальный срыв стека. Вы с пользователя расписку кровью берете, что ключ у него не будет длиннее 32 символов?

        А еще, под такое дело есть strcpy.

        void ReadBlock(FILE *inFile, uint8_t *Block, bool *eofReached);
        

        В C++ можно передавать параметр по ссылке: void ReadBlock(FILE *inFile, uint8_t *Block, bool& eofReached);

        И глаз за звездочку не запинается, и рисков меньше.

        Ну и работа с файлом по байтикам — это очень медленно. Есть же fread, fwrite, которые читают/пишут блоком.

        Реализация самого шифрования видимо не ваша, уже хорошо.

        В целом: из явного криминала — только отсутствие проверки входных данных, ну и тормозной доступ к файлам. Гигабайты не шифровать.
          0
          Я так понимаю имена файлов больше 50 символов тоже могут вызвать переполнение стека?
          char bufEncPreName[50] = ENC_PRENAME; // "pic.jpg" -> "enc_pic.jpg"
          char bufDecPreName[50] = DEC_PRENAME; // "enc_pic.jpg" -> "dec_enc_pic.jpg"
          
            +1
            Да, переподнение будет, но не в этом месте. В этом месте порядочный компилятор ругнется, если в макроподстановке слишком длинная строка. Непорядочный таки устроит переполнение.

            Переполнение будет ниже, на конкатенации:
            outFile = fopen(strcat(bufEncPreName, argv[1]), "wb");
            
          0
          Под linux-os/2 был (или есть) замечательный aefs, который шифрует каждый файл отдельно. Я так понимаю, что подобно encfs. Под винду, к сожалению нет подобного решения (если кто знает — напишите!).
            0
            Вот неплохая статья была про шифрование в облаках habrahabr.ru/post/207306/
              +2
              После «а теперь напишем батник» пошёл читать срач в коментах. где срач?
              • UFO just landed and posted this here
                  0
                  Если вы расшифровываете по тому же пути, эта версия ляжет в историю изменений.
                    0
                    * Шифрование AES-256 выполняется очень медленно. На моем Celeron скорость шифрования составила примерно 40 кб/с. Но вряд ли на более мощной машине можно получить сколь-нибудь удовлетворительную цифру.
                    Первые три проблемы вполне можно решить, если вдруг появится сильное желание.

                    Т.е. вы считаете, что работу AES ускорить никак нельзя?
                    Тогда рекомендую ознакомиться с этой статьей habrahabr.ru/post/201114/
                      +2
                      Автор читает и пишет файлы побайтно. Ни о каком быстродействии и речи быть не может.
                      • UFO just landed and posted this here
                      0
                      gpg -c.

                      Only users with full accounts can post comments. Log in, please.