Создан: 19.07.2011
Модиф: 16.08.2011
Иванов Аркадий
Для безопасной передачи данных через небезопасный Интернет придумано многое - GnuPG, OpenSSL, Java SSL,.... Что использовать - определяется задачей и разработчиком программ.
В этом описании я немного соберу для самого себя команды, которые приходится использовать для создания ключей шифрования и всего, что с ними связано.
Важнейшим математическим трюком, который используется при шифровании, является следующий:
- Сторона A создаёт пару ключей. Ключ - это длинная последовательность битов, например 256 бит. В созданной паре один ключ является закрытым (private) ключём, который бережно хранится владельцем. Второй ключ является открытым (public), т.е. его совершенно спокойно можно передать по доступным врагам каналам своему товарищу.
- Прелесть ключей и алгоритмов шифрования состоит в том, что когда сторона A создала эту пару ключей и передала открытый ключ стороне B, теперь сторона B может шифровать свои сообщения для A открытым ключём и посылать их к A через Интернет.
- Чтобы расшифровать сообщение от B, сторона А использует свой закрытый ключ.
- Хакерам позволено перехватить весь поток данных между A и B, как открытый ключ, так и зашифрованные им сообщения. Алгоритм, с помощью которого шифрует сторона B, весьма сложен и не позволяет перехватчикам подобрать его за разумное время без наличия у них закрытого ключа.
- Вот именно этот алгоритм и является достижением математиков, позволившим передавать безопасно данные через Интернет между компьютерами без предварительной передачи ключей с помощью курьера или каким-нибудь другим неэлектронным образом.
Выше речь шла о шифровании сообщений.
Наличие таких алгоритмов позволило реализовать ещё одну важную функцию - электронную подпись. Электронная подпись - это набор символов, который прицепляется к сообщению или идет отдельно от сообщения и позволяет получателю твёрдо удостоверится, что сообщение пришло от нужного автора. Здесь тоже используется пара ключей.
- В случае с подписью сторона А создаёт private и public ключи. Публичный ключ она по традиции пересылает стороне B.
- Сторона А создаёт сообщение и добавляет к нему электронную подпись с помощью private ключа. В создании подписи участвует как сам текст всего сообщения, так и закрытый ключ.
- Сторона B получает сообщение по открытым каналам и с помощью ранее полученного public (открытого) ключа A проверяет, что сообщение действительно пришло от A.
Замечу, что для шифрования сообщения на стороне B используется открытый ключ А, и сторона А будет расшифровывать присланное сообщение своим закрытым ключём.
Но для создания подписи используется свой закрытый ключ и другая сторона будет удостоверяться в авторстве полученного послания с помощью открытого ключа другой стороны.
Эти механизмы позволяют очень чётко разграничить ответственность получателя и посылателя. Если вы получили правильную подпись от получателя, даже если позже выяснилось, что это сообщение было сфабриковано, ответственность лежит на отправителе, поскольку у вас нет возможности подделать его подпись - у вас нет закрытого ключа.
При передаче открытого ключа другой стороне обычно дополнительно передаётся информация о сервере, чёй это открытый ключ. В файле, где лежит открытый ключ, лежит и инфо о владельце.
Открытый ключ + доп. информация о владельце называется сертификатом.
При создании ключей обычно сразу создаётся закрытый ключ и сертификат.
Сертификаты могут быть подписаны электронной подписью Центра Сертификации (Center of Athority - CA). Обычно CA - это третья сторона, которая такой подписью удостоверяет, что это действительно сертификат вашей компании. Создав закрытый ключ и сертификат, вы просите СА подписать свой сертификат их подписью. Программы для создания ключей в таких случаях создают не сертификат, а CSR - Certificate Signing Request, запрос на подпись сертификата, который вы отсылаете в CA. Прежде, чем подписать ваш сертификат, третья сторона проводит исследования, что вы - это вы, а не жулик. Открытые ключи этой третьей стороны обычно уже содержатся в программах, например в броузерах. При установлении зашифрованного соединения броузер получает от вашего сервера подписанный третьей стороной сертификат (т.е. открытый ключ вашего сервера + информацию о вас + электронную подпись от CA). Имея открытый ключ самого CA, броузер проверяет правильность электронной подписи. Если подпись не подделка, браузер без лишних вопросов начинает использовать открытый ключ вашего сервера. Несколько фирм в мире ведут свой бизнес на том, что подписывают сертификаты, например,Twahte, VeriSign.
Для SSL-соединений используются сертификаты с подписью. Иногда можно использовать и самоподписанные сертификаты, т.е. в качестве CA используется ваша фирма.
Получая такой самоподписанный сертификат от сервера броузеры спрашивают пользователя о его согласии продолжать работать и позволяют добавить ваш сертификат в список тех, кому вы доверяете. Для нормального Internet-бизнеса использование самоподписанных сертификатов опасно, поскольку позволяет хакерам сделать копию вашего сайта и отловить данные невнимательных пользователей.
Теперь перехожу к командам разных систем для работы с ключами.
Создание пары ключей:
OpenSSL | openssl req -new -x509 -days 3660 -newkey rsa:2048 -keyout privkey.pem -out pubkey.crt \ -subj "/C=RU/ST=Kamchatka/L=Elizovo/O=Roga I Kopyta/OU=IT/CN=www.mydomain.ru/emailAddress=my@addr.com" Команда создаст файлы privkey.pem - закрытый ключ и pubkey.crt - открытый ключ (точнее сертификат), ещё и пароль задаст. req запрос на создание нового сертификата -new Создание запроса на сертификат (Certificate Signing Request (CSR)). -newkey rsa:2048 cоздать новый закрытый RSA ключ длиной 2048 бита. -keyout privkey.pem Файл закрытого ключа - privkey.pem -x509 Вместо создания CSR (см. опцию -new) создать самоподписанный сертификат. -days 3660 Срок действия сертификата 3600 дней. -subj "/C=RU/ST=Kamchatka/L=Elizovo/O=Roga I Kopyta/OU=IT/CN=www.mydomain.ru/emailAddress=my@addr.com" Данные сертификата, пары параметр=значение, перечисляются через '/'. Если в параметре есть пробел, его можно замаскировать с помощью обратного слэша "\", например "O=Roga\ I\ Kopyta". Описание параметров: С - код страны (Country). ST - Название региона,области,края L - Название города,поселка (Locality Name) O - Название организации (Organization Name) OU - Название подразделения (Organization Unit). CN - доменное имя хоста (Common Name). При создании сертификата для сервера оно должно совпадать с DNS-именем сервера. Это проверяется в SSL-соединении. До 64 символов. emailAddress - E-mail адрес. До 40 символов. Чтобы снять с ключа пароль, (что для ключа на сервере просто необходимо) делаем следующее: $ mv privkey.pem privkey.pem.orig $ openssl rsa -in privkey.pem.orig -out privkey.pem |
GnuPG | Здесь процедура интерактивна: $ gpg --gen-key Вам надо будет выбрать тип ключа (выбирайте RSA), длину (1024 бита вполне подойдёт), ввести своё имя, E-mail и пароль для ключа (пароль можно пройти Enter-ом, тогда его не будет). В подкаталоге .gnupg домашнего каталога пользователя программа создаст новые ключи. Если в диалоге при создании сертификата я указал имя "Arc", то его следует использовать при работе с этими ключами. |
Java Keytool | Диалоговая программа: $ keytool -genkeypair -alias mysert -keyalg RSA -validity 365 -alias mysert В хранилище идентификатором этого сертификата будет "mysert". Работа с сертификатом производится по его алиасу -keyalg RSA Алгоритм, для которого созданы эти ключи, называется RSA. -validity 365 Ключи будут действительны 365 дней В диалоге на вопрос "What is your first and last name?" следует ввести имя сервера. Ключи помещаются в хранилище. По умолчанию это файл в .keystore в домашнем каталоге. |
Криптование при помощи открытого ключа:
OpenSSL |
openssl rsautl -encrypt -certin -inkey pubkey.pem -in plain.txt -out crypted.txt
rsautl
использую RSA утилиты
-certin
указываю, что используется сертификат, а не публичный ключ
-inkey
указываю файл сертификата
-in
указываю файл для зашифровки
-out
указываю выходной файл
Замечу, что большие файлы так криптовать не удатся. Поток байтов следует
разбивать на блоки, например, по 100 байтов и криптовать эти блоки по
отдельности.
Если есть открытый ключ, а не сертификат, указывается ключ -pubin,
а не -certin
|
GnuPG | gpg -r XXX -o 1.encoded --encrypt 1.html -r XXX указываю ID ключа, который надо использовать для шифрования. -o указываю выходной файл --encrypt указываю, что будет операция шифрования |
Расшифровка присланного сообщения:
OpenSSL |
openssl rsault -decrypt -certin -inkey privkey.pem -in crypted.txt -out plain.txt |
GnuPG | gpg -r XXX --out 2 --decrypt 1.encoded |
Создание нового приватного ключа и одновременно с ним CSR:
OpenSSL | openssl req -out pubkey.csr -new -newkey rsa:2048 -nodes -keyout privkey.pem |
Создание публичного ключа из приватного RSA ключа:
OpenSSL |
openssl rsa -in privkey.pem -pubout -out pubkey.pem |
Выделение публичного ключа из сертификата:
OpenSSL | openssl x509 -inform pem -in pubkey.crt -noout -pubkey >pubkey.pem |
Подпись файла приватным ключом:
OpenSSL |
openssl dgst -sha1 -sign privkey.pem -out sign.txt datafile
Будет сформирована подпись sign.txt для данных из файла datafilе.
Сначала будет вычислен SHA-1 хэш по данным из datafile и затем сделана подпись.
|
GnuPG | gpg -u XXX --sign file Создаст file.gpg, который будет содержать подпись пользователя XXX. gpg -u XXX --clearsign file Создаст file.asc, который будет содержать неизменённый текст файла file и подпись пользователяXXX. |
Проверка подписи файла:
OpenSSL |
openssl dgst -sha1 -verify pubkey.pem -signature sign.txt datafile
Проверит по открытому ключу pubkey.pem, что подпись данных из datafile,
которая находится в sign.txt, соответствует владельцу закрытого ключа.
|
GnuPG | gpg --verify 1.txt.asc Проверит и напечатает инфо о владельце ключа, которым подписано сообщение. |
Теперь опишу процедуры для безопасной передачи автоматизированной данных между сервером и клиентом с помощью OpenSSL.
При этом сервер должен быть уверен, что это правильный клиент, а клиент должен быть уверен, что он попал на правильный сервер.
РАЗНОЕ
Формат файла .PFX (ещё есть название PKCS12 для этого формата) используется для хранения закрытого ключа, подписанного сертификата и сертификата того сервера, который подписывал наш ключ (CA). Изготавливается сервером, на который мы собираемся коннектиться броузером и позволяет серверу удостовериться, что мы именно те, за кого себя выдаём. Созданный сервером этот наборчик клиент скачивает в виде PFX-файла через Интернет в надежде, что никто не перехватит этот "ключ от сейфа, где деньги лежат". Также PFX обычно снабжается паролем. Без пароля хакер ничего не сможет сделать с этим набором ключей.
WebMoney использует такой способ аутентификации клиента, т.е. вместо логина и пароля вы импортируете PFX-файл в броузер и при подключении к серверу броузер автоматом использует шифрование, понятное серверу и ему самому. Иногда надо превратить PFX в набор PEM-ов. Делается это так:
- Сначала вытаскиваем все ключи в формате PEM в один файл. Пароль при конвертации отменяю.
openssl pkcs12 -nodes -in file.pfx -out keys.pem
- Выделяю из этого файла приватный ключ в формате PEM:
openssl rsa -in keys.pem -out private.key
- Выделяю редактором из keys.pem свой подписанный сертификат в файл public.crt. Определите свой сертификат по названию (CN).
- Оставляю редактором в keys.pem только сертификаты сервера (стираю приватный ключ и свой сертификат). Называю файлcerts.ca
Теперь этот набор можно использовать, например в программе curl:
curl --key private.key --cert public.crt --cacerts certs.ca "https://mydomain.ru/verysecret.html"