Создан: 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 \
запрос на создание нового сертификата -new Создание запроса на сертификат (Certificate Signing Request (CSR)). -newkey rsa:2048 cоздать новый закрытый RSA ключ длиной 2048 бита. -keyout privkey.pem Файл закрытого ключа - privkey.pem -x509 Вместо создания CSR (см. опцию -new) создать самоподписанный сертификат. -days 3660 -subj "/C=RU/ST=Kamchatka/L=Elizovo/O=Roga I Kopyta/OU=IT/CN=www.mydomain.ru/emailAddress= Данные сертификата, пары параметр=значение, перечисляются через '/'. Если в параметре есть пробел, его можно замаскировать с помощью обратного слэша "\", например "O=Roga\ I\ Kopyta". Описание параметров: OU - Название подразделения (Organization Unit). CN - доменное имя хоста (Common Name). При создании сертификата для сервера оно должно совпадать с DNS-именем сервера. Это проверяется в SSL-соединении. До 64 символов.
Чтобы снять с ключа пароль, (что для ключа на сервере просто необходимо) делаем следующее: $ mv privkey.pem privkey.pem.orig |
| 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 В диалоге на вопрос "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.
При этом сервер должен быть уверен, что это правильный клиент, а клиент должен быть уверен, что он попал на правильный сервер.
- Сначала на сервере в каталоге /mycrt делается самоподписанный сертификат. Повторю ранее приведёную команду.
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=Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript. " - Снимаю пароль с секретного ключа:
mv privkey.pem privkey.pem.orig
openssl rsa -in privkey.pem.orig -out privkey.pem - На сервере в каталоге (например /mycrt), где буду хранить ключи и сертификаты,
создаю конфигурационный файл с именем ca.config:
[ ca ]
default_ca = CA_CLIENT # При подписи сертификата
# использовать секцию CA_CLIENT
[ CA_CLIENT ]
dir = /mycrt/db # Каталог для служебных файлов
certs = $dir/certs # Каталог для сертификатов
new_certs_dir = $dir/newcerts # Каталог для новых сертификатов
database = $dir/index.txt # Файл с базой данных
# подписанных сертификатов
serial = $dir/serial # Файл содержащий серийный номер
# сертификата
# (в шестнадцатиричном формате)
certificate = ./pubkey.crt # Файл сертификата CA
private_key = ./privkey.key # Файл закрытого ключа CA
default_days = 3650 # Срок действия в днях подписываемого
# сертификата
default_crl_days = 7 # Срок действия CRL
default_md = md5 # Алгоритм подписи
policy = policy_anything # Название секции с описанием
# политики в отношении данных
# сертификата
[ policy_anything ]
countryName = optional # RU
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied # обязателен
emailAddress = optional
Делаю каталоги и файлы, соответствующие параметрам конфиге:
mkdir db
mkdir db/certs
mkdir db/newcerts
touch db/index.txt
echo "01" > db/serial
Примечание: В файле db/serial записывается текущий серийный номер подписываемого сертификата в шестнадцатиричном формате. В файл db/index.txt сохраняются данные о
подписываемых сертификатах.
- На клиентской машине клиент создаёт закрытый ключ и запрос на подпись сертификата (CSR):
openssl req -new -days 3660 -newkey rsa:1024 -keyout privkey.pem -out pubkey.csr \
-subj "/C=RU/ST=Kamchatka/L=Elizovo/O=Client Rogov i Kopyt/OU=IT/CN=www.cl.ru/emailAddress=Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript. "
- Снимается пароль с секретного клиентского ключа:
mv privkey.pem privkey.pem.orig
openssl rsa -in privkey.pem.orig -out privkey.pem
- pubkey.crt копируется на сервер с именем pubkey01.crt и на сервере в каталоге /mycrt делаю:
openssl ca -config ca.config -in pubkey01.csr -out pubkey01.crt -batch
- В результате в этом каталоге будет создан pubkey01.crt, в базу данных он запишется с именем 01.pem и в файлах базы данных openssl проведёт необходимые изменения.
- pubkey01.crt необходимо вернуть на клиента. Клиент по информации внутри подписанного сертификата может проверить, что ключ действительно пришёл от сервера. Также сервер теперь тоже имеет публичный ключ клиента и сможет проверить подпись от клиента.
- Сервер должен в общий доступ выложить свой публичный ключ(точнее сертификат), а клиент скачать его. Теперь эта пара компьютеров обладает публичными ключами друг друга
и могут шифровать, подписывать, расшифровывать и проверять подписи сообщений между собой.
РАЗНОЕ
Формат файла .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"