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 появилась возможность использовать STARTTLS в ходе общения с SMTP-серверами.

# порт 25/TLS; использовать такой же синтаксис для порта 587
openssl s_client -connect remote.host:25 -starttls smtp

# порт 465/SSL
openssl s_client -connect remote.host:465

Чтобы использовать для обозначения конца строки именно CRLF, а не CR или LF, используется опция -crlf. Это важно особенно для Qmail.

openssl s_client -connect remote.host:25 -crlf -starttls smtp

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

На момент написания openssl поддерживал TLS из командной строки только с SMTP, поэтому для других протоколов нужно использовать прямые SSL-соединения.

# https: HTTP over SSL
openssl s_client -connect remote.host:443

# ldaps: LDAP over SSL
openssl s_client -connect remote.host:636

# imaps: IMAP over SSL
openssl s_client -connect remote.host:993

# pop3s: POP-3 over SSL
openssl s_client -connect remote.host:995


Как запустить SSL-сервер из командной строки?

Подкоманда s_server позволяет запустить сервер с поддержкой SSL прямо из командной строки; сервер предназначен только для проверки и отладки. Для полноценной работы рекомендуется использовать stunnel.

Подкоманда s_server работает намного лучше, если есть сертификат; когда его нет, её возможности сильно сокращаются.

# при использовании опции -www 
# каждому HTTP-клиенту, запросившему страницу
# будет отправляться статусная страничка HTML
openssl s_server -cert mycert.pem -www

# опция -WWW эмулирует простой web-сервер;
# поиск страничек будет выполняться относительно текущего каталога
# В этом примере прослушивание будет выполнять на порт 443, не на 4433 как обычно
openssl s_server -accept 443 -cert mycert.pem -WWW

Дайджесты

Создание дайджестов (криптографических контрольных сумм) с помощью подкоманды dgst — одна из наиболее распространённых задач, выполняемых с помощью openssl.

Как создавать дайджесты MD5 или SHA1?

Дайджесты создаются с помощью подкоманды dgst:

 # MD5 digest
 openssl dgst -md5 filename
 
 # SHA1 digest
 openssl dgst -sha1 filename

Дайджест MD5 эквивалентен дайджесту, создаваемому известной утилитой md5sum, хотя выводится в другом формате:

$ openssl dgst -md5 foo-2.23.tar.gz
MD5(foo-2.23.tar.gz)= 81eda7985e99d28acd6d286aa0e13e07
$ md5sum foo-2.23.tar.gz
81eda7985e99d28acd6d286aa0e13e07  foo-2.23.tar.gz

То же верно и для дайджестов SHA1 и программы sha1sum:

$ openssl dgst -sha1 foo-2.23.tar.gz
SHA1(foo-2.23.tar.gz)= e4eabc78894e2c204d788521812497e021f45c08
$ sha1sum foo-2.23.tar.gz
e4eabc78894e2c204d788521812497e021f45c08  foo-2.23.tar.gz

Как подписать дайджест?

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

Подписать дайджест SHA1 для файла foo-1.23.tar.gz:

# подписанный дайджест будет в foo-1.23.tar.gz.sha1
openssl dgst -sha1 \
  -sign mykey.pem
  -out foo-1.23.tar.gz.sha1 \
  foo-1.23.tar.gz

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

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

# есть файл foo-1.23.tar.gz, дайджест foo-1.23.tar.gz.sha1
# и открытый ключ pubkey.pem
openssl dgst -sha1 \
    -verify pubkey.pem \
    -signature foo-1.23.tar.gz.sha1 \
    foo-1.23.tar.gz

Как создать запись типа digest для файла паролей Apache?

У web-сервера Apache есть специальный формат файла с паролями, использующийся для выполнения digest-аутентификации. В комплект с web-сервером входит утилита htdigest, но она умеет записывать данные только в файл, а не на стандартный поток вывода. При работе с удалёнными пользователями может быть целесообразным им сначала сгенерировать хэш, а потом переправить его по почте или другому каналу информации для включения в базу.

Формат базы паролей прост: список нескольких полей, разделённых двоеточиями. Поля:

  • имя пользователя (username);
  • область авторизации (authorization realm; AuthRealm);
  • MD5-суммы для этих полей и пароля.

Скрипт, представленный ниже, повторяет действие htdigest с той разницей, что выводит данные на стандартный поток вывода. Кроме того, он умеет считывать данные со стандартного потока ввода.

#!/bin/bash

echo "Create an Apache-friendly Digest Password Entry"
echo "-----------------------------------------------"

# get user input, disabling tty echoing for password
read -p "Enter username: " UNAME
read -p "Enter Apache AuthName: " AUTHNAME
read -s -p "Enter password: " PWORD; echo

printf "\n%s:%s:%s\n" \
  "$UNAME" \
  "$AUTHNAME" \
  $(printf "${UNAME}:${AUTHNAME}:${PWORD}" | openssl dgst -md5)

Какие ещё есть дайджесты?

Подкоманда list-message-digest-commands даёт список типов дайджестов, доступных в данной инсталляции.

openssl list-message-digest-commands

Шифрование/расшифровка

Как закодировать что-то по методу base64?

Использовать опцию -base64.

# закодировать file.txt в base64 и вывести его на стандартный поток вывода
openssl enc -base64 -in file.txt

# то же, но вывести результат в файл file.txt.enc
openssl enc -base64 -in file.txt -out file.txt.enc

Закодировать одну строку:

$ echo "encode me" | openssl enc -base64
ZW5jb2RlIG1lCg==

Без перевода строки (важно для паролей):

$ echo -n "encode me" | openssl enc -base64
ZW5jb2RlIG1l

Опция -d выполняет обратный процесс (то есть, раскодирование):

$ echo "ZW5jb2RlIG1lCg==" | openssl enc -base64 -d
encode me

Как зашифровать файл?

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

Список поддерживаемых шифров есть на странице enc(1). Более просто (и более точно) узнать этот список у самой программы openssl.

# в подзаголовке 'Cipher commands' есть список
openssl -h

# или длинный список, по одному шифру в строке
openssl list-cipher-commands

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

# зашифровать file.txt в file.enc с помощью 256-битного шифра AES в режиме CBC
openssl enc -aes-256-cbc -salt -in file.txt -out file.enc

# то же, но выполнять кодирование base64
openssl enc -aes-256-cbc -a -salt -in file.txt -out file.enc

Расшифровка файла на стороне получателя:

# расшифровать бинарный файл
openssl enc -d -aes-256-cbc -in file.enc

# расшифровать base64-файл
openssl enc -d -aes-256-cbc -a -in file.enc

Можно не вводить парольную фразу постоянно при шифровании и расшифровке, а передавать её автоматически (подробнее: openssl(1); раздел "PASS PHRASE ARGUMENTS"). Формат аргумента прост:

# provide password on command line
openssl enc -aes-256-cbc -salt -in file.txt \
  -out file.enc -pass pass:mySillyPassword

# provide password in a file
openssl enc -aes-256-cbc -salt -in file.txt \
  -out file.enc -pass file:/path/to/secret/password.txt

Ошибки

Как интерпретировать сообщения об ошибках SSL?

В системных журналах обнаружились строки, которые, похоже, имеют отношение к OpenSSL или crypto:

sshd[31784]: error: RSA_public_decrypt failed: error:0407006A:lib(4):func(112):reason(106)
sshd[770]: error: RSA_public_decrypt failed: error:0407006A:lib(4):func(112):reason(106)

В первом приближении определить, что не так, можно с помощью подкоманды errstr, которая умеет интерпретировать код ошибки. Код ошибки находится между "error:" и ":lib". В данном случае это 0407006A.

$ openssl errstr 0407006A
error:0407006A:rsa routines:RSA_padding_check_PKCS1_type_1:block type is not 01

Дальше информацию надо искать в документации. В данном случае в man-странице RSA_padding_add_PKCS1_type_1(3) будет написано, что PKCS #1 использует для подписей блочные методы.

Ключи

Как сгенерировать ключ RSA?

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

# по умолчанию длина ключа 512 бит; ключ выводится на стандартный поток
openssl genrsa

# ключ 1024 бита, сохраняется в файл mykey.pem
openssl genrsa -out mykey.pem 1024

# то же, что выше, только зашифрован с помощью парольной фразы
openssl genrsa -des3 -out mykey.pem 1024

Как сгенерировать открытый ключ RSA?

С помощью подкоманды rsa можно создать открытую версию для закрытого ключа RSA:

openssl rsa -in mykey.pem -pubout

Как сгенерировать ключ DSA?

Для построения ключей DSA нужен специальный файл параметров (parameter file), кроме того, операции с DSA медленнее чем аналогичные операции с RSA, в связи с этим, DSA используется не так часто, как RSA.

Если нужно сгенерировать только один ключ DSA, то это можно сделать одной командой, с помощью подкоманды dsaparam:

# ключ будет называться dsakey.pem
openssl dsaparam -noout -out dsakey.pem -genkey 1024

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

# записать параметры в dsaparam.pem
openssl dsaparam -out dsaparam.pem 1024

# создать первый ключ
openssl gendsa -out key1.pem dsaparam.pem

# и второй
openssl gendsa -out key2.pem dsaparam.pem

Как создать ключ, основанный на эллиптических кривых (elliptic curve key)?

Процедуры для работы с эллиптическими кривыми были добавлены в openssl, начиная с версии 0.9.8. Работа с этими процедурами выполняется через подкоманду ecparam.

openssl ecparam -out key.pem -name prime256v1 -genkey

# openssl может показать полный список параметров кривых, 
# который можно передавать с опцией <tt>-name</tt>
openssl ecparam -list_curves

Как создать открытый EC ключ?

С помощью подкоманды ec можно создать открытую версию для закрытого ключа EC (elliptic curve):

openssl ec -in key.pem -pubout -out pub.pem

Как удалить парольную фразу у ключа?

Каждый раз, когда запускается демон, использующий ключ, надо будет набирать парольную фразу. Её можно убрать.

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

# надо будет ввести парольную фразу
openssl rsa -in key.pem -out newkey.pem

Если закрытый ключ (private key) и открытый сертификат хранятся в одном файле, нужно будет выполнить две команды:

# надо ввести парольную фразу ещё раз
openssl rsa -in mycert.pem -out newcert.pem
openssl x509 -in mycert.pem >>newcert.pem

Хэши для паролей

С помощью подкоманды passwd можно генерировать хэши паролей, которые совместимы со стандартными хэшами из /etc/passwd, /etc/shadow или файла паролей Apache.

Как сгенерировать хэш в стиле crypt?

Сгенерировать хэш очень просто:

$ openssl passwd MySecret
8E4vqBR4UOYF.

Если salt для пароля известен, можно воссоздать хэш.

$ openssl passwd -salt 8E MySecret
8E4vqBR4UOYF.

Как сгенерировать хэш пароля в стиле shadow?

В новых UNIX/Linux-системах вместо старого crypt-хэша используется новый, более стойкий хэш MD5. Его генерирование выполняется с помощью ключа -1:

$ openssl passwd -1 MySecret
$1$sXiKzkus$haDZ9JpVrRHBznY5OxB82.

В этом формате salt состоит из 8 символов; он находится между вторым и третьим знаком $, в данном случае это sXiKzkus.

$ openssl passwd -1 -salt sXiKzkus MySecret
$1$sXiKzkus$haDZ9JpVrRHBznY5OxB82.

Простые числа

Поскольку openssl активно использует механизмы для работы с простыми числами, не удивительно, что в нём есть соответствующие процедуры. Начиная с версии 0.9.7e (или где-то так), в openssl появилась подкоманда binary.

Как проверить, является ли число простым?

Передать число как аргумент к подкоманде prime. Результат будет не в десятичном, а в шестнадцатеричном виде.

$ openssl prime 119054759245460753
1A6F7AC39A53511 is not prime

Можно проверять и шестнадцатеричные числа:

$ openssl prime -hex 2f
2F is prime

Как сгенерировать набор простых чисел?

Сгенерировать множество чисел и оставить только простые среди них. Для генерирования последовательностей удобно использовать seq.

# начальная и конечная точки
AQUO=10000
ADQUEM=10100
for N in $(seq $AQUO $ADQUEM); do
# в десятичную форму преобразуем с помощью bc
openssl prime $N | awk '/is prime/ {print "ibase=16;"$1}' | bc
done

Случайные данные

Как генерировать случайные данные?

Используйте подкоманду rand.

# Выдать 128 случайных байтов, закодированных в base64 на стандартный поток вывода
openssl rand -base64 128

# Записать 1024 случайных байта в файл
openssl rand -out random-data.bin 1024

# Инициализировать генератор случайныхх чисел полуслучайными данными из кэша браузера
cd $(find ~/.mozilla/firefox -type d -name Cache)
openssl rand -rand $(find . -type f -printf '%f:') -base64 1024

На UNIX/Linux-системах, в которых есть файл /dev/urandom, похожего эффекта можно добиться иначе, и иногда с лучшим результатом даже:

# взять 32 символа из /dev/urandom и закодировать их в base64
head -c 32 /dev/urandom | openssl enc -base64

Между устройствами random и urandom есть разница. Дополнительная информация в random(4) для Linux и BSD или random(7D) для Solaris.

S/MIME

S/MIME — стандарт для получения и отправки безопасных MIME-данных, в особенности, почтовых сообщений. Большинство почтовых клиентов умеет работать с такими сообщениями сами, но для этого же можно использовать и openssl smime.

Много хороших примеров есть в smime(1).

Как проверить подписанное сообщение S/MIME?

Проверить, сохранённое в файле msg.txt подписанное сообщение:

openssl smime -verify -in msg.txt

Если сертификат отправителя подписан сервером сертификатов, которому доверяет инсталляция OpenSSL, будут показаны заголовки сообщения, копия сообщения и заключительная строка "Verification successful".

Если сообщение было изменено, в выводе будет содержаться сообщение о том, что подпись или дайджест (контрольная сумма) не соответствуют действительности:

Verification failure
23016:error:21071065:PKCS7 routines:PKCS7_signatureVerify:digest
failure:pk7_doit.c:804:
23016:error:21075069:PKCS7 routines:PKCS7_verify:signature
failure:pk7_smime.c:265:

Если сертификат не опознан, возникнет похожая ошибка:

Verification failure
9544:error:21075075:PKCS7 routines:PKCS7_verify:certificate verify
error:pk7_smime.c:222:Verify error:self signed certificate

Большинство почтовых клиентов отправляют копию открытого сертификата прикреплёнными к сообщению. Данные сертификата можно посмотреть из командной строки. Используется хитрая комбинация подкоманд smime -pk7out и pkcs7. Немного странно на первый взгляд, но работает!

openssl smime -pk7out -in msg.txt | \
openssl pkcs7 -text -noout -print_certs

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

openssl smime -pk7out -in msg.txt -out her-cert.pem

Дальше этот сертификат можно или интегрировать в инфраструктуру OpenSSL, или сохранить его для будущего использования, например, такого:

openssl smime -verify -in msg.txt -CAfile /path/to/her-cert.pem

Как зашифровать сообщение S/MIME?

Допустим, кто-то прислал вам свой сертификат, которым попросил шифровать сообщения ему. Сертификат сохранён в her-cert.pem. Ответ сохранен в файле my-message.txt.

Для того чтобы получить шифрование по умолчанию RC2-40 (оно, правда, слабое), нужно только сказать 'openssl, где находится сертификат:

openssl smime her-cert.pem -encrypt -in my-message.txt

Если есть уверенность, что на удалённой стороне есть современная поддержка SSL, можно использовать алгоритм шифрования посильнее чем DES:

openssl smime her-cert.pem -encrypt -des3 -in my-message.txt

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

openssl smime her-cert.pem \
-encrypt \
-des3 \
-in my-message.txt \
-from 'Your Fullname <you@youraddress.com>' \
-to 'Her Fullname <her@heraddress.com>' \
-subject 'My encrypted reply' |\
sendmail her@heraddress.com

Как подписать сообщение S/MIME?

Подписать (но не шифровать) сообщение своим собственным сертификатом, так чтобы получатель имел возможность убедиться, кто является истинным автором.

openssl smime \
  -sign \
  -signer /path/to/your-cert.pem \
  -in my-message.txt \
  -from 'Your Fullname <you@youraddress.com>' \
  -to 'Her Fullname <her@heraddress.com>' \
  -subject 'My signed reply' |\
sendmail her@heraddress.com


Подключение сертифицированного СКЗИ Рутокен ЭЦП к OpenSSL

http://forum.rutoken.ru/topic/1639/

Дополнительная информация

  • openssl.org (англ.) — домашний сайт проекта
  • Использование OpenSSL (рус.), Всеволод Стахов — большая статья, посвящённая использованию OpenSSL
  • OpenSSL demystified (англ.) — несколько дополнительных примеров использования OpenSSL и родственных инструментов

Примечания

  1. http://www.madboa.com/geek/openssl/
Источник — «http://xgu.ru/wiki/OpenSSL»