Статьи

Хранение секретов в безопасности с GnuPG

GnuPG расшифровывается как GNU Privacy Guard , форма криптографии с открытым ключом, основанная на стандарте OpenPGP. Эта статья покажет вам, как выполнить несколько важных задач с GnuPG с использованием PHP и расширения GnuPG PECL.

Для наших целей, как человеку, который хотел бы передавать и получать зашифрованные сообщения, вам необходимы три ключа: ваш собственный открытый ключ, ваш личный ключ и открытый ключ человека, с которым вы хотели бы общаться.

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

GnuPG также служит средством проверки подлинности незашифрованных данных с помощью зашифрованных подписей, но эта тема здесь не рассматривается.

Обсуждаемое здесь расширение GnuPG зависит от установки GnuPG на любой машине, с которой вы работаете, а также от конфигурации учетной записи пользователя, под которой будет выполняться код. Приведенные здесь примеры предназначены для запуска из командной строки и будут взаимодействовать со средой GnuPG пользователя, который их запускает. Это должно быть тривиально, чтобы расширить понятия здесь, чтобы работать от веб-скрипта.

Генерация ключей

Прежде чем вы сможете что-либо сделать с GnuPG, у вас должна быть пара секретного / открытого ключа. Хотя расширение PECL не позволяет вам создавать эти ключи прямо из PHP, вы можете легко сделать это из командной строки с помощью команды gpg или дружественного интерфейса с графическим интерфейсом для любой выбранной вами ОС. В Linux все, что вам нужно, это:

  gpg --gen-key 

После ответа на несколько простых вопросов о вашей личности, выбора ключевой фразы для использования вашего личного ключа и принятия значений по умолчанию для всего остального будет сгенерировано ваше кольцо ключей GnuPG. Брелок хранит ваши ключи и ключи всех, с кем вы планируете взаимодействовать.

После того, как сгенерировано, ваше кольцо ключей автоматически заполняется вашими первыми закрытыми / открытыми ключами. Вы должны экспортировать копию ваших открытых и закрытых ключей и хранить их в надежном месте, чтобы вы могли повторно использовать одни и те же ключи во всех будущих взаимодействиях с GnuPG. Вы также можете рассмотреть возможность публикации своего открытого ключа на сервере ключей, чтобы сделать его безопасным для всех, кому он нужен. Дополнительную информацию об инструментах и ​​ключевых серверах GnuPG можно найти на веб-сайте gnupg .

Экспорт ключей

Один из способов экспортировать ваш открытый ключ GnuPG — это PHP. Однако прежде чем вы сможете выполнить экспорт, вы должны найти «отпечаток» ключа вашего нового открытого ключа. Каждый ключ в вашем наборе ключей будет иметь отпечаток пальца, который используется в качестве уникального идентификатора. Чтобы перечислить их все, gnupg_keylistiterator() объект gnupg_keylistiterator() :

 <?php $iter = new gnupg_keylistiterator(); foreach ($iter as $fingerprint => $user) { print "$fingerprint: $usern"; } 

Для набора ключей пользователя с именем «testuser» на моей рабочей станции приведенный выше код приводит к следующему выводу:

  6436010991C352981F95F9A5D5AF916244CD449B: тестовый пользователь (это тестовая учетная запись) <[email protected]> 

Сам ключ является двоичными данными, поэтому для фактического кодирования и печати версии открытого ключа в формате ASCII нам понадобится новый код:

 <?php $gpg = new gnupg(); $export = $gpg->export("6436010991C352981F95F9A5D5AF916244CD449B"); print $export; 

Это создает новый объект gnupg и использует метод export () для экспорта открытого ключа, соответствующего предоставленному отпечатку. В моем случае ключ тестового пользователя:

  ----- НАЧАТЬ PGP PUBLIC KEY BLOCK -----
 Версия: GnuPG v1.4.2 (GNU / Linux)

 mQGiBFDP4 + cRBACupVdbSBVa5wLjKFoELiS9IunzQA6hj2P1jCYmXtwSPwvvrXRX
 LqhpkmXmWrHvo + 4WW8aDjI2csuh8z4gNB + YGkaB3iKZxyhdazKco0R1BU7fjPrUn
 4iqVqkpaixcdMVDPkjjBTJDEdjxWWieErSzbzkjy8wuTJR + lAVFWTcuTOwCg9WAg
 bLwpPIlcULQ + D / l3sLt2AaED / jgdcTvMsVG96xZGWT9bewl / HVX + 2ZpCWIkbE34E
 AABS8c9hwNEz3QvkEqoxcf5sC8ujtvTf3Gky4E6h4KZrpCZuZ8kFRQiAhqP6XwNi
 8jJM0BK8ooYPFP4UsfRQImc4XczL / njtwpwJ8wX2UOb7oglJB5acMulvzpD4cRvK
 FkqIA / 9NzGFExUeJeJ8b6GC17KDOIHfBwlrcGvc85c574fUVekV9jGGaAzl6i89O
 OIWQCELH9s8quTA23tDeMcHRwUMHAYxh7lf2stoJmwz0IySpUCkmxcUhB5TIzBOB
 jHifGAlJKby6gNJhlvghTxXlVGsQiM14JLJo2 + hS2qMc17vp77QyVGVzdCBVc2Vy
 IChUaGlzIGlzIGEgdGVzdCBhY2NvdW50KSA8dGVzdEB0ZXN0LmNvbT6IYAQTEQIA
 IAUCUM / j5wIbAwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJENWvkWJEzUSb6iIA
 nRhCMJ3CN + 1QXSD2zAtsoWgVebqZAKDLp1636WZ3XZAIVOlHBnpMTfcdA7kCDQRQ
 г + PwEAgAkRnVYvmbpkGCCU8T56Wh2 + jMA5GVPbPuyqmprfvgrt7yp9EEXfXRrGVA
 KYMbFDU4 + Vdc2U9Wm / T6P7McvI3dJARWOD6NeqOh + k6yTYxH + qznsU2d / 7 + Vugfx
 zxVXtllhpnyWc5AlAr6yo98UdjO + q5RNM3fzSdjHth + MCJqEBfkyTui2VN9odnnS
 IkDFHJyVcaUfQ580RpLWllwAC3 + Urntc02S6xxEr03fKIe / wuhXC9gpG5lWu3hyj
 k0PlsSh55w5gb4zF3Q2yDbToAuvSg1My0ytIPddmjjBx8gs4PCnB + 48R52jsT / Ui
 Ju6j83Ddy1Ph1cnalChIpMit2Hm40wADBQf + J, + NRhzLByj3YRsRK9ohZ0dm1 + СМУ
 S86Xv676IQMgTzohFCAicnFZtTJx6N35pox / azOOGxAoof79TPv1r897bysAXjmu
 qjW2mMpAfhnNY18Wf2SB + R7oYsID / z4fOQltyX54z8Fi40OO6UtI1X3Lh4KGzhUK
 AnkgVeYGxupiK2HHtxeknEiKuAY + RXiQRYIC8YgAZboKqbWt8WVSMwctLbtRgXQC
 VlkcZzwPk + mPocxYcnID + mZgIpwX0 / + Zs4OOlyrf1k1oI6zQA7tJ + etGugtee78j
 e8gub9CYvyCJMFM3pI5OEKC9BRSjPjgSw / 6kQEc4bHP1Bn4WqPgh2d61Q4hJBBgR
 AgAJBQJQz + PwAhsMAAoJENWvkWJEzUSbAhYAoKnL / nGFmJejtoPdws + QRW95VECn
 AJ4yFFV1axpTDbIClQQTerJS7xpxjg ==
 = Г / ФГ
 ----- КОНЕЦ PGP ПУБЛИЧНЫЙ КЛЮЧЕВОЙ БЛОК ----- 

Расширение позволяет нам экспортировать только открытый ключ, поэтому, если вы хотите экспортировать свой закрытый ключ аналогичным образом для целей резервного копирования, вам нужно будет использовать сам инструмент GnuPG.

Импорт ключей

Теперь у нас есть три ключа, необходимые для частного обмена. Мы сгенерировали наши собственные открытые / закрытые ключи, и у вас есть открытый ключ для testuser выше, который мы будем использовать в качестве стороннего открытого ключа.

Чтобы связаться с testuser, нам нужно вставить ее открытый ключ в нашу связку ключей. Импортировать открытый ключ можно, передав открытый ключ методу import() :

 <?php $keydata = "FULL PUBLIC KEY FROM ABOVE"; $gpg = new gnupg(); $info = $gpg->import($keydata); 

Вы можете проверить, что этот ключ был добавлен в ваш gpg --list-keys в командной строке, с помощью gpg --list-keys и использовать gnupg_keylistiterator() из предыдущего, чтобы получить отпечаток.

Шифрование сообщений

Со всеми нашими ключами в нашей связке ключей мы можем зашифровать важное сообщение для testuser. Сообщение содержит ответ на вопрос:

Q: Сколько программистов нужно, чтобы поменять лампочку?

Мы будем использовать открытый ключ testuser, чтобы гарантировать, что она будет единственным человеком, способным расшифровать ответ. Код для шифрования ответа:

 <?php $gpg = new gnupg(); $gpg->addencryptkey("6436010991C352981F95F9A5D5AF916244CD449B"); $enc = $gpg->encrypt("A: None, that is a hardware problem!"); print $enc; 

Мы используем addencryptkey() чтобы указать, каким открытым ключом шифровать это сообщение, ключом получателя, а не отправителя. В данном случае это отпечаток открытого ключа тестируемого.

После шифрования никто не сможет расшифровать сообщение, если у него не будет личного ключа testuser в их связке ключей… который должен быть не кем иным, как самой testuser.

Расшифровка сообщений

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

 <?php $encrypted = "THE UNREADABLE ENCRYPTED MESSAGE SHOULD BE PASTED HERE"; $gpg = new gnupg(); $gpg->adddecryptkey("6436010991C352981F95F9A5D5AF916244CD449B","test1234"); $plain = $gpg->decrypt($encrypted); print $plain; 

Зашифрованное сообщение хранится в $encrypted . Мы создаем новый объект gnupg() , указываем, какой из ключей тестируемого следует использовать для расшифровки сообщения по отпечатку пальца и паролем нашего закрытого ключа, а затем печатаем дешифрованное сообщение. Важно отметить, что для расшифровки сообщения всегда требуется, чтобы получатель addencryptkey() пароль, связанный с закрытым ключом, в addencryptkey() , за исключением gnupg v2, где вы не можете ввести простой текстовый пароль в коде — вас попросят для пароля при запуске этого кода в CLI. Если вы планируете использовать эту функцию в веб-инструменте с gnupg v2, возможно, вы захотите исключить фразу-пароль из личного ключа веб-пользователя.

В заключение

Теперь, когда мы знаем, как шифровать и дешифровать с помощью GnuPG, зачем вам это нужно в PHP? С помощью SSL вы можете защитить данные, передаваемые между веб-сервером и клиентом, а SSH можно использовать для защиты сеансов оболочки, так что же еще нужно?

Иногда вам нужна информация, чтобы быть защищенной, не только во время ее передачи, но и в том месте, где она хранится, и между всеми слоями. Возможно, вам нужно передать финансовую информацию в удаленное место; Можете ли вы доверять системным администраторам или тем, кто имеет физический доступ на месте? Или, возможно, проект требует передачи данных с использованием небезопасного протокола, такого как FTP.

Хотя наши простые примеры, приведенные выше, полезны для передачи зашифрованных сообщений, GPG и расширение gnupg также можно использовать для проверки подлинности незашифрованных сообщений с помощью подписей. Электронная почта также является общеизвестно небезопасным способом связи, и сообщения легко подделываются, и хотя здесь это подробно не описано, использование шифрования и зашифрованных подписей обеспечивает безопасность и подлинность.

Я призываю вас продолжить изучение вариантов и концепций инструмента GnuPG, если вы пишете приложение, которое требует серьезной защиты данных.

Изображение через Fotolia