OpenPGP crypto key
Привет.
Я думаю над проектом устройства, реализующего необходимые для конфиденциальной переписки криптографические функции. Мотив в том, чтобы предотвратить доступ к хранилищу ключей с потенциально скомпрометированного компьютера. Вопрос – как организовать интерфейс взаимодействия устройства с хостом. В конечном счёте, хотелось бы получить решение, полностью совместимое с протоколом openpgp: формат ключей, сообщений, подписей и прочее. Чтобы мне не изобретать велосипеды, может быть, вы подскажете какие стандартные решения в этой области применимы? Читал, что есть стандарт PKCS #11, но пока не ознакомился с документацией. Он будет пригоден для моей задачи?
Спасибо!
Ссылки
[link1] https://www.pgpru.com/comment41042
[link2] https://www.pgpru.com/comment85024
[link3] https://www.pgpru.com/comment86061
[link4] https://www.pgpru.com/comment71148
[link5] http://forum.gsmhosting.com/vbb/f675/what-could-you-expect-gpgserver-1270346/
[link6] https://www.pgpru.com/forum/kriptografija/openpgpcryptokey/files?get=gpgremote-0.9b1.tar.bz2
[link7] https://www.pgpru.com/forum/kriptografija/openpgpcryptokey/files?get=gpgremote-0.9b1.tar.bz2.sig
[link8] http://idioms.thefreedictionary.com/with%20respect%20to
[link9] https://www.pgpru.com/razrabotki/gpgremote
Он решает ровно эту задачу. GnuPG и PGP поддерживают хранение закрытых ключей на PKCS#11-совместимых смарт-картах.
Токенов и так существует дофига (при том, что их безопасность — довольно-таки условная штука), а интерфейсов для работы с ключом из-под другой ОС или другого юзера в той же ОС нет. Лучше бы вы их сделали. Нужно, чтоб работа с приватным ключом велась под другой ОС, доступной по сети (допустим, на каком-то порту крутится демон). Клиент мог бы предоставлять демону данные на шифрование, расшифрование и подпись, но не мог бы заставить его выдать сам приватный ключ. И надо ещё интегрировать поддержку этого дела в тот софт, что завязан на PGP (mail-клиенты, jabber), чтоб прозрачно всё работало.
Если в новогодние каникулы не возникнет срочной работы, сделаю такую штуку. Единственно, поддерживать она будет только gpg, но не gpgme.
И это тоже сделаете? :-)
Если приложение использует обычный командный интерфейс gpg вместо линковки с gpgme, всё должно работать из коробки.
Решение видится следующим. Клиент-серверное приложение на питоне, используется простейший сетевой протокол а-ля telnet (никакого канального шифрования, его пользователь может навесить сам с помощью ssh-туннеля). Клиент, которым заменяется бинарник gpg, принимает набор команд и возможный ввод с stdin и без изменений шлёт серверу. Сервер отфильтровывает небезопасные команды (типа --export-secret-keys и таких, которые модифицируют связку, хотя скорее всего там будет настраиваемый белый список) и передаёт их локальному gpg. Полученный результат повторно фильтруется на предмет PRIVATE KEY BLOCK и возвращается клиенту. Клиент выводит данные.
Спасибо, понятно.
А если я ему передам на шифрование какой-нибудь третий приватный ключ, он его зашифрует? Или если слова «PRIVATE KEY BLOCK» будут в тексте, который надо будет зашифровать или подписать, он это сделает?
... к примеру, делаю запрос сделать --clearsign-подпись какого-нибудь приватного ключа.
Если какие-то внешне валидные штуки вдруг будут запрещены, в некоторых автоматических протоколах (типа tkabber XMPP[link1]) другая сторона потенциально сможет отличать обычных юзеров gpg от заSATtva'енных ⇒ брешь в анонимности.
<irony> Ой, и правда, если в jabber-клиенте дыра, и он почему-то не сливает закрытый ключ противнику, — это та ещё деанонимизация. </irony> Лол, а Вы хотели и рыбку съесть, и сковородку не запачкать? Но вообще под запрет должны попасть только реально небезопасные действия, которые программы-пользователи gpg и так не должны выполнять. Я даже пока не уверен, нужно ли в действительности отфильтровывать PRIVATE KEY BLOCK — это скорее перестраховка (тем более, что вывод может быть запрошен без --armor, а разбирать бинарный формат у меня нет никакого желания).
И я к тому, что перестраховка в некоторых случаях может дать тривиальный различитель. Пример с tkabber плохой, но, допустим, у нас есть некоторое приложение, работающее с сетью в сколь-нибудь автоматическом режиме. Сторона потенциального противника может добиться, чтобы я ему что-то подписал. Если вдруг оказывается, что мой клиент отправляет противнику все обычные сообщения, а после вставки в них определённой строки уже не отправляет, противник понимает, что моя версия gpg необычная.
К примеру, в почтовом письме абонент укажет где-то слова PRIVATE KEY BLOCK, а я должен буду их процитировать при ответе на письмо, подписать и отправить. Там, конечно, неавтоматически делается (поэтому пример тоже плохой), но смысл примерно в этом. Я клоню к тому, что стоит ли такое делать (перестраховку), если не знать всех подводных камней, где, кем и как такая обвязка может использоваться. Например, перестраховку можно сделать опциональной и отключаемой.
gpg не предназначен для анонимности путём сокрытия версий. Даже если там есть --no-emit-version, то я бы этому не доверял, у разработчиков стойкая неразличимость, скорее всего, не в приоритете.
Гость, я так понимаю, говорит о том, что если на стандартный ввод gpg возвращает нестандартный вывод (который может быть доступен противнику), противник может заключить, что пользователь использует gpg в нестандартном окружении. Получается достаточно уникальный профиль, снижающий анонимность до псевдонимности.
Да, или никакого.
Да, об этом и речь. Дело не в том, что противник узнает версию и тем самым сузит поиск, а в том, что если такой программой пользуются полтора анонима, то ваш профиль будет светиться везде и всюду (особенно если вы такое gpg будете использовать как в анонимном, так и в неанонимном своих аккаунтах).
Небольшой status report. Работаю над программой, осталось не так много. Увы, как бы мне того ни хотелось, полностью выдержать принцип KISS не удалось из-за поддержки обработки файлов — это потянуло за собой заметное усложнение кода. Плюс потребовалось более тонко разбирать аргументы командной строки, чтобы не сделать сервер уязвимым к раскрытию информации: в тривиальном случае клиент мог бы передать серверу путь к файлу в его (сервера) файловой системе, тот скормил бы его GPG и вернул клиенту.
Хорошо, будем посмотреть. Результат будет в виде чего? Питон-скрипт? Deb-пакет? Gentoo-ebild?
Скрипты и документация.
Раньше как-то не придавал значение такой штуке, но тут она, конечно же, всплыла во всей красе. Изначально была надежда, что если не вайтлистить опции типа --import, то связка будет фактически только для чтения. Хрен бы там! GPG настолько умён, что
читает мысли пользователяпарсит стандартный ввод в зависимости от контекста.Скажем, если кинуть ему в stdin ключ (не важно, открытый или закрытый), он автоматически импортирует его на связу(и), не задавая никаких вопросов. Более того, он сделает это, независимо от того, в какой части ввода поймает хидеры ключа. Зато если вызвать gpg -e, то ключ, он, конечно же не импортирует, а зашифрует.
Программу я всеми силами старался сделать context-agnostic. Единственная опция, являющаяся спэшл-кейсом в обработке — это --output/-o. Такой подход я считаю правильным, т.к. пытаться детально эмулировать поведение GnuPG в зависимости от контекста — всё равно, что прыгнуть в бездонный колодец; плюс GnuPG в любой момент может изменить своё поведение, открывая какие-то дырки на уровне выше.
Короче, как и думалось[link2] изначально, попытки выковыривать неудобные данные из stdin совершенно бесперспективны. Хотя лично мне не особо нравится, что клиент может
безнаказаннокидать серверу на связку какие-то левые ключи, всё-таки не вижу в этом большого риска,1 поэтому, если только кто-нибудь не сможет предложить элегантное решение, выведу модификацию связки из модели угрозы. В конечном счёте, на административном уровне решение существует: запускать сервер от пользователя, не имеющего доступ на запись файлов связок.К слову, из-за того же моего нежелания разбирать контекст возникают некоторые другие неочивидные отличия в поведении программы.2 В частности, если вызвать процесс gpg без параметров или с параметрами -s, -e и т.п., не передав ему ничего в stdin, он почему-то считает, что надо ожидать ввод из TTY и наглухо залипает. Подозреваю, что это можно как-то победить (хотя пока не знаю как), но до тех пор при пустом stdin передаю туда пустую строку — аналог cat /dev/null | gpg [...], из-за чего он может выплюнуть какой-то шифртекст или системную ошибку.
1 Я думал над этим, но не могу перевести такую "особенность" в вектор атаки, разве что в крайнем случае DoS, если клиент засрёт серверу связку/диск ключами.
2 Кстати, не нужно думать, будто в остальном поведение будет стандартным. Там куча отличий, специфических сообщений об ошибках и т.д.
вайтлиститьблэклистить опции типа --import, то связка будет фактически только для чтения.Fxd
Проверяете вывод на наличие там блоков PRIVATE KEY?
Вы издеваетесь что ли?
Вот вам три атаки[link3]. Могу раскрыть любую одну из них. Не продолжайте работу, пока не найдёте другие две.Да, это хорошее замечение. Правда, не знаю, как это будет выглядеть технически. Дело в том, что в ~/.gnupg хранится в т.ч. регулярно обновляемый random_seed. Наверно, на ~/.gnupg надо выставить права rx, а на pubring.gpg и secring.gpg — r.4
А разе в командной строке он не так же себя ведёт? Наберите gpg и нажмите Eneter — он будет ждать ввода с TTY. Пока не нажмёте Ctrl+C (прерывание) или Ctrl+D (корректное завершение потока), он так и будет висеть:
P.S. Основная мысль: понять, какие опции нужны GnuPG для автоматической работы с почтой и джаббером, и разрешить только их. Т.е., белый лист вместо чёрного. Ну, и как ещё одна организационная мера — иметь много связок, каждая для своей цели, не класть все яйца в одну корзину. Например, там, где происходит ручная работа с командной строкой и под доверенным пользователем, этими навороченными интерфейсами можно вообще не пользоваться.
3 Могут быть нюансы с выбором приоритетов, но я про это не в курсе. Если бы это делалось в командной строке, GnuPG бы предложил выбрать один из двух ключей, т.к. KeyID не фиксирует конкретный, или нет? Не знаю, как с этим будет работать автоматика, когда это вызывается джаббером или почтовой программой.
4 Если на ~/.gnupg будет rwx, атакующий не сможет поменять существующие pubring.gpg и secring.gpg, но сможет просто их стереть и вместо них создать свои новые с такими же именами.
вайтлиститьблэклистить опции типа --import, то связка будет фактически только для чтения.FxdBroken. :PТам впереди частица "не", которую Вы, видимо, не заметили. У Вас получается, что если --import не заблэклищен (т.е. разрешён), то связка будет только для чтения.
Нет, это излишне.
Это ещё вопрос, кто тут издевается. :) Всё, перечисленное Вами — косяки на стороне пользователя и клиентских приложений. Ну, ещё можно кошку высушить в микроволновке, а потом подать в суд на производителя за то, что
онакошка сломалась. GnuPG позволяет указывать ключи по полным отпечаткам, а если используете короткий keyID, да ещё без подписей, то просто дразните судьбу.Эти файлы лежат в homedir, а связки не обязаны находиться там же. Всё это настраиваемо как через gpg.conf, так и непосредственно в конфиге сервера: можно указать, с какими опциями ему вызывать gpg, независимо даже от того, что содержится в gpg.conf.
Разница в том, что при вызове из консоли есть тот самый TTY, из которого можно ждать ввод, а при запуске процесса — нет. Но, как уже сказал, причина может быть в моих кривых руках.
Нет, дело не в этом, просто смысл не уловил сразу. Замечение принято.
Ну найдите нам другие приложения. Как вашему tkabber'у ключ задать? Можно по полному отпечатку? Мой клиент требует 16-ричный KeyID, насчёт полного отпечатка я не в курсе.
И, в конце концов, весь смысл этого проекта — костыль для латания дыр на стороне пользователя и его приложений, да. Если дыр нет, можно считать, что ключ никто не похитит.
Правда, если глубоко копать, то можно вглянуть на проблему с другой стороны: если у атакующего есть права на выполнение произвольного кода и изменение конфигурационных файлов, то, тем более, у него есть права на чтение переписки из-под этого пользователя. Тут можно напереть разве что на то, что в конфиги и на связку будут внесены незаметные изменения, которые далеко не сразу будут обнаружены.
В большинстве клиентских команд указывается 8-значный KeyID. Считается, что отпечаток однажды проверили, а двух ключей с одинаковыми KeyID'ами на связке нет.
Цель проекта — не дать пользователю вытащить закрытый ключ; это такая смарт-карта "для бедных", если хотите. Подпорки и костыли для UI и программных интерфейсов в клиентском ПО — это настолько out of the scope, насколько вообще возможно.
Разумеется, читать текущую переписку никто ему не запретит, это ведь именно дырявое клиентское ПО или атакующий передаёт gpg данные для шифрования.
Что касается импорта, я выше писал, что с удовольствием бы его запретил, существуй для этого какое-то лаконичное решение. Обучение программы семантике опций gpg таковым явно не является. Более того, оно и недостаточно, учитывая, что ввод может быть чисто бинарным (т.е. в нём может и не быть никаких PRIVATE/PUBLIC KEY BLOCK). Поэтому административное решение с блокированием записи связок представляется мне вполне достаточным и элегантным. Найдёте лучше — милости прошу.
Пожалуй, соглашусь.
Хотелось бы понять по поводу вайтлистинга. Его поддержка будет? Чтобы руками можно было задать, какие конкретно команды gpg могут быть выполнены [возможно, вплоть до конкретных KeyID'ов] (а все остальные должны блокироваться).
Кстати, всё-таки больше, чем смарт-карта за счёт возможности работы в распределённом режиме — сервер может крутиться на любой удалённой системе.
Заложена изначально. Фильтрации keyID нет в виду отсутствия разбора семантики. Хотя добавить фильтрацию параметров, в принципе, возможно, хорошая идея.
Я не вижу, чем KeyID'ы (значения опций) принципиально отличаются от собственно опций. Если есть фильтрация по опциям, то там же можно зафиксировать и параметры этих опций.
GPGIndustries:
15-ое июня 2011-го уже прошло.
По сути, так и есть (технические детали несколько сложнее). Уже сделал.
Хех. Я обозвал поделие GPGRemote.
Тогда уж лучше назвать «GPG Remote» (раздельно), а сам исполнимый файл — как-то типа gpg-remote (по аналогии с gpg-agent, gpg-zip и т.д.).
Принято.
Remote — плохое слово, в IT оно обычно соседствует с такими словами как exploit и exploitable. Но, ладно, это уже придирки. Если будет дыра, будут стебать в виде «gpg remote is indeed so remote!» :-)
Значит, в очередной раз подтвердим "как корабль назовёте..." :)
Код готов, документация плюс-минус тоже. Хочу ещё немного потестить, дописать юниттестов. Выложу для публичного тестирования через пару дней.
Спасибо. На github'е будет или тут?
Здесь. Финальную версию скорее всего выложу на bitbucket.
Бета-версия вот:
file:gpgremote-0.9b1.tar.bz2[link6]
file:gpgremote-0.9b1.tar.bz2.sig[link7]
Тут же обнаружил небольшую ошибку: в конструкциях типа "--output -" одиночный дефис воспринимается как опция. Уже исправлено (пока только у меня). Ох уж эти спэшл-кейсы. :\
Впечатляет. И не подумал бы, что в, казалось бы, такой простой задаче требуется так много кода.
Английский в README:
→ variety of reasons? Я сам не знаю.
Я бы так сделал.
Вместо intend лучше plan или want. Это более формально. Intend — это ближе к «намереваться, замышлять», слишком художественный смысл (хотя тоже используется в тех. текстах).
Не уверен, что это называется self-contained, хотя я понял, что вы хотите сказать. Обычно пишут что-то типа stand-alone.
Вот как-то так я бы написал. Оборот to be to там напрашивается сам собой, и, как нас учили, надо писать не "о", а "что". Не описательно, а конкретно.
Мне кажется, в этих случаях все пишут overwritten (параметр переписывается новым конфигом, а не "отменяется",
да ещё и в юридическом смысле поди).However лучше всегда ставить в начало. По правилам, после него всегда запятая. Вроде так.
Иначе рунглиш.
Слишком нефорамльно и художественно. Техницизмы: remind, recall, take into account, note, notice.
У "additional" есть слишком "additional" смысл, и если вы не о нём, то лучше сказать another.
However, this requires... Я не уверен про this vs it, но чаще пишут именно it.
А не with respect to?
Кажется, нетехническое и неуместное слово — раз, смысл я с первых прочтений не понял — два.
Рунглиш. Which — это наше всё, нельзя им злоупотреблять. Это только мы его в каждое предложение суём по поводу и без.
По-моему, запятая не нужна: "а и b", хотя "а, b, и c". Кажется, так.
Жаль.
Язык очень хороший (поделитесь с unknown'ом и gegel'ем, им явно не хватает), но много где, на мой вкус, слишком неформальный и гуманитарный. К математическим объектам у вас применяются слова, которые обычно используются для описания вещей.
Надо бы ещё сам код потестить, и можно ждать
бетугамму с дельтой. :)+remember
Непосредственно логики там не так уж много. Если выкинуть комментарии (aka docstrings), дублированный кусок кода сетевого интерфейса и весь обвес с логами и обработкой ошибок, объём сократится раза в два.
Правильно, как есть.
(comprised ofthat includes STDERR, STDOUT, exit code, as well as newly generates files)is sent back to client.Разница между "состоящий из" и "включающий" в том, что второе — implicitly открытый перечень ("включает это и, возможно, что-то ещё"). Первоначально написал тут именно "includes", но позднее при правке заменил ради большей однозначности.
Тут речь о том, что не имеют зависимостей в виде внешних модулей (аналог статической линковки в C/C++), это общепринятый термин.
Тут неточность в моей формулировке привела к тому, что Вы неправильно поняли весь пассаж — "overridden" относится не к конфигу, а к пути, где программа будет его искать (т.е. как в предыдущем абзаце). Исправил.
Это одно и то же. Например.[link8]
whichthey may contain sensitive cleartext dataВ данном конкретном случае употребление оправдано.
Обращал внимание, что англоязычные ставит запятую даже в перечислениях из двух элементов. Вероятно, это распространённая ошибка — глянул сейчас правила, и, формально, там то же, что и в русском: серия из трёх и более либо сложное предложение.
С остальным согласен, спасибо за замечания.
Это относится к случаю, когда клиент и сервер находятся на разных машинах. В противном случае, если настроен gpg-agent с графическим pinentry, вылетит
птичкаокошко для ввода пароля. А по поводу удалённого вызова см. один из пунктов TODO. У gpg-agent вроде бы есть какой-то IPC-интерфейс, но в деталях не разбирался. Меня больше смущает тот факт, что парольная фраза пойдёт через питонокод, а у него безопасность данных в памяти отсутствует как класс (как у всех интерпретируемых языков, собственно), т.е. "забыть" пароль не удастся, он там и будет торчать в памяти сервера,пока ОС не сольёт всё в своп. Так что пока не уверен, стоит ли вообще связываться с передачей паролей.Запостил в репозиторий: https://bitbucket.org/sattva/gpg-remote
Имхо, как раз includes — включение без конкретизации, всё ли это. В иных случаях используется formed by или consists of. Правда, опять же, это больше для вещей (как и comprize), а не объектов. Для последних используется что-то уместное для конкретного случая (to be или др. глагол). Наверно, я бы в вашем случае написал consists of, хотя не исключено, что есть более удачные варианты.
Так я ровно об этом и пишу. :) Касаемо замечания относительно comprized, это уже по большей части вкусовщина, чем конструктив. Доки уже совершенно понятны, и они меня на самом деле меньше всего волнуют — куча функций совсем не покрыта тестами.
Да, упустил я. :) В общем, больше пока замечаний нет.
Сделал специальную страничку[link9], дальнейшее обсуждение можно вести там. Также зафиксировал вторую бету с несколькими незначительными изменениями.