Окружение
Изначально предполагается наличие шифрующего софта на компьютере. Естественный выбор использовать openssl. В линуксе он есть по умолчанию. В windows он идет в комплекте с mingw в инсталяции git для windows. Единственное о чем нам надо позаботиться под Windows, чтоб папка в которой openssl находится (например «C:\Program Files\Git\mingw64\bin\») оказалась в переменной среды PATH. Тогда нам не придется создавать дополнительные утилиты (как это рекомендуется в статьях про шифрование в гите) и вся конфигурация намного проще.
Настройка git
Теперь займемся магией создания аттрибутов в git. Для начала мы должны разобраться с тем, что именно мы хотит шифровать в дереве. Если вы матерый параноик, вроде меня, то вы решите шифровать всё. Создадим файл в корне пустого репозитория .gitattributes:
* filter=openssl diff=openssl
.git* !filter !diff
init.txt !filter !diff
Если вы не настолько параноидальны, можете заменить вилдкард на *.java или *.cpp по вкусу.
Зачем init.txt? Сделаем небольшую памятку для себя, чтобы в случае клонирования репозитория не приходилось судорожно искать инструкцию в интернете. Кроме того, её можно весьма успешно использовать как шеловский скрипт для инициализации криптования в свежесклонированной копии.
Теперь создадим упомянутый файл init.txt:
<code>#This is protected repository. To initialize it you need: # # git clone -n https://github.com/<your_project_name> # git checkout tags/init # Then execute in shell: # . init.txt <password for repository> [ -z "$1" ] && echo "Argument required: <password>" && return git config filter.openssl.clean "openssl enc -base64 -aes-256-ecb -S 123456789 -k $1" git config filter.openssl.smudge "openssl enc -d -base64 -aes-256-ecb -k $1" git config diff.openssl.textconv "openssl enc -d -base64 -aes-256-ecb -k $1 2&>/dev/null || cat" git checkout master</code>
Убедившись в том, что git и openssl доступны в путях мы запускаем файл как и показано в комментарии (Если вы находитесь в Windows это надо запускать из git-bash).
. init.txt my_repo_pass
Или же просто руками запускаем 3 команды git config из этого файла заменив $1 в строке на пароль для репозитория.
Теперь добавим это всё в репозитарий:
git add .
git commit -m "protection initialization"
git push
git tag init
git push --tags
Вуаля, у нас всё готово к работе. Теперь мы можем добавлять новые файлы и они будут автоматически криптоваться.
Интеграция с Intelij
Теперь самое интересное. Если вы создадите закриптованный java проект на github и начнете с ним работать вы очень скоро заметите, что гитовый плагин в IDE упорно не хочет сравнивать файлы с предыдущими версиями. Это происходит из-за того, что intelij подтягивает предыдущие версии файла из репозитория с помощью команды git show. А теперь внимание: команды git show и git format-patch не используют фильтры по-умолчанию. Для этого необходимо им указывать опцию --textconv. Заставить это делать сам гитовский плагин я не смог, поэтому я сделал маленький враппер для git и указал его в настройках. Он автоматически добавляет эту опцию для команду show.
git4idea.bat
@echo off
set ARGS=%*
"C:\Program Files\Git\bin\git.exe" %ARGS: show = show --textconv %
Вариант для линукса (к сожалению не проверялось):
#!/bin/bash
export ARGS="$*"
git "${ARGS/ show / show --textconv }"
Теперь, надеюсь, тема раскрыта.
Комментарии (46)
arandomic
14.10.2017 14:501. Технический аспект.
Отлично. У нас все зашифровано и любое малейшее изменение в файле ведет к полному изменению его зашифрованной копии.
Теперь посмотрим как работают pack-и git'а.
Они стараются хранить diff-ы файлов, чтобы предотвратить рост размера репозитория.
Проведите эксперимент — создайте два репозитория. Один в зашифрованном виде, другой — в незашифрованном.
Положите в них один и тот же файл размером в 50mb (для наглядности)
Измените в файле один символ и сделайте коммит.
Повторите это действие несколько раз. (На обоих репозиториях синхронно)
Теперь сделайте команду git gc на обоих репозиториях и сравните размер.
2. Моральный аспект:
«Если вы захотели воспользоваться публичным ресурсом вроде GitHub или GoogleDrive для хранения своего репозитория, но при этом не готовы делиться со всем миром результатами своего труда, то вам поможет»… приватный репозиторий от Github или собственный git-сервер.
Шифруя открытые репозитории, вы нарушаете свое соглашение с GithubSly_tom_cat
14.10.2017 17:54Второй пункт почему то мне на ум пришел самым первым.
Не понимаю зачем создавать публичный, открытый репозиторий и хранить в нем шифрованный контент.ZyXI
14.10.2017 19:54По моему мнению создание репозитория на github и хранение на нём шифрованных данных вполне логично:
Автор почему?то привёл в пример именно шифрование кодовой базы. Но вы можете, к примеру, сделать на этой основе свой парольный менеджер и хранить так пароли, при этом храня и историю их изменения, не опасаясь что?то случайно удалить.
Ещё так можно публично хранить все.файлы скопом — в том числе .ssh — в зависимости от того, к чему именно вы имеете доступ такое может быть вполне приемлемо.
В моём первом предложении не случайно отсутствует слова «публичный» и «открытый». Шифрование репозитория просто значит «я не доверяю github, но не готов поддерживать свой сервер». Ничто не мешает взять и также зашифровать приватный репозиторий.
Заметьте, автор написал «воспользоваться публичным ресурсом». А не «публичным репозиторием».
Sly_tom_cat
14.10.2017 20:45О, шикарно, вы случайно не адвокатом работаете?
Шифрование кодовой базы в публичном репозитории Github-а, у вас чудесным образом превращается в шифрование паролей на всего лишь публичном ресурсе…
Ну да, конечно, свои шифрованные пароли просто обязательно хранить в общедоступном месте, других мест — конечно же нет. :)
И вот уж совсем интересный поворот — предложение шифровать приватный репозиторий… м-да… :/ZyXI
14.10.2017 22:10А вы не политиком? Я вот не вижу, чтобы автор писал про публичный репозиторий, не покажете? Может ещё скажете, что там же упомянутый GoogleDrive стал внезапно публиковать файлы по?умолчанию? А в начале комментария про пароли я вообще написал «Автор почему?то привёл в пример именно шифрование кодовой базы» а не «Автор на самом деле имел ввиду шифрование паролей».
Кроме того, где ваши предложения про «другие места»? Почему вам не нравится шифрование приватных репозиториев? В отличие от вас, я написал, какая может быть мотивация за этим действием.
В общем ваш комментарий практически не содержит смысла, но зато содержит пачку ораторских приёмов. Политику бы определённо подошёл.
Sly_tom_cat
15.10.2017 00:14Да видимо адвокат. На одно возражение — ушат претензий и обвинений....
Osykov Автор
15.10.2017 22:15У вас такая живая беседа задалась, что даже не хочется встревать :)
По первому комментарию — за использование шифрования приходится платить. Как и за всё хорошее в этом мире.
По второму — едва ли хранение репозитория на гуглдрайве противоречит соглашению с гуглом. Зато ему полностью соответствует индексирование вашей почты и содержимого гуглдрайва гуглом. Я не желаю, чтоб мои файлы с паролями попадали в базы данных гугла.
А по поводу гитхаба — я предлагаю вам указать на пункт соглашения, который мешает мне шифровать некоторые файлы репозитория. Я читал это соглашение — а вы? А по поводу необходимости — есть некоторые случаи (например связанные с правами на код) которые могут помешать выложить часть кода в чистом виде. Если у вас проект находится на границе лицензий и какая-то его часть, к примеру, не может быть GPL. А если у вас подобной необходимости никогда не было, то непонятно почему вы развили такой спор под этой статьей.Sly_tom_cat
15.10.2017 22:51GPL как раз не позволяет скрывать код. Никакой. Ни свой ни встроенный.
Но если вы хотите скрыть весь код (а именно это предложено в статье) то зачем тогда его располагать на публичном ресурсе?
Про гуглодрайв — речи не было. В статье именно на гитхаб заливается шифрованные исходники. Потому и тред развернулся...
Кстати держать репы в облаках — не очень удобно. Яндекс например упорно стирает права на исполнение файла (под linux).
Osykov Автор
15.10.2017 23:04Код распространяемый под GPL действительно не позволяет изменять предоставляемый код. Но что, если у вас в репозитории есть и какая-нибудь утилита, которую можно использовать но нельзя предоставлять в виде кода по условиям лицензии? А всё, что помещается на гитхаб автоматически соответствует его лицензии.
Как это «про гуглдрайв не было речи», когда он упомянут ещё в аннотации? Фактически изначально я шифрование поднимал именно на гуглдрайве а на гитхаб переехал значительно позже.
К слову про гуглдрайв — на днях выложу статейку про «родное» криптование документов в гуглдоксах. Работает и на телефоне.
ZyXI
15.10.2017 23:28GPL позволяет скрывать весь свой код — пока вы не начали распространять программу, скрывайте сколько хотите. Можете сделать свой закрытый форк чего угодно с лицензией GPL, главное — не предоставляйте его клиентам, они могут потребовать от вас код, а вы не можете в ответ потребовать NDA: https://gcc.gnu.org/ml/gcc/2001-07/msg01342.html.
deniskreshikhin
14.10.2017 20:17У нас все зашифровано и любое малейшее изменение в файле ведет к полному изменению его зашифрованной копии.
Если шифровать построчно, то такой проблемы нет.
Моральный аспект
На GitHub не обязательно хранить код. Можно зип-архивы, бинарки и т.д. Плюс это еще и статический хостинг сайтов.
ZyXI
14.10.2017 22:20Если шифровать построчно, то вам понадобится сравнительно сложный скрипт построчного (де)шифрование и понимание криптографии на достаточно высоком уровне, чтобы скрипт не сделал шифрование хуже, чем бесполезным: напоминаю, что если шифровать именно код, то там будет очень много весьма предсказуемых строк вроде «пустая строка», «строка с пробелами и закрывающей фигурной скобкой» и какие?нибудь
#!/usr/bin/env bash
. Одна ошибка в скрипте и эти строки выдают злоумышленнику пароль, всего лишь за возможное уменьшение размера репозитория.deniskreshikhin
14.10.2017 22:31Да вполне тривиальная вещь на самом деле https://ru.wikipedia.org/wiki/Galois/Counter_Mode
mayorovp
15.10.2017 11:50Не пойдет: при вставке строки все счетчики поплывут.
deniskreshikhin
15.10.2017 13:21-1Вот пожалуйста, небольшой скриптик https://gist.github.com/kreshikhin/af92121bf2fb5770562b5ff2952fa048
Берём текст qsort на Haskell:
quicksort [] = [] quicksort (x:xs) = quicksort small ++ (x : quicksort large) where small = [y | y <- xs, y <= x] large = [y | y <- xs, y > x]
Меняем в третьей строчки y <= x на x >= y:
quicksort [] = [] quicksort (x:xs) = quicksort small ++ (x : quicksort large) where small = [y | y <- xs, x >= y] large = [y | y <- xs, y > x]
Прогоняем через стандартный AES-GCM (https://www.npmjs.com/package/node-aes-gcm) и сравниваем результирующий base64 по чанкам в 16 байт:
0 kZIMx/mCB6iNQFsd => kZIMx/mCB6iNQFsd 1 WVHSXTgttVxia1ka => WVHSXTgttVxia1ka 2 O61ub9b0SDdOhmpT => O61ub9b0SDdOhmpT 3 4SbidSozTV7YAm5V => 4SbidSozTV7YAm5V 4 w6qNv691PuD0VvrE => w6qNv691PuD0VvrE 5 MbCg+/2AH+T00sCE => MbCg+/2AH+T00sCE 6 0cqUOqVS/0F6uYaW => 0cqUOqVS/0F6uYaW 7 puAtHwP3eDzjBIwE => puAtHwP3eDzjBIwE 8 gnt8zMhOLJ5wMSef => gnt8zMhOLJ5wMSef 9 ZhcNUbidyJhAHvBc => ZhcNUbidyJhAHvBc 10 pPOKCjs67wX09t2R => pPKKCDs67gX09t2R changed!!! 11 yBuEPwNZFotmDESy => yBuEPwNZFotmDESy 12 p9P8uwIe8Rru84H0 => p9P8uwIe8Rru84H0 13 BxSGUwFBZm+Nl8TJ => BxSGUwFBZm+Nl8TJ 14 XE0= => XE0=
Изменился только 10 чанк, остальные чанки — ни до, ни после не меняются.
a5b
14.10.2017 22:28В данном случае шифруется поблочно — режим ecb, сжатие не включено (openssl enc -d -base64 -aes-256-ecb -k $1; https://www.openssl.org/docs/man1.0.2/apps/enc.html) — https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_.28ECB.29 — т.е. каждый блок данных в 128 бит (16 байт) для данного ключа однозначно отображается в какой-то другой 16-байтный блок (еще в начале зашифрованного файла 8 байт Salt и в конце файла добавляется 1 блок PKCS#7 padding). Замена 1 символа в середине файла приведет к изменению 1 блока; добавление символов в середине файла приведет к сдвигу последующих данных, но добавление 16 байтов в середине (или кратного количества) не изменит последующую зашифрованную часть файла. Из-за base64 и переноса строк каждые 64 символа (хотя в вики заявляют про 80 символов) в строке помещается 3 блока по 16 байтов, поэтому добавлять или удалять текст из середины файла лучше размерами, кратными 48 байтам.
Режим ecb не самый безопасный — одинаковые блоки открытого текста в каждом файле всегда кодируются в такие же блоки шифротекста — см https://crypto.stackexchange.com/questions/20941/why-shouldnt-i-use-ecb-encryption "Why shouldn't I use ECB encryption? / You should use any authenticated encryption mode, such as GCM, EAX or OCB.) и классический bmp "The ECB Penguin"
.
Да, зато получается "We are using AES-256 ECB mode as the encryption algorithm, as it turns out a deterministic encryption works best with git (we will explain later)." — https://gist.github.com/dstrctrng/3430823
deniskreshikhin
14.10.2017 22:37Ага, ну это довольно известная проблема ECB. Но для построчного шифрования этот режим и не нужен. Т.к. важно не то что бы одинаковые строки шифровались одинаково. А одинаковые строки в том же месте.
a1888877
15.10.2017 22:451. По первому моменту шифрование это ещё и оверхейд на скорость работы. Но такова цена безопастности, шифрование не бывает бесплатным.
2. Нужно понимать, что шифруется не всё, а указанные маски. Даже для opensource шифрование к примеру ключей подписи бинарников — весьма актуально. А хранить их в репозитарии со всем остальным удобно.
bores
15.10.2017 22:47Вопрос по пункту 1.
Вы случайно не путаете git и mercurial?
https://git-scm.com/book/ru/v2/Введение-Основы-Git
arandomic
16.10.2017 14:08+1Так. UPD:
— Оба пункта относятся к шифрованию по маске **/*, т.е. полному шифрованию репозитория пофайлово.
— Как мне подсказывает KOLANICH в ToS Github нигде явно не зафиксировано, что в public репозиториях нельзя использовать обфурскацию/шифрование, так что стоит говорить лишь о fair use.
Также travis ci напрямую советует использовать шифрование.
Если, скажем, шифровать какие-либо ключи для travis ci — то оба мои возражения отпадают.
Технический — т.к. незашифрованные ключи обладают теми же свойствами, что и зашифрованные — они меняются не познаково, а целиком.
Моральный — т.к. кодом мы всё еще делимся, просто при этом защищаем наш pipeline от вандалов.
askv
14.10.2017 15:55Dreyk
14.10.2017 22:17в воображении опровержителя криптоманьяка, те кто хотят взломать ваши пароли, находятся рядом с вами
askv
14.10.2017 22:57Те, кому очень надо, найдут :)
Dreyk
14.10.2017 22:58не знаю, как криптоманьяки в общем, а я больше защищаюсь от "ковровых бомбежек", а не целевых ударов
Osykov Автор
15.10.2017 23:28когда есть опасность того, что найдут, мой товарищ делал два связанных ключа и один отдавал директору второй его заму. И админа можно потом хоть вечность пытать.
fRoStBiT
14.10.2017 20:30Использовать это для ограничения доступа к коду в публичном репозитории — как-то плохо.
Использовать для других целей — слишком много информации утекает в открытом виде — имена и размеры файлов, сообщения коммитов.
Но подход интересный, не думал, что в Git есть что-то подобное.Sly_tom_cat
14.10.2017 20:49Простите, но вы кажется не поняли.
В git шифрования нет, но гит настолько гибкий инструмент, что небольшими усилиями в него можно хоть черта в ступе прикрутить. И автор прикрутил шифрование.
Как по мне так это скрещивание бульдога с носорогом…ZyXI
14.10.2017 21:53Ага, гибкий. Но даже аналога фаз из mercurial почему?то нет, не говоря уже о чём?то более фундаментальном вроде changeset evolution. Для чего?то простого можно обвешаться атрибутами и хуками, и это гораздо проще, чем написать дополнение для mercurial или даже делать шифрование на «фильтрах» (аналогично атрибутам, вот только настройких не хранятся в репозитории), но если вам, к примеру, захочется иметь возможность объявлять «этот коммит опубликован, его нельзя менять (в т.ч. удаляя из ветки)» и «этот коммит не опубликован, его можно менять», то вам понадобятся, во?первых, хуки, во?вторых, отдельный сервер синхронизации фаз: средств добавления метаданных в коммиты нет вообще, тем более средств добавления метаданных, которые не учавствуют в расчёте хэша и могут быть изменены позднее.
Конкретно с фазами проблема частично решается запретом force-push в «публикующих» репозиториях, но это, во?первых, менее удобно для пользователя, а, во?вторых, поднятие проблемы, решаемой фазами, не является целью комментария вообще. Приведя данный пример, длительное время существовавший в виде дополнения я просто показываю, что дополнения в mercurial обеспечивают намного бо?льшую гибкость, чем позволяет архитектура git.
Sly_tom_cat
15.10.2017 00:16Простите, но казалось бы: а причём тут mercurial.....
avost
15.10.2017 10:52-1Видимо потому, что если копнуть чуть глубже данного чуть менее, чем малополезного примера, то оказывается, что "настолько гибкий инструмент" не настолько уж и гибкий, что даже меркуриал его кроет ;)
Sly_tom_cat
15.10.2017 12:16-1Ну а бык корову кроет… Это конечно тоже важный факт в свете темы топика :)
avost
17.10.2017 14:56Ну, это был ответ на сентенцию, — "настолько гибкий инструмент", а не на исходный топик. И сентенция эта вашего авторства, так что претензии по важности фактов — всё к вам.
Dreyk
14.10.2017 22:20pass как раз так и делает для хранения паролей в гите
arandomic
16.10.2017 14:57Хм. Судя по всему он просто делает checkout из зашифрованного гита в dev/shm
Вопрос: достаточно ли сделать rm -rf из dev/shm, чтобы гарантировать, что никто больше из этой области памяти не прочитает наши пароли?
Беглый гуглинг не дал результатов.
Просто всяческое crypto-по активно использует zeromemory и прочие гарантии удаления данных из памяти.
Как с этим в dev/shm?
С другой стороны — это супер идея, «я ее джва года ждал». Хранить под гитом пароли! Спасибо за наводку!
Ensay
15.10.2017 21:46В конце статьи про интеграцию с интеграцию с Intelij.
А как это в Linux сделать?Osykov Автор
15.10.2017 21:54аналогично — вам нужен шеловский скрипт который будет вызываться вместо оригинального гита. Примерно такой:
#!/bin/bash
export ARGS="$*"
git "${ARGS/ show / show --textconv }"
python273
15.10.2017 22:25Keybase недавно запустили шифрование git:
https://keybase.io/blog/encrypted-git-for-everyone
You can have as many repositories as you want, but the total for your personal repositories can't exceed 100GB.
:)What if we're living in a simulation?
Keybase offers no guarantees against sophisticated side-channel attacks by higher-level entities.Osykov Автор
15.10.2017 22:36Да, с неделю назад. Надо посмотреть насколько стабилен сервис. Пока у меня пельмени в холодильнике старше. Кроме того для этого используется их приложение, что добавляет звено в цепочку и уменьшает её надежность. Кроме этого гитхаб это в том числе и вики/сайт/трекинг задач и промо-возможности. От добра добра не ищут.
ekadesign
Нюансы. Отредактируйте, пожалуйста
lostpassword
https://habrahabr.ru/conversations/Osykov/