OpenSSL

Материал из Xgu.ru

Перейти к: навигация, поиск


OpenSSL — универсальный криптографический инструмент, построенный вокруг протоколов SSL/TLS и сертификатов X.509.

Помимо того, что этот инструмент позволяет работать с соединениями SSL/TLS, сертификатами X.509, он может делать множество других полезных вещей: шифровать и расшифровывать файлы, создавать и проверять цифровые подписи, проверять числа на простоту, тестировать производительность компьютера и другое.


Содержание

Вопросы и ответы

Раздел написан на основе OpenSSL Command-Line HOWTO[1]

Введение

Как определить какую версию OpenSSL я использую?

Использовать опцию version:

$ openssl version
OpenSSL 0.9.8b 04 May 2006

Расширенная информация с опцией -a:

$ openssl version -a
OpenSSL 0.9.8b 04 May 2006
built on: Fri Sep 29 18:45:58 UTC 2006
platform: debian-i386-i686/cmov
options:  bn(64,32) md2(int) rc4(idx,int) des(ptr,risc1,16,long) blowfish(idx) 
compiler: gcc -fPIC -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -D_REENTRANT
-DDSO_DLFCN -DHAVE_DLFCN_H -DL_ENDIAN -DTERMIO -O3 -march=i686
-Wa,--noexecstack -g -Wall -DOPENSSL_BN_ASM_PART_WORDS -DOPENSSL_IA32_SSE2
-DSHA1_ASM -DMD5_ASM -DRMD160_ASM -DAES_ASM
OPENSSLDIR: "/usr/lib/ssl"

Как получить список доступных команд?

Вызвать с неправильным ключом (например, help или -h).

$ openssl help
openssl:Error: 'help' is an invalid command.

Standard commands
asn1parse      ca             ciphers        crl            crl2pkcs7      
dgst           dh             dhparam        dsa            dsaparam       
ec             ecparam        enc            engine         errstr         
gendh          gendsa         genrsa         nseq           ocsp           
passwd         pkcs12         pkcs7          pkcs8          prime          
rand           req            rsa            rsautl         s_client       
s_server       s_time         sess_id        smime          speed          
spkac          verify         version        x509           

Message Digest commands (see the `dgst' command for more details)
md2            md4            md5            rmd160         sha            
sha1           

Cipher commands (see the `enc' command for more details)
aes-128-cbc    aes-128-ecb    aes-192-cbc    aes-192-ecb    aes-256-cbc    
aes-256-ecb    base64         bf             bf-cbc         bf-cfb         
bf-ecb         bf-ofb         cast           cast-cbc       cast5-cbc      
cast5-cfb      cast5-ecb      cast5-ofb      des            des-cbc        
des-cfb        des-ecb        des-ede        des-ede-cbc    des-ede-cfb    
des-ede-ofb    des-ede3       des-ede3-cbc   des-ede3-cfb   des-ede3-ofb   
des-ofb        des3           desx           rc2            rc2-40-cbc     
rc2-64-cbc     rc2-cbc        rc2-cfb        rc2-ecb        rc2-ofb        
rc4            rc4-40

Аналогично с подкомандами:

$ openssl dgst -h
unknown option '-h'
options are
-c              to output the digest with separating colons
-d              to output debug info
-hex            output as hex dump
-binary         output in binary form
-sign   file    sign digest using private key in file
-verify file    verify a signature using public key in file
-prverify file  verify a signature using private key in file
-keyform arg    key file format (PEM or ENGINE)
-signature file signature to verify
-binary         output in binary form
-engine e       use engine e, possibly a hardware device.
-md5 to use the md5 message digest algorithm (default)
-md4 to use the md4 message digest algorithm
-md2 to use the md2 message digest algorithm
-sha1 to use the sha1 message digest algorithm
-sha to use the sha message digest algorithm
-sha256 to use the sha256 message digest algorithm
-sha512 to use the sha512 message digest algorithm
-mdc2 to use the mdc2 message digest algorithm
-ripemd160 to use the ripemd160 message digest algorithm

Как посмотреть список доступных шифров?

Использовать команду ciphers:

# все доступные шифры
openssl ciphers -v

# только шифры TLSv1
openssl ciphers -v -tls1

# только шифры длиною больше 128 битов (high ciphers)
openssl ciphers -v 'HIGH'

# только шифры длиною больше 128 битов, использующие AES
openssl ciphers -v 'AES+HIGH'

Измерение производительности

Как измерить производительность системы с помощью openssl?

Общая производительность:

openssl speed

Пример для 2.16GHz Intel Core 2.

The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes
md2               1736.10k     3726.08k     5165.04k     5692.28k     5917.35k
mdc2                 0.00         0.00         0.00         0.00         0.00 
md4              18799.87k    65848.23k   187776.43k   352258.73k   474622.63k
md5              16807.01k    58256.45k   160439.13k   287183.53k   375220.91k
hmac(md5)        23601.24k    74405.08k   189993.05k   309777.75k   379431.59k
sha1             16774.59k    55500.39k   142628.69k   233247.74k   288382.98k
rmd160           13854.71k    40271.23k    87613.95k   124333.06k   141781.67k
rc4             227935.60k   253366.06k   261236.94k   259858.09k   194928.50k
des cbc          48478.10k    49616.16k    49765.21k    50106.71k    50034.01k
des ede3         18387.39k    18631.02k    18699.26k    18738.18k    18718.72k
idea cbc             0.00         0.00         0.00         0.00         0.00 
rc2 cbc          19247.24k    19838.12k    19904.51k    19925.33k    19834.98k
rc5-32/12 cbc        0.00         0.00         0.00         0.00         0.00 
blowfish cbc     79577.50k    83067.03k    84676.78k    84850.01k    85063.00k
cast cbc         45362.14k    48343.34k    49007.36k    49202.52k    49225.73k
aes-128 cbc      58751.94k    94443.86k   111424.09k   116704.26k   117997.57k
aes-192 cbc      53451.79k    82076.22k    94609.83k    98496.85k    99150.51k
aes-256 cbc      49225.21k    72779.84k    82266.88k    85054.81k    85762.05k
sha256            9359.24k    22510.83k    40963.75k    51710.29k    56014.17k
sha512            7026.78k    28121.32k    54330.79k    86190.76k   104270.51k
                sign    verify    sign/s verify/s
rsa  512 bits 0.000522s 0.000042s   1915.8  23969.9
rsa 1024 bits 0.002321s 0.000109s    430.8   9191.1
rsa 2048 bits 0.012883s 0.000329s     77.6   3039.6
rsa 4096 bits 0.079055s 0.001074s     12.6    931.3
                sign    verify    sign/s verify/s
dsa  512 bits 0.000380s 0.000472s   2629.3   2117.9
dsa 1024 bits 0.001031s 0.001240s    969.6    806.2
dsa 2048 bits 0.003175s 0.003744s    314.9    267.1

Каждый тест можно вызывать отдельно:

# проверить скорость rsa
openssl speed rsa

# проверить то же самое на 2-процессорной системе
openssl speed rsa -multi 2

Как измерить производительность сетевого соединения?

openssl s_time -connect remote.host:443

Помимо этого простейшего измерения у подкоманды s_time есть множество других возможностей:

# получить удалённую страницу test.html, используя только новые сеансы
openssl s_time -connect remote.host:443 -www /test.html -new

# аналогично, но только используя SSLv3 и сильное шифрование
# (подробности относительно шифрования в ciphers(1))
openssl s_time \
  -connect remote.host:443 -www /test.html -new \
  -ssl3 -cipher HIGH

# сравнить относительную производительность разных шифров
# 10-секундные тесты
IFS=":"
for c in $(openssl ciphers -ssl3 RSA); do
echo $c
openssl s_time -connect remote.host:443 \
    -www / -new -time 10 -cipher $c 2>&1 | \
    grep bytes
echo
done

Сэмулировать web-сервер с помощью openssl s_server:

# запустить сервер (на порту 4433)
openssl s_server -cert mycert.pem -www

# на втором хосте (или даже этом же) запустить s_time
openssl s_time -connect myhost:4433 -www / -new -ssl3

Сертификаты

Как сгенерировать самоподписной сертификат?

Создать файл mycert.pem, в котором будет и секретный ключ и открытый сертификат, основанный на нём. Сертификат будет действителен в течение 365 дней; ключ (благодаря опции -nodes) будет нешифрованным.

openssl req \
    -x509 -nodes -days 365 \
    -newkey rsa:1024 -keyout mykey.pem -out mycert.pem

После вызова команды надо будет ответить на несколько вопросов: Country Name, State, City и так далее. На вопрос “Common Name” нужно отвечать именем сервера, по которому будут обращаться люди.

Можно автоматизировать ввод ответов с помощью опции -subj.

openssl req \
  -x509 -nodes -days 365 \
  -subj '/C=US/ST=Oregon/L=Portland/CN=www.madboa.com' \
  -newkey rsa:1024 -keyout mycert.pem -out mycert.pem

Как сгенерировать запрос сертификата у VeriSign?

Секретный ключ в файле mykey.pem и запрос на сертификат myreq.pem:

openssl req \
  -new -newkey rsa:1024 -nodes \
  -keyout mykey.pem -out myreq.pem

Если ключ уже есть, и его надо использовать только для генерации сертификата, используется команда попроще:

openssl req -new -key mykey.pem -out myreq.pem

Или, с информацией для сертификата прямо в командной строке:

openssl req \
-new -newkey rsa:1024 -nodes \
-subj '/CN=www.mydom.com/O=My Dom, Inc./C=US/ST=Oregon/L=Portland' \
-keyout mykey.pem -out myreq.pem

Не допускайте ошибок в названиях! Каждый символ важен.

Проверка:

# проверить подпись
openssl req -in myreq.pem -noout -verify -key mykey.pem

# проверить информацию
openssl req -in myreq.pem -noout -text

Файл с ключом нужно сохранить в надёжном месте.

Как проверить новый сертификат?

Подкоманда s_server предоставляет простой, но эффективный метод тестирования. В примерах ниже предполагается, что ключ и сертификат хранятся в файле mycert.pem.

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

openssl s_server -cert mycert.pem -www

Если команда запустилась без ошибок, открывайте в браузере страницу: https://127.0.0.1:4433/

Как получить удалённый сертификат?

С помощью openssl и sed:

#!/bin/sh
#
# usage: retrieve-cert.sh remote.host.name [port]
#
REMHOST=$1
REMPORT=${2:-443}

echo |\
openssl s_client -connect ${REMHOST}:${REMPORT} 2>&1 |\
sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'

Можно вернуть данные openssl, например, для того чтобы выяснить, для каких дат он действителен:

#!/bin/sh
#
for CERT in \
  www.yourdomain.com:443 \
  ldap.yourdomain.com:636 \
  imap.yourdomain.com:993
do
  echo |\
  openssl s_client -connect ${CERT} 2>/dev/null |\
  sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' |\
  openssl x509 -noout -subject -dates
done

Как извлечь какую-либо информацию из сертификата?

В SSL-сертификате есть много информации, в частности:

  • кто выдал сертификат (issuer);
  • насколько долго он действителен (valid dates);
  • получатель сертификата (subject);
  • разнообразная криптографическая информация.

Опция текст даёт весь объём информации:

openssl x509 -text -in cert.pem

Другие опции дают другую информацию:

# кто его выдал?
openssl x509 -noout -in cert.pem -issuer

# кому его выдали?
openssl x509 -noout -in cert.pem -subject

# до какой даты он действителен?
openssl x509 -noout -in cert.pem -dates

# всё вышеперечисленное:
openssl x509 -noout -in cert.pem -issuer -subject -dates

# какой у него хэш?
openssl x509 -noout -in cert.pem -hash

# какой у него отпечаток MD5?
openssl x509 -noout -in cert.pem -fingerprint

Извлечение открытого ключа, который требуется для проверки цифровой подписи (дайджеста):

openssl x509 -noout -in cert.pem -pubkey > pubkey.pem

Как экспортировать или импортировать сертификат PKCS#12?

Файлы PKCS#12 используются в разных приложениях типа MS IIS. Они часто имеют расширение .pfx.

# создать файл, содержащий ключ и самоподписной сертификат
openssl req \
  -x509 -nodes -days 365 \
  -newkey rsa:1024 -keyout mycert.pem -out mycert.pem

# экспортировать mycert.pem как файл PKCS#12, mycert.pfx
openssl pkcs12 -export \
  -out mycert.pfx -in mycert.pem \
  -name "My Certificate"

Превратить pfx в pem:

# export certificate and passphrase-less key
openssl pkcs12 -in mycert.pfx -out mycert.pem -nodes

# same as above, but you’ll be prompted for a passphrase for
# the private key
openssl pkcs12 -in mycert.pfx -out mycert.pem

Проверка сертификата

Приложения, слинкованные с библиотеками OpenSSL, могут проверять подлинность сертификатов, выданных сервером сертификатов (certificate authority, CA).

Как проверить сертификат?

Использовать подкоманду verify:

openssl verify cert.pem

Если в сертификате всё в норме, то будет выдано сообщение OK:

$ openssl verify remote.site.pem
remote.site.pem: OK

Если чего-то не хватает, появятся соответствующие сообщения об ошибках, например:

  • error 10 at 0 depth lookup:certificate has expired. Время действия сертификата истекло.
  • error 18 at 0 depth lookup:self signed certificate. Если не указать явным образом, openssl не будет проверять самоподписные сертификаты (self-signed certificate).

Какие центры сертификации распознаёт OpenSSL?

При сборке OpenSSL в нём настраивается местоположение OpenSSL-файлов (Directory for OpenSSL files). Этот параметр задаётся опцией --openssldir, передающейся конфигурационному скрипту. В этом каталоге, как правило, хранится информация о центрах сертификации, которым доверяет система.

По умолчанию, этот каталог находится в /usr/local/ssl, но большинство сборщиков размещает его в других местах, таких как /etc/pki/tls (Red Hat/Fedora), /etc/ssl (Gentoo), /usr/lib/ssl (Debian) или /System/Library/OpenSSL (Macintosh OS X).

Посмотреть, какой именно каталог используется в конкретной инсталляции, можно с помощью опции version(параметр OPENSSLDIR):

openssl version -d

Внутри данного каталога есть подкаталог certs/, в котором находятся файлы трёх разных типов:

  1. Большой файл под названием cert.pem, объёмистый сборник многих сертификатов от признанных общеизвестных центров сертификации, таких как VeriSign и Thawte.
  2. Множество маленьких файлов с расширением .pem, каждый из которых содержит сертификат от отдельного центра сертификации;
  3. Символические ссылки в со странными именами вида 052eae11.0. Как правило, для каждого .pem-файла есть такая ссылка.

Первая часть странного имени ссылки — это, на самом деле, хэш, основанный на сертификате внутри .pem-файла, на который эта ссылка указывает. Расширение файла это итератор (то есть, номер), поскольку теоретически возможно, что разные сертификаты укажут на одинаковый хэш.

Например, ссылка f73e89fd.0 указывает на файл vsignss.pem. Значит, сертификат соответствует хэшу, который равен имени ссылки:

$ openssl x509 -noout -hash -in vsignss.pem
f73e89fd

Когда приложение получает удалённый сертификат, оно сначала проверяет, есть ли этот сертификат в cert.pem и, если нет, смотрит в файле, соответствующем хэшу сертификата. Если такой файл найден, сертификат считается верным.

Нужно иметь в виду, что некоторые приложения, такие как Sendmail, например, позволяют во время исполнения указывать местоположение сертификатов, а некоторые, например Pine, нет.

Как мне заставить OpenSSL признавать сертификат?

Сертификат, которому нужно доверять, должен быть размещён в каталоге certs/. После этого необходимо создать хэшированную символическую ссылку на него. Вот небольшой скрипт, который делает это:

#!/bin/sh
#
# usage: certlink.sh filename [filename ...]

for CERTFILE in "$@"; do
  # Убедиться, что файл существует и это сертификат
  test -f "$CERTFILE" || continue
  HASH=$(openssl x509 -noout -hash -in "$CERTFILE")
  test -n "$HASH" || continue

  # использовать для ссылки наименьший итератор
  for ITER in 0 1 2 3 4 5 6 7 8 9; do
    test -f "${HASH}.${ITER}" && continue
    ln -s "$CERTFILE" "${HASH}.${ITER}"
    test -L "${HASH}.${ITER}" && break
  done
done

Клиенты и серверы для командной строки

Подкоманды s_client и s_server предоставляют возможность для запуска SSL-клиентов для командной строки.

Как подключиться к безопасному SMTP-серверу?

С помощью подкоманды s_client можно проверить или даже использовать SMTP-сервер с поддержкой SSL.

Безопасные SMTP-серверы могут предлагать безопасные соединения на портах: 25 (TLS), 465 (SSL) и 587 (TLS). Где-то в районе релиза 0.9.7 у openssl появила