4 июня 2010 в 13:37

Шифрование важных файлов в Git

Git*
Допустим мы храним данные на некотором удалённом сервере в Bare-репозитории.
Если есть сомнения в честности обслуживающего сервер персонала, или мы опасаемся, что кто-то сопрёт наш проект, можно зашифровать избранные секретные файлы, представляющие особо секретные технологии фирмы и тем самым затруднить клонирование проекта.

Я не буду обсуждать согласование описываемого ниже метода с политикой и лицензионным соглашением бесплатных Git-репозиториев (а ля GitHub) — это дело частностей и вашей совести.

В реализации мы всопользуемся .gitattributes, staging, filters (фильтрами) и главой 7.2 Pro Git Book.


Вот как мы это будем делать.
Существуют два важных нам состояния:

image
State A.

image
State B.

State A — когда вы сделали выборку (git checkout) и работаете с вашей рабочей копией — в этот момент файлы должны расшифровываться и находиться в читаемом состоянии. Эта фаза контролируется фильтром stage.

State B — когда изменения ваше рабочей копии готовятся к отправке в репозиторий (git add) — в этот момент файлы должны быть зашифрованы до передачи в хранилище. Эта фаза контролируется фильтром clean.

Обычно фазы stage & clean используются для чего-то более мирного, например форматирование (indent) исходников по вашим вкусам и причёсывание их под принятые в организации стандарты при обратной отправке.

Перед отправкой в хранилище (локальное или удалённое) и для получения читаемых секретных файлов проекта необходимо произвести подготовку на машине разработчика.

Добавляем описание фильтров в ~/.gitconfig:

[filter "private"]
clean = ~/git_encode.pl
smudge = ~/git_decode.pl


В домашней директории у нас располагаются два скрипта.
Замените SecurePassword на свой пароль. Выберите на свой вкус метод шифрования из имеющихся в вашей сборке библиотеки OpenSSL. Мы использовали rc5.

~/git_encode.pl:

#!/usr/bin/env perl
use strict;
undef $/;
my $data = <STDIN>;
my $tmp = "/tmp/git.encode.$$." . rand() . ".tmp";
local * O;
open(O,">$tmp");
print O $data;
close(O);
print `openssl enc -rc5 -k SecurePassword -nosalt < $tmp`;
unlink($tmp);


~/git_decode.pl:

#!/usr/bin/env perl
use strict;
undef $/;
my $data = <STDIN>;
my $tmp = "/tmp/git.decode.$$." . rand() . ".tmp";
local * O;
open(O,">$tmp");
print O $data;
close(O);
print `openssl enc -d -rc5 -k SecurePassword -nosalt < $tmp`;
unlink($tmp);


Установите на эти скрипты право исполнения (в командной строке):

chmod +x ~/git_encode.pl ~/git_decode.pl

В рабочем каталоге подключаем защиту к необходимым файлам.
.gitattributes:

*.m filter=private
*.h filter=private
*.c filter=private
*.cpp filter=private


Теперь при отправке в хранилище выбранные файлы будут проходить через шифровщик, а при выборке через расшифровщик.
Чтобы Git не думал каждый раз, что файлы изменились, убедитесь, что шифровщик не «солит» (salted) файлы (используйте опцию -nosalt).
Alexey Galygin @MiF
карма
39,0
рейтинг 0,0
Самое читаемое Разработка

Комментарии (26)

  • +1
    А как будут выглядеть чейнджсеты? То есть получается как бы работа с бинарными файлами?
    • 0
      Проверил штатный git diff,
      к сожалению да, как двоичные файлы, но, возможно, это можно обойти дополнительными фильтрами.
      В крайнем случае, можно получить копии открытых (расшифрованных) версий файлов и сравнить их в индивидуальном порядке.
      Смысл метода скрыть не всё, а только что-то ну очень секретное.
  • –1
    А не проще TrueCrypt поставить и организовать хранилище на шифрованном разделе?
    • 0
      Да, это подойдёт для сокрытия всего. Но тогда хранилище уже не будет на сервере представлено в виде Bare-репозитория (тогда в этом уже нет смысла).
      Смысл скрыть именно несколько файлов и при этом оставить штатный доступ к Git.
      Если образ диска разместить на сервере — то сколько человек сможет с ним работать одновременно?
      Лично я использовал FUSE + SSHFS и монтировал AES-тома через SSH. Но пока диск у меня, остальные не могут с ним работать безопасно — это плохо кончится. TrueCrypt свободен от этой проблемы?
      • –1
        Если образ диска разместить на сервере, монтировать его и расположить на нем GIT репозитарий, то работа с GIT для всех будет выглядеть абсолютно прозрачно пока диск не размонтируют. Или, может быть, я вас неправильно понял? Может быть, смысл в том, чтобы никто не смог работать с некоторыми конкретными файлами в репозитарии?
        • 0
          Вопрос в том, где этот диск будет смонтирован (возможности TrueCrypt). Допустим, 100 разных человек в разных точках земли, смогут ли смонтировать этот диск и работать с репозиторием, так чтобы целостность данных была в порядке?
          Ограничения этого метода:
          1. Если внутри одной организации — то можно конечно расшарить один смонтированный диск между сотрудниками.
          2. На GitHub такое не пройдёт
          3. Возможна физическая порча репозитория (он уже не сокрыт за сервером, а вот он как локальный)
        • 0
          к сожалению, тогда владельцам хостинга теоретически станут доступны файлы на зашифрованном разделе, пока он смонтирован (т.е. они могут, по крайней мере легко, запустить соответствующий софт на сервере).

          Для предотвращения доступа владельцев сервера к вашим данным есть только два основных направления — усложнение доступа (нестандартные схемы, постоянный контроль софта и т.д.) и дешифровка на клиенте (причем возможен вариант, когда один из надежных клиентов становится временным сервером, а хостинг провайдера используется как простое хранилище). В статье описан второй вариант — в данном случае это наиболее простой и эффективный метод, жаль что ограничивает функционал на стороне клиента. Но первый вариант — не на столько надежен, как второй.

          p.s.
          • +1
            p.s. а если клонировать репозитарий уже от клиента, но без шифрования фильтрами, файлы будут переданы дешифрованными или зашифрованными?
            • 0
              Расшифрованными они будут только если установлены фильтры,
              внутри хранилища они лежат в виде двоичного мусора даже на клиенте у которого в рабочей копии открытый файл.
              Иначе получите двоичный закодированный файл.
  • 0
    Зачем скрипты на перле, если бы одна строка «openssl ...» сработала бы?
    • 0
      Может быть. Процесс эксперимента с фильтрами не сразу привёл к результату. Мне удобнее писать Perl-скрипты, вместо SH-скриптов, поэтому получилось именно так.
      • +1
        На больших файлах print `command`; даст не лучшую производительность, так как будет буферизировать всё в памяти. А запись «секретных» данных лишний раз во временный файл в /tmp вообще противопоказана.
        • 0
          По поводу /tmp — предполагается, что это Ваша машина (клиент).
          Иначе и редактировать файлы на ней не стоит.
          • +2
            Вы же за машиной не один работаете.

            Если уж секретный, то в home пишите, а то из tmp его быстро уведут.
            • 0
              К счастью, в конкретный текущий момент времени один. Сразу после использования файл удаляется. Но использование tmp в home поддерживаю всё равно.
              И как тут уже отмечалось, Perl скрипты остались от иследования фильтров.
              Можно, действительно, обойтись openssl в одну строку без обёртки и без временных файлов.
  • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Доверие доверием, а подстраховаться никогда не повредит.
      Дополнительное шифрование — это второй уровень защиты.
      К примеру, Вы платите за хостинг и размещаете там репозиторий.
      Насколько Вы доверяете хостеру и местным специалистам, который день и ночь шныряют по SSH?
      Это как замки в квартире — Вы можете их и вовсе не ставить, но тогда…
      А когда Вы их ставите, разве Вы живёте не в скомпроментированном мире?
  • НЛО прилетело и опубликовало эту надпись здесь
    • +1
      Если есть доступ по SSH и Гит на сервере установлен, то никаких проблем возникнуть не должно.
      • НЛО прилетело и опубликовало эту надпись здесь
        • 0
          Без рутовых прав нельзя.
          • +1
            теоретически, при наличии ssh и установленных зависимостей (некоторые можно самому поставить) можно попытаться установить все необходимое в домашнюю директорию, очень даже может быть что что-нибудь потребуется пересобрать с опцией --preffix=/home/username/ но что то мне говорит что геморою будет намного больше чем стоит любая самая вшивая vps.
          • +1
            На самом деле можно.
            Только не нужно ставить в директории не принадлежащие Вашему пользователю (например, в /usr, /usr/local).
            Просто переопределите prefix при configure.
    • 0
      Не скажу по поводу «заморачиваться», но лично я за практику — попробовать стоит по любому.
      Из моего опыта — удачно удалось развернуть Git на 301-м тарифе РуЦентра — там в SSH даже gcc есть — сначала собрал nginx, потом git, svn там из коробки идёт.
  • 0
    Итак, резюмирую укороченное решение шифрования-дешифрования с возможностью производить diff:
    Вместо Perl-скриптов и для работы diff в определении фильтра прописываем:

    [filter "private"]
    clean = openssl enc -rc5 -k SecurePassword -nosalt
    smudge = openssl enc -d -rc5 -k SecurePassword -nosalt
    [diff "private"]
    textconv = cat


    Для нужных файлов в .gitattributes:

    *.h filter=private diff=private

    При модификации .gitattributes на стороне клиента после клонирования, достаточно выполнить git stash для применения новых настроек фильтра smudge. Чтобы не было недоразумений, не забудьте добавить .gitattributes в хранилище.

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.