Криптография - статьи
         

Основы работы с OpenSSL


Автор: Vsevolod A. Stakhov/CEBKA
E-mail: VStakhov tehnopark org
Сайт:

OpenSSL — это система защиты и сертификации данных, название SSL переводится, как система безопасных сокетов (secure socket layer). OpenSSL используется практически всеми сетевыми серверами для защиты передаваемой информацией. Существует программное API SSL (SSLEAY), позволяющее создавать безопасные сокеты с шифрацией передаваемых данных в собственных разработках. Но в данной статье я бы хотел рассказать о самой системе OpenSSL, вызываемой через командную строку.

Т.к. OpenSSL поддерживает очень много различных стандартов сертификации, шифрования, хеширования, то использование данной команды достаточно сложно. Внутри OpenSSL существуют отдельные компоненты, отвечающие за то или иное действие, для получения списка доступных компонентов можно вызвать openssl с параметрами list-standart-commands. Можно также получить список доступных алгоритмов хеширования (list-message-digest-commands) и алгоритмов шифрования (list-cipher-commands).

OpenSSL может использоваться во множестве случаев и умеет выполнять следующие задачи:

  • Создавать и управлять ключами RSA и DSA — команды rsa, dsa, dsaparam.
  • Создавать сертификаты формата x509, запросы на сертификацию, восстановление — команды x509, req, verify, ca, crl, pks12, pks7.
  • Зашифровывать данные с помощью симметрического или асимметрического шифрования — команды enc, rsautl.
  • Высчитывать хеши различных типов — команда dgst.
  • Работа с S/MIME — команда s/mime.
  • Проверка работы серверов и клиентов ssl — команды s_client, s_server.

Cуществует также несколько вспомогательных утилит ssl:

    — openssl speed [список_алгоритмов_хеширования_или шифрования]:

тестирование скорости различных алгоритмов, если запускать без параметров, то тестируются все алгоритмы; алгоритмы внутри списка разделяются пробелом, например: openssl speed md5 rsa idea blowfish des 3des sha1. В конце работы выводится общая скорость работы различных алгоритмов (в 1000-х байт в секунду), для обработки различной длины блоков. Вот результат работы тестов скорости на моем домашнем компьютере (Celeron 366), на других машинах значения будут другими:

Проверка алгоритмов асимметрического шифрования:

    — openssl rand [-out file] [-rand file] num:

генерация num рандомных байт, можно использовать для проверки рандомизационной последовательности rand:

# openssl rand -rand .rnd 5
Wеб~
#


    — openssl ciphers [-ssl2] [-ssl3] [-tls1] NAME: вывод доступных алгоритмов для обеспечения уровня безопасности NAME, где NAME — это символическое название группы алгоритмов. Обычно используются значения:

      LOW — алгоритмы низкого уровня безопасности (<128 бит);

      MEDIUM — алгоритмы среднего уровня стойкости (128 бит);

      HIGH — алгоритмы высокой стойкости (>128 бит);

      ALL — все алгоритмы;

      NULL — алгоритмы без шифрования.

Обычно в настоящее время используются алгоритмы групп MEDIUM и HIGH, которые еще долго не смогут быть взломаны прямым перебором. Можно также вывести список алгоритмов из нескольких групп, разделив их «:» (например, MEDIUM:HIGH).

Теперь я бы хотел рассказать об основных утилитах openssl. Для начала о методах генерации ключей, затем о командах шифрования, и, наконец, о сертификатах, s/mime. Итак, пару слов о генерации ключей. Для создания rsa-ключей используется команда genrsa: openssl genrsa [-out file] [-des | -des3 | -idea] [-rand file] [bits]

Команда genrsa создает секретный ключ длиной bits в формате PEM, шифрует его одним из алгоритмов: des (56 бит), des3 (3-й des 168 бит) или idea (128 бит). При выборе алгоритма шифрования будет запрошен пароль для шифрации создаваемого секретного ключа (если алгоритм не указан, то секретный ключ не шифруется, чего делать ни в коем случае нельзя для личных ключей, т.к. некоторые серверы требуют отсутствие шифрации для сектетного ключа сервера). Опция -out говорит программе, что вывод нужно осуществлять не в stdout, а в файл file (опция -out присутствует во множестве других компонентов openssl и используется аналогичным образом для указания выходного файла). Опция -rand указывает на файл[ы] (разделенные «:»), из которых будут считываться данные для установки seed (зерна) генератора случайных чисел. В качестве таких файлов сразу же приходит на ум использовать что-то вроде /dev/random или /dev/urandom, но у меня с этим возникли проблемы: все вешалось наглухо, поэтому я рекомендую в этом случае использовать какие-нибудь сложно угадываемые файлы, вроде /var/log/messages или /boot/vmlinuz, думаю, что угадать содержимое этих файлов не намного проще, чем содержимое /dev/random, но работает этот фокус в любом *nix (опция -rand также присутствует во всех компонентах генерации и управления ключами и сертификатами). Использовать /dev/random и /dev/urandom, конечно, можно, но я для этого скопировал из /dev/random 32768 байт в файл .rnd таким образом: dd if=/dev/[u]random of=.rnd count=64



Кроме этого, можно указывать в качестве -rand-файла EGD-сокет, который обеспечивает генерацию определенного количества случайных байт, EGD доступен на узле http://www.lothar.com/tech/crypto/. Установка генератора случайных чисел производится на основании хеша -rand файла, поэтому можно указывать файлы различной длины, т.к. хеш все равно имеет фиксированное число бит. Пример генерации 4096 битового секретного ключа RSA: # openssl genrsa -out /etc/openssl/key.pem -des3
-rand /var/log/messages 4096 Generating RSA private key .....++*...++++++++* Enter PEM passphrase: Verify PEM passphrase:



После этого секретный ключ зашифровывается и записывается в файл (в текстовом виде). В начале ключа указывается алгоритм шифрования. Для создания публичного ключа rsa на основе секретного используется команда openssl rsa. Даная команда имеет следующий формат:

openssl rsa -in filename [-out file] [-des | -des3 |-idea] [-check] [-pubout]

Утилита openssl rsa способна изменять пароль и алгоритм шифрования секретного ключа, будучи вызвана с параметром -in и -out. Если применить параметр -pubout, то в указанный файл -out будет записан публичный ключ, вычисленный на основе -in секретного. Например, создание публичного ключа на основании секретного: openssl rsa -in /etc/openssl/key.pem
-out /etc/openssl/pubkey.pem -pubout

Изменение пароля и алгоритма шифрования секретного ключа с des3 на idea: openssl rsa -in /etc/openssl/key.pem -out /etc/openssl/key1.pem -idea

Для создания ключей DSA используется утилита openssl gendsa, аналогичная genrsa, но есть два отличия: во-первых, для ключей DSA нельзя прямо указывать длину в битах и, во-вторых, ключи DSA могут генерироваться согласно некоторым параметрам, записанным в файл paramfile утилитой openssl dsaparam. dsaparam имеет следующий формат:

openssl dsaparam [-rand file{s}] [-C] [-genkey] [-out file] numbits

где numbits — длина желаемого ключа, -С заставляет dsaparam вывести на stdout код на СИ для программной генерации DSA на основе необходимых параметров, а опция -genkey говорит, что в выходной файл, наряду с параметрами, дополнительно записывается созданный секретный ключ DSA, но нельзя его сразу же зашифровать, поэтому удобнее воспользоваться утилитой openssl gendsa, которая имеет схожий синтаксис с командой genrsa, но вместо числа бит указывается файл параметров, созданный dsaparam:

# openssl gendsa -out /etc/openssl/dsakey.pem -rand /boot/vmlinuz -idea paramfile



  Enter PEM passphrase:

  Verify PEM passphrase:

Для управления ключами dsa используется программа openssl dsa, которая абсолютно аналогична (в параметрах) утилите openssl rsa. Поэтому я просто приведу пример генерации публичного ключа DSA: # openssl dsa -in /etc/openssl/dsakey.pem
-out /etc/openssl/pubdsakey.pem -pubout

Теперь настало время рассказать о компонентах openssl, выполняющих шифрование и хеширование данных. Для выполнения симметрического шифрования используется утилита openssl enc -cipher или ее сокращенная запись openssl cipher, где cipher — это одно из символических имен симметрических шифров. Наиболее популярными являются следующие: base-64 (преобразование в текстовый вид), bf (blowfish — 128 бит), des (56 бит), des3 (168 бит), rc4 (128 бит), rc5 (128 бит), rc2 и idea (128 бит). Для указания входного и выходного файлов используется опции -in и -out соответственно. Пароль для шифрования вводится с клавиатуры (можно указать в командной строке параметром -k, но это очень плохо по соображениям безопасности, т.к. большинство шеллов умеют сохранять историю командной строки, IMHO намного лучше ввести пароль непосредственно перед шифрованием, хотя эта опция полезна для скриптов, так что забывать о ней нельзя :). Учтите, что пароль не спрашивается при обработке файла base64, т.к. шифрования не происходит. Для расшифровки зашифрованных данных примените openssl cipher с опцией -d (алгоритм шифрования и дешифрования должен совпадать!), а для одновременной обработки данных base64 можно воспользоваться опцией -a. Шифрование по умолчанию происходит с подмешиванием, т.е. для выбора алгоритма подмешивания используется случайная соль (salt), в этом случае, если вы шифруете один и тот же файл в разное время одним и тем же алгоритмом и паролем, то результаты скорее всего будут разными (это затрудняет атаку по словарю). Также по умолчанию используется cbc-режим алгоритмов, когда ключ меняется в течение всего сеанса работы согласно передаваемым данным, этот прием очень сильно затрудняет брутфорс, т.к. атакующему сложно поймать нужный момент времени. Приведу несколько примеров:

* зашифруем файл, используя алгоритм des3
# openssl des3 -in file -out file.des3
* расшифруем полученный файл
# openssl des3 -d -in file.des3 -out file
* зашифруем файл, используя алгоритм blowfish(bf), и



* закодируем base64
# openssl bf -a -in file -out file.bf64
* теперь расшифруем его и обработаем сразу же base64
# openssl bf -a -d -in file.bf64 -out file

Для вычисления хешей ( их еще называют отпечатками или контрольными суммами) используется команда openssl dgst -hashalg или краткая форма openssl hashalg (первая команда может также выполнять манипуляции с ЭЦП, но об этом далее). Обычное использование данной команды таково:

openssl hashalg [-c] file[s]

Вычисляется хеш-сообщения фиксированной длины в виде одной строки или, если указана опция -c, строки, разделенной на пары HEX-чисел двоеточием. Из алгоритмов хеширования могут применяться следующие: md2 (128 бит), md4(128 бит), md5 (128 бит), mdc2 (128 бит), sha (160 бит), sha1 (160 бит), ripemd160 (160 бит). Опять же приведу пару примеров:

* вычислим md5-хеш файла:
# openssl md5 -c file
MD5(file)= 81:fd:20:ff:db:06:d5:2d:c3:55:b5:7d:3f:37:ac:94
* а теперь SHA1-хеш этого же файла:
# openssl sha1 file
SHA1(file)= 13f2b3abd8a7add2f3025d89593a0327a8eb83af

Как я уже говорил, утилита openssl dgst может использоваться для подписывания сообщения секретным ключом и проверки ЭЦП публичным ключом. Для этого используется следующий синтаксис:

openssl dgst -sign private_key -out signature -hashalg file[s]

Подписывание file с помощью секретного ключа "private_key", используя алгоритм хеширования "hasalg" (обычно применяются sha1 или md5). openssl dgst -signature signature -verify public_key file[s]

Проверка подписи в "file", используя публичный ключ "public_key" и ЭЦП "signature". Данная программа выводит «Verification OK» при правильной подписи или «Verification Failure» в любом другом случае. Учтите, что ЭЦП в таком случае хранится отдельно от файла, который ею подписан (причем в каком-то кривом формате).

Для шифрации и дешифрации RSA алгоритмом используется программа rsautl. Данная утилита имеет также возможность подписывать и проверять подпись сообщений (однако работать все равно приходится с хешем сообщения, т.к. подписывать можно только небольшой объем данных, по этой причине лучше применять openssl dgst). Для шифрации/дешифрации используется следующий синтаксис:

openssl rsautl -in file -out file.cr -keyin pubkey.pem -pubin -encrypt



(Шифрация "file" с использованием публичного ключа "pubkey.pem")

openssl rsautl -in file.cr -out file -keyin secretkey.pem -decrypt

(Дешифрация "file.cr" с использованием секретного ключа "secretkey.pem")

Теперь настало время рассказать об одном из главных применений openssl — управление сертификатами. Openssl имеет возможность генерировать сертификаты, управлять ЭЦП и шифрацией с помощью сертификатов. Однако применение утилит управления сертификатами — достаточно сложная задача. Поэтому для начала я дам общие представления о сертификатах. Сертификат содержит публичный ключ, подписанный одним из корневых доверенных центров сертификации (или комплементарным секретным ключом), данные об организации, выдавшей сертификат и в некоторых случаях зашифрованный секретный ключ, а также отпечаток (хеш) публичного ключа. Сертификаты имеют время действия, по окончанию которого они автоматически считаются недействительными, иерархия сертификатов обычно строится на основании сети доверия (бывают довольно длинные цепочки сертификатов, ведущие к доверенному ключу из root CA). Таким образом, сертификат — это полный комплекс системы асимметрического шифрования, предоставляющий гораздо больше возможностей, чем сами по себе ключи (а также являющийся более защищенной системой). Основным привлекательным моментом сертификата является возможность записи в него информации об организации, этот ключ выдавшей. Таким образом явно напрашивается применение собственной системы сертификации в данной организации. Можно, например, выдавать сотрудникам их персональные сертификаты, подписанные сертификатом организации (его можно сгенерировать самому или получить от сторонней компании). Причем эти сертификаты впоследствии можно использовать для удостоверения личности сотрудника, например, при почтовой переписке или аутентификации на http-сервере (apache+ssl). Единственное условие, которое должно выполняться, — это наличие на машине клиента сертификата организации в списке корневых доверенных ключей. Общее содержание сертификатов определено стандартом x509, в то время как форматы записей сертификатов могут внести некоторую путаницу. Openssl по умолчанию использует формат PKCS#10, Microsoft использует по умолчанию формат PKCS#12 (в руководстве по openssl этот формат охарактеризован, как один большой баг :), формат PKCS#7 используется для запросов на сертификацию к CA (центр сертификации) и не может содержать секретного ключа, также для этой цели может использоваться DER-закодированный сертификат (DER-кодирование подобно кодированию base64, но имеет специальное назначение для использования в криптографических системах) также без секретного ключа. Учтите, что при использовании DER-формата убираются маркеры начала и конца сертификата, а его содержимое кодируется base64, поэтому в файле DER можно хранить только один сертификат, с другой стороны DER сертификаты поддерживаются M$ (стандартное расширение .cer), поэтому иногда бывает нужно преобразовать сертификаты из одного формата в другой (я здесь имею ввиду PEM или DER): PEM-->DER openssl x509 -inform PEM -in cert.pem
-outform DER -out cert.cer DER-->PEM openssl x509 -inform DER -in cert.cer
-outform PEM -out cert.pem



Таким же образом можно конвертировать и ключи асимметрического шифрования (используя утилиты rsa или dsa).

Думаю, что не сильно запутал вас всеми этими стандартами. Если объяснять на пальцах, то все выглядит следующим образом: клиент создает сертификат и отправляет свой публичный сертификат (PKCS#7) в центр сертификации. В центре сертификации обрабатывается запрос клиента (запрос на сертификацию), и сертификат клиента подписывается секретным ключом центра сертификации. Клиент, имея публичный ключ центра сертификации, проверяет подлинность подписи и может далее использовать свой сертификат. Для организации можно предложить следующее решение: на сервере создается сертификат организации; генерируется запрос на сертификацию и отправляется к некоему доверенному центру сертификации (который будет известен всем клиентам и персоналу данной организации); получается сертификат организации, который можно использовать при создании сертификатов клиентов. Последние создаются так: клиент посылает запрос на выдачу сертификата; сервер создает сертификат клиента и подписывает его сертификатом организации; клиент получает сертификат клиента и сертификат организации; после проверки достоверности ключа организации (предполагается, что клиент доверяет CA, которым был подписан сертификат организации) проверяется достоверность сертификата клиента. После такой операции клиент будет точно уверен, что получил сертификат от данной организации, и может его использовать для работы с ней. По такой схеме построены все центры выдачи сертификатов(правда зачастую сертификат организации бывает подписан самим собой, что требует от клиента добавить сертификат организации к доверенным, а в первой схеме сертификат организации принадлежит к группе промежуточных центров сертификации, и этот случай предпочтительнее с точки зрения безопасности и удобства клиента, но требует больше работы от администратора). Да, хорошенькое объяснение на пальцах! Но что тут поделать: сертификаты — это довольно запутанная вещь. Сейчас я объясню, как создавать сертификаты с помощью openssl, и приведу пример только что описанного безобразия…

Для создания сертификата используется инструмент openssl req. Он имеет довольно много параметров, поэтому, чтобы не парить мозги, я просто приведу пару примеров его использования. Для начала требуется конфигурационный файл, который имеет следующий формат(все строки, начинающиеся с # — это мои комментарии, в конечном файле их может и не быть):

[ req ]
# Секция основных опций
default_bits = 2048
# Число бит
default_keyfile = keyfile.pem
# Имя ключа, используемого для сертификата
distinguished_name = req_distinguished_name
# DN организации, выдавшей сертификат
prompt = no
# Брать параметры из конфига неинтерактивный режим
[ req_distinguished_name ]
# DN организации
CN=RU
# Страна
ST=Ivanovskaya
# Область
L=Gadukino
# Город
O=Krutie parni
# Название организации
OU=Sysopka
# Название отделения
CN=Your personal certificate
# Имя для сертификата (персоны, получающей сертификат)
emailAddress=certificate@gaduk.ru
# Мыло организации



Если не указывать prompt no, то значения для параметров будут считаны в интерактивном режиме (то бишь с клавиатуры), а значения параметров будут являться подсказками при вводе данных. При интерактивном режиме можно указывать значения по умолчанию, а также минимальное и максимальное значения для параметров (для строковых параметров устанавливается ограничение на длину). В таком случае общий формат параметра таков:

имя = подсказка
имя_default = значение_по_умолчанию
имя_max = максимум
имя_min = минимум

Пример интерактивного файла конфигурации:

[ req ]
default_bits = 1024
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name

[ req_distinguished_name ]

countryName = Country Name (2 letter code)

countryName_default = RU

countryName_min = 2

countryName_max = 2

localityName = Locality Name (eg, city)

organizationName = Organization Name(eg, org)

organizationalUnitName = Organizational Unit Name (eg, section)

commonName = Common Name (eg, YOUR name)

commonName_max = 64

emailAddress = Email Address

emailAddress_max = 40

Спешу обрадовать некоторых ленивых товарищей: если вы намереваетесь создавать просто сертификат сервера (например, для LDAP-сервера), то указывать конфиг необязательно, будет использоваться конфиг по умолчанию /usr/lib/ssl/openssl.cnf, который содержит все необходимое. Ну а теперь традиционно приведу примеры использования openssl req(я не собираюсь подробно описывать данную команду, т.к. думаю, что для большинства случаев хватит примеров, а для особых случаев можно почитать man req).

openssl req -new -newkey rsa:2048 -keyout rsa_key.pem -config cfg -out certreq.pem

Создание запроса на сертификацию (-new) на основе создаваемого секретного ключа rsa (-newkey rsa:2048), который записывается в файл -keyout(и шифруется тройным DES). Запрос на сертификацию создается на основе конфигурационного файла — config. openssl req -x509 -new -key private_key.pem -config cfg -out selfcert.pem -days 365

Создание (-new) self-signed сертификата (-x509) для использования в качестве сертификата сервера или сертификата CA. Сертификат создается с использованием секретного ключа -key и конфигурационного файла -config. Создаваемый сертификат будет действителен в течение 365 дней (-days), опция -days не применима к запросам на сертификацию.

Для управления сертификатами x509 используется утилита openssl x509. С ее помощью можно подписать сертификат или запрос на сертификацию сертификатом CA. Также можно просмотреть содержимое сертификата в читаемой форме (DN, публичный ключ, время действия, отпечаток и.т.д.). Приведу примеры вышеописанных действий:

openssl x509 -in cert.pem -noout -text



Просмотреть информацию о сертификате в «нормальной» форме. Вот что примерно будет выведено, также можно использовать дополнительные опции: -fingerprint (необходимо сочетать с одной из опций -sha1, -md5 или -mdc2), -modulus (вывод публичного ключа), -serial, -subject, -issuer (организация, выдавшая сертификат), -email, -startdate, -enddate:

Certificate:
Data:
Version: 3 (0x2)
Serial Number: 0 (0x0)
Signature Algorithm: md5WithRSAEncryption
Issuer: C=RU, ST=region, L=city, O=organization, OU=Sysopka,CN=CEBKA/Email=CEBKA@smtp.ru
Validity
Not Before: Nov 9 08:51:03 2002 GMT
Not After : Nov 9 08:51:03 2003 GMT
Subject: C=RU, ST=region, L=city, O=organization, OU=Sysopka,CN=CEBKA/Email=CEBKA@smtp.ru
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:c6:6b:3b:8e:f8:33:05:a0:dc:e1:38:8f:6a:68:
42:1c:21:33:aa:90:b6:8c:93:14:11:9b:69:94:8a:
3a:0e:42:29:b0:45:14:1b:f0:37:2c:f3:05:db:13:
06:a9:cd:eb:99:31:51:25:86:c8:69:e0:5e:8d:28:
04:8d:1f:08:37:d7:72:39:fe:05:57:61:68:95:bf:
5c:ae:13:f2:05:a1:29:c3:bf:3b:32:ca:1a:ff:22:
53:f9:32:92:78:fe:44:c3:e1:ca:42:5c:5f:d1:49:
da:1c:9f:34:06:04:ee:46:74:8d:11:68:ef:37:e2:
74:1e:d9:46:04:b8:7e:d5:c5
Exponent: 65537 (0x10001)
Signature Algorithm: md5WithRSAEncryption
3b:42:85:45:08:95:f3:f1:fc:8a:23:88:58:0e:be:e5:9b:56:
1e:c1:ff:39:28:4f:84:19:f8:3e:38:ef:98:34:d6:ee:e0:0a:
de:36:3a:5c:15:88:d7:2a:a4:0a:d5:dc:3e:b2:72:4c:82:57:
b8:fe:52:f6:e2:06:01:38:eb:00:0b:f2:a9:87:be:65:83:19:
13:50:ae:6c:f2:0a:07:14:e6:8c:60:cd:c5:a3:d1:e1:ea:da:
24:c2:6a:06:d5:dc:1c:71:c9:64:fa:9e:c9:ca:97:e2:06:84:
de:4c:69:b8:9a:af:66:14:8d:46:9a:00:53:13:c9:ab:10:b8:
09:c2

openssl x509 -req -in clientreq.pem -extfile /usr/lib/ssl/openssl.cnf \ -extensions /usr/lib/ssl/openssl.cnf -CA CAcert.pem
-CAkey serverkey.pem \ -CAcreateserial -out clientcert.pem

Подписать запрос на сертификацию (-req) файла -in, используя доверенный CA сертификат -CA и его секретный ключ -CAkey. В конечный сертификат клиента (-out), записываются дополнительные параметры сертификата 3-й версии из файла /usr/lib/ssl/openssl.cnf (конфигурационный файл по умолчанию). Но об этом я расскажу после на конкретном примере. Такое поведение x509 позволяет организовать свой центр сертификации, подписывающий запросы клиентов на сертификацию. openssl x509 -in CAcert.pem -addtrust sslclient -alias "myorganization CA" \ -out CAtrust.pem



Преобразование сертификата -in в доверенный сертификат для использования в SSL-клиентах (sslserver — использование в качестве сертификата сервера, emailProtection — использование в качестве сертификата S/MIME).

Я еще раз хотел бы вернуться к проблеме построения CA. Для использования внутри организации можно использовать self-signed сертификат, но для использования CA вне организации приходится использовать сертификаты, выданные или подписанные сторонней организацией. Во втором случае возникает проблема выбора такой сторонней организации (она легко разрешается для дочерних компаний), которая требует юридического анализа (в разных странах существуют свои законы криптографии и поэтому дать какой-либо конкретный совет я не могу). Если вам довелось работать в российской правительственной компании, то считайте, что вам не повезло — использовать openssl для работы с правительственными организациями нельзя. Наши уважаемые гос. деятели добавили геморроя админам, разрешив использовать только алгоритмы ГОСТ (симметрические, асимметрические, хеширования — меня просто выворачивает от самого этого слова ГОСТ ;), поэтому использовать вам придется только специальные программы, реализующие эти алгоритмы. Я же приведу здесь пример построение собственного CA с self-signed сертификатом:

1) Генерируем секретный ключ:

openssl genrsa -out CAkey.pem -rand randfile -des3 4096

2) Создаем self-signed сертификат:

openssl req -new -x509 -key CAkey.pem -out CAcert.pem -days 365 -config cfg

Содержимое конфигурационного файла зависит от организации, можно даже воспользоваться утилитой /usr/lib/ssl/misc/CA.pl -newcert, которая создаст ключ и сертификат в одном файле в интерактивном режиме (хотя мне этот вариант не очень понравился, лучше один раз написать нормальный конфиг) — о дополнительных требованиях к конфигурации CA сертификата см. ниже.

3) Приведу пример скрипта, генерирующего клиентские сертификаты:

#!/bin/bash

dd if=/dev/random of=/tmp/.rnd count=64

RAND="/var/log/messages:/boot/vmlinuz:/tmp/.rnd"



REQ="openssl req"

X509="openssl x509"

RSA="openssl rsa"

GENRSA="openssl genrsa"

O="company"

C="RU"

ST="region"

L="city"

PURPOSES="digitalSignature, keyEncipherment"

CERTTYPE="client, email, objsign"

CA="/etc/openssl/CAcert.pem"

CAkey="/etc/openssl/CAkey.pem"

OUTDIR="/etc/openssl/clientcert/"

CN="client"
BITS=2048
DAYS=365

# Создаем секретный ключ во временной папке БЕЗ шифрования

TMP="/tmp/ssl-$$"
mkdir $TMP

if [ ! -d $OUTDIR ];then
mkdir $OUTDIR
fi


pushd $TMP > /dev/null
$GENRSA -rand $RAND -out tmp.key $BITS

# Создаем конфиг для клиента

cat > cfg <

[ req ]
default_bits = $BITS
distinguished_name = req_DN
extensions = v3_req
[ req_DN ]
countryName = "1. Country Name (2 letter code)"
countryName_default = "$C"
countryName_min = 2
countryName_max = 2
stateOrProvinceName = "2. State or Province Name (full name) "
stateOrProvinceName_default = "$ST"
localityName = "3. Locality Name (eg, city) "
localityName_default = "$L"
0.organizationName = "4. Organization Name (eg, company) "
0.organizationName_default = "$O"
organizationalUnitName = "5. Organizational Unit Name (eg, section) "
organizationalUnitName_default = "$OU"
commonName = "6. Common Name (eg, CA name) "
commonName_max = 64
commonName_default = "$CN"
emailAddress = "7. Email Address (eg, name@FQDN)"
emailAddress_max = 40
emailAddress_default = ""
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = $PURPOSES
nsCertType = $CERTTYPE
EOT
# Создаем запрос на сертификацию
$REQ -new -key tmp.key -config cfg -rand $RAND -out $CN.pem

# Этот файл лучше удалить побыстрее: мало ли чего...
rm -fr /tmp/.rnd

if [ $? -ne 0 ]; then
echo "Failed to make a certificate due to error: $?"
popd > /dev/null
rm -fr $TMP
exit $?
fi
# Подписываем сертификат сертификатом сервера

$X509 -req -in $CN.pem -CA $CA -CAkey $CAkey -CAsetserial \
-extensions -config cfg -days $DAYS -out $OUTDIR$CN.pem

chmod 0400 $OUTDIR$CN.pem
chown root:root $OUTDIR$CN.pem
# Шифруем секретный ключ
$RSA -in tmp.key -des3 -out $OUTDIR$CN-key.pem

chmod 0400 $OUTDIR$CN-key.pem
chown root:root $OUTDIR$CN-key.pem
# Выполняем заключительные действия
popd > /dev/null

rm -fr $TMP

echo -e "Generation complete, go to $OUTDIR and give to client $CN his certificate and \
\n private key (for windows users you should use openssl pkcs12 utility)"



Дополнительные свойства, описанные в скрипте (v3_req), означают, что клиент может использовать сертификат для подписывания и шифрации, но его сертификат не является CA сертификатом. Для CA-сертификата значение basicConstraits должно быть равно CA:TRUE (об этом забывать нельзя!). Поле nsCertType определяет дополнительные назначения данного ключа (для использования в качестве клиента, подписывания, использования в почтовых сообщениях). Для CA-сертификатов обычно применяют следующие значения nsCertType: sslCA, emailCA. Для ssl-ключей серверов (например, Apache) используется значение nsCertType = server. Полученный таким образом сертификат клиента будет содержать информацию о поставщике сертификата (то есть о вашем сертификате организации). Клиенту необходимо будет передать его сертификат, его секретный ключ (зашифрованный!) и ваш сертификат организации. Для клиентов Micro$oft необходимо еще и перевести сертификаты в формат PKCS#12. Для этого воспользуемся командой openssl pkcs12: openssl pkcs12 -export -in client.pem
-inkey client-key.pem -out client.p12 \ -name "Client certificate from our organization"

Для обратного преобразования используется синтаксис:

openssl pkcs12 -in client.p12 -out client.pem

В выходной файл записываются сертификат клиента, ca сертификат, секретный ключ клиента (его можно зашифровать опцией -des3, -idea и.т.д.). Такое поведение позволяет использовать для вывода только формат pem (маркеры здесь обязательны!). Для экспорта сертификата организации можно воспользоваться командой pkcs12 (конечно же, без параметра inkey ;), можно также обработать сертификат организации base64 и сохранить в файле .cer (openssl x509 -in CA.pem -outform DER -out CA.cer).

В openssl существует компонент управления s/mime-сообщениями, называющийся openssl smime. Данная утилита позволяет зашифровывать, расшифровывать, управлять ЭЦП и MIME-заголовками писем. Приведу опять же несколько примеров ее использования:

openssl smime -sign -in mail.txt -text -from CEBKA@smtp.ru -to \



user@mail.ru -subject "Signed message" -signer mycert.pem -inkey \
private_key.pem | sendmail user@mail.ru

Подписывает сообщение -in (в текстовом виде) и подписывает (-sign) его с помощью сертификата (-signer) и секретного ключа (-inkey). Вывод идет непосредственно к sendmail, для этого определены MIME-заголовки from, to и subject.

openssl smime -verify -in mail.msg -signer user.pem -out signedtext.txt

Проверяет подпись в файле -in, записывает сообщение в файл -out, а полученный сертификат — в файл -signer (для проверки s/mime-сообщения не требуется ничего, кроме него самого, т.к. ЭЦП s/mime содержит публичный ключ!). openssl smime -encrypt -in mail.txt -from CEBKA@smtp.ru
-to user@mail.ru \ -subject "Encrypted message" -des3 user.pem | sendmail \ user@mail.ru

Шифрация файла -in с помощью сертификата получателя "user.pem", используя алгоритм "des3". Вывод программы посылается непосредственно в sendmail. openssl smime -decrypt -in mail.msg -recip mycert.pem -inkey private_key.pem \ -out mail.txt

Расшифровка файла -in с помощью секретного ключа -inkey и сертификата -recip (ваш собственный сертификат).

Есть альтернатива не указывать smime-заголовки from, to и subject. Можно просто указать необходимый файл -out и добавить заголовки с помощью программы sendmail вручную. Кроме этого, есть еще одна деталь использования smime: некоторые почтовые клиенты используют в качестве подписи вложение в формате PKCS#7 (чаще всего закодированное base64). В таком случае необходимо применять smime следующим образом: openssl smime -verify -inform [PEM | DER]
-in signature.pem[der] -content \ mail.txt

PEM используется для стандартного формата PKCS#7, а DER заставляет произвести дополнительную обработку base64. Учтите, что в данном случае файл -in представляет собой только подпись (аттачмент), а -content — непосредственно текст письма. Можно также заставить smime подписывать сообщения подобным образом, если указать опцию -pk7out (PEM формат). Для преобразования PKCS#7 структуры из формата PEM в формат DER можно воспользоваться утилитой openssl base64 (обратное преобразование достигается за счет использования опции -d).

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


Содержание раздела