Introduction
Want to learn what version of OpenSSL you have?
OpenSSL is an open-source cryptographic library and SSL toolkit. The applications contained in the library help create a secure communication environment for computer networks.
OpenSSL contains an implementation of SSL and TLS protocols, meaning that most servers and HTTPS websites use its resources.
In this tutorial, learn how to find the OpenSSL version with a single command.
Prerequisites
- A command-line/terminal window.
- OpenSSL installed on your system.
OpenSSL Version Command
The openssl version command allows you to determine the version your system is currently using. This information is useful if you want to find out if a particular feature is available, verify whether a security threat affects your system, or perhaps report a bug. Type in:
openssl version
The resulting data will consist of the OpenSSL version designation and the date of its initial release.
The output is clear and easy to understand. We can break down the version format to get valuable insight. Additionally, using flags can help structure the data.
OpenSSL Releases
The format of the version provides a lot of information. The position of the numbers represent the release type:
- Major Releases – You can recognize a major release if one or both of the first two digits change. This type of release can break compatibility with previous versions. For example: 1.1.0g vs. 1.2.0
- Minor Releases – A minor release changes the last number of the version designation, e.g., 1.1.0 vs. 1.1.1. These releases are likely to contain new features; however, they should not break binary compatibility. You do not need to recompile applications to benefit from them.
- Letter Releases – The release designation in our example 1.1.0g contains bug and security fixes exclusively. No new features were added.
Note: The next planned version of OpenSSL is 3.0.0. Once the new version is released, the versioning scheme is going to change to a more contemporary format: MAJOR.MINOR.PATCH
OpenSSL Flags
By using a general flag –help we can see an overview of all valid options for openssl version.
openssl version –help
There are eight (8) valid options that allow you to narrow your search. The option that provides the most comprehensive set of information is:
openssl version –a
This command compiles all the information contained under the individual flags into a single output.
This option is convenient, especially when troubleshooting or composing a bug report.
The OPENSSLDIR line is especially interesting, as it will tell you where OpenSSL will look for its configurations and certificates. You can print out that specific line by using the following command:
openssl version -d
In this example, the configuration files and certificates are located at /usr/lib/ssl
Conclusion
Now you have learned how to check the OpenSSL version.
You should now understand how to interpret that data. And how it can be used to improve server security, troubleshoot or submit a bug request.
The flags presented in the article provided you with the necessary tools to help you make an informed decision and administer your system effectively.
NAME
OPENSSL_VERSION_MAJOR, OPENSSL_VERSION_MINOR, OPENSSL_VERSION_PATCH, OPENSSL_VERSION_PRE_RELEASE, OPENSSL_VERSION_BUILD_METADATA, OPENSSL_VERSION_TEXT, OPENSSL_VERSION_PREREQ, OPENSSL_version_major, OPENSSL_version_minor, OPENSSL_version_patch, OPENSSL_version_pre_release, OPENSSL_version_build_metadata, OpenSSL_version, OPENSSL_VERSION_NUMBER, OpenSSL_version_num, OPENSSL_info — get OpenSSL version number and other information
SYNOPSIS
#include <openssl/opensslv.h>
#define OPENSSL_VERSION_MAJOR x
#define OPENSSL_VERSION_MINOR y
#define OPENSSL_VERSION_PATCH z
/* The definitions here are typical release values */
#define OPENSSL_VERSION_PRE_RELEASE ""
#define OPENSSL_VERSION_BUILD_METADATA ""
#define OPENSSL_VERSION_TEXT "OpenSSL x.y.z xx XXX xxxx"
#define OPENSSL_VERSION_PREREQ(maj,min)
#include <openssl/crypto.h>
unsigned int OPENSSL_version_major(void);
unsigned int OPENSSL_version_minor(void);
unsigned int OPENSSL_version_patch(void);
const char *OPENSSL_version_pre_release(void);
const char *OPENSSL_version_build_metadata(void);
const char *OpenSSL_version(int t);
const char *OPENSSL_info(int t);
/* from openssl/opensslv.h */
#define OPENSSL_VERSION_NUMBER 0xnnnnnnnnL
/* from openssl/crypto.h */
unsigned long OpenSSL_version_num();
DESCRIPTION
Macros
The three macros OPENSSL_VERSION_MAJOR, OPENSSL_VERSION_MINOR and OPENSSL_VERSION_PATCH represent the three parts of a version identifier, MAJOR.MINOR.PATCH.
The macro OPENSSL_VERSION_PRE_RELEASE is an added bit of text that indicates that this is a pre-release version, such as "-dev"
for an ongoing development snapshot or "-alpha3"
for an alpha release. The value must be a string.
The macro OPENSSL_VERSION_BUILD_METADATA is extra information, reserved for other parties, such as "+fips"
, or "+vendor.1"
). The OpenSSL project will not touch this macro (will leave it an empty string). The value must be a string.
OPENSSL_VERSION_STR is a convenience macro to get the short version identifier string, "MAJOR.MINOR.PATCH"
.
OPENSSL_FULL_VERSION_STR is a convenience macro to get the longer version identifier string, which combines OPENSSL_VERSION_STR, OPENSSL_VERSION_PRE_RELEASE and OPENSSL_VERSION_BUILD_METADATA.
OPENSSL_VERSION_TEXT is a convenience macro to get a full descriptive version text, which includes OPENSSL_FULL_VERSION_STR and the release date.
OPENSSL_VERSION_PREREQ is a useful macro for checking whether the OpenSSL version for the headers in use is at least at the given pre-requisite major (maj) and minor (min) number or not. It will evaluate to true if the header version number (OPENSSL_VERSION_MAJOR.OPENSSL_VERSION_MINOR) is greater than or equal to maj.min.
OPENSSL_VERSION_NUMBER is a combination of the major, minor and patch version into a single integer 0xMNN00PP0L, where:
- M
-
is the number from OPENSSL_VERSION_MAJOR, in hexadecimal notation
- NN
-
is the number from OPENSSL_VERSION_MINOR, in hexadecimal notation
- PP
-
is the number from OPENSSL_VERSION_PATCH, in hexadecimal notation
Functions
OPENSSL_version_major(), OPENSSL_version_minor(), OPENSSL_version_patch(), OPENSSL_version_pre_release(), and OPENSSL_version_build_metadata() return the values of the macros above for the build of the library, respectively.
OpenSSL_version() returns different strings depending on t:
- OPENSSL_VERSION
-
The value of OPENSSL_VERSION_TEXT
- OPENSSL_VERSION_STRING
-
The value of OPENSSL_VERSION_STR
- OPENSSL_FULL_VERSION_STRING
-
The value of OPENSSL_FULL_VERSION_STR
- OPENSSL_CFLAGS
-
The compiler flags set for the compilation process in the form
compiler: ...
if available, orcompiler: information not available
otherwise. - OPENSSL_BUILT_ON
-
The date of the build process in the form
built on: ...
if available orbuilt on: date not available
otherwise. The date would not be available in a reproducible build, for example. - OPENSSL_PLATFORM
-
The «Configure» target of the library build in the form
platform: ...
if available, orplatform: information not available
otherwise. - OPENSSL_DIR
-
The OPENSSLDIR setting of the library build in the form
OPENSSLDIR: "..."
if available, orOPENSSLDIR: N/A
otherwise. - OPENSSL_ENGINES_DIR
-
The ENGINESDIR setting of the library build in the form
ENGINESDIR: "..."
if available, orENGINESDIR: N/A
otherwise. This option is deprecated in OpenSSL 3.0. - OPENSSL_MODULES_DIR
-
The MODULESDIR setting of the library build in the form
MODULESDIR: "..."
if available, orMODULESDIR: N/A
otherwise. - OPENSSL_CPU_INFO
-
The current OpenSSL cpu settings. This is the current setting of the cpu capability flags. It is usually automatically configured but may be set via an environment variable. The value has the same syntax as the environment variable. For x86 the string looks like
CPUINFO: OPENSSL_ia32cap=0x123:0x456
orCPUINFO: N/A
if not available.
For an unknown t, the text not available
is returned.
OPENSSL_info() also returns different strings depending on t:
- OPENSSL_INFO_CONFIG_DIR
-
The configured
OPENSSLDIR
, which is the default location for OpenSSL configuration files. - OPENSSL_INFO_ENGINES_DIR
-
The configured
ENGINESDIR
, which is the default location for OpenSSL engines. - OPENSSL_INFO_MODULES_DIR
-
The configured
MODULESDIR
, which is the default location for dynamically loadable OpenSSL modules other than engines. - OPENSSL_INFO_DSO_EXTENSION
-
The configured dynamically loadable module extension.
- OPENSSL_INFO_DIR_FILENAME_SEPARATOR
-
The separator between a directory specification and a filename. Note that on some operating systems, this is not the same as the separator between directory elements.
- OPENSSL_INFO_LIST_SEPARATOR
-
The OpenSSL list separator. This is typically used in strings that are lists of items, such as the value of the environment variable
$PATH
on Unix (where the separator is:
) or%PATH%
on Windows (where the separator is;
). - OPENSSL_INFO_CPU_SETTINGS
-
The current OpenSSL cpu settings. This is the current setting of the cpu capability flags. It is usually automatically configured but may be set via an environment variable. The value has the same syntax as the environment variable. For x86 the string looks like
OPENSSL_ia32cap=0x123:0x456
.
For an unknown t, NULL is returned.
OpenSSL_version_num() returns the value of OPENSSL_VERSION_NUMBER.
RETURN VALUES
OPENSSL_version_major(), OPENSSL_version_minor() and OPENSSL_version_patch() return the version number parts as integers.
OPENSSL_version_pre_release() and OPENSSL_version_build_metadata() return the values of OPENSSL_VERSION_PRE_RELEASE and OPENSSL_VERSION_BUILD_METADATA respectively as constant strings. For any of them that is undefined, the empty string is returned.
OpenSSL_version() returns constant strings.
SEE ALSO
crypto(7)
HISTORY
The macros and functions described here were added in OpenSSL 3.0, except for OPENSSL_VERSION_NUMBER and OpenSSL_version_num().
COPYRIGHT
Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the «License»). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at https://www.openssl.org/source/license.html.
Категорії
Підбір сертификату
Проверка версии OpenSSL
Определение используемой версии OpenSSL является важным первым шагом в подготовке генерации приватного ключа и запроса CSR. Ваша версия OpenSSL диктует криптографический алгоритм, который может использовать для генерации ключей и поддерживаемый протокол. К примеру, OpenSSL version 1.0.1 является первой версией, поддерживающей TLS 1.1 и TLS 1.2. Знание используемой версииf OpenSSL также важно когда вы решаете возникшие в процессе проблемы.
Команда для определения версии OpenSSL:
openssl version -a
В этой команде, » -a » включит отображение следующей информации:
- Номер версии и дата выхода (OpenSSL 1.0.2g 1 Mar 2016).
- Опции библиотеки (options).
- название директории где находятся сертификат и приватные ключи (OPENSSLDIR).
При вводе команды openssl version -a появится информация такого вида:
OpenSSL 1.0.2g 1 Mar 2016
built on: reproducible build, date unspecified
platform: debian-amd64
options: bn(64,64) rc4(16x,int) des(idx,cisc,16,int) blowfish(idx)
compiler: cc -I. -I.. -I../include -fPIC -DOPENSSL_PIC -DOPENSSL_THREADS -
D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -m64 -DL_ENDIAN -g -O2 -fstack-protector-
strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -Wl,-
Bsymbolic-functions -Wl,-z,relro -Wa,--noexecstack -Wall -DMD32_REG_T=int -
DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -
DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -
DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM -DECP_NISTZ256_ASM
OPENSSLDIR: "/usr/lib/ssl"
OpenSSL and CSR Creation
Первым шагом к получению SSL-сертификата является использование OpenSSL для создания запроса подписи сертификата (CSR), который может быть отправлен в центр сертификации (CA) (например, DigiCert). CSR содержит общее имя (ы), которое вы хотите, чтобы ваш сертификат был защищен, информация о вашей компании и ваш открытый ключ. Чтобы создать CSR, он должен иметь закрытый ключ, из которого извлекается открытый ключ. Это можно сделать, используя существующий закрытый ключ или создав новый закрытый ключ.
Примечание по безопасности. Из-за проблем с безопасностью, связанных с использованием существующего закрытого ключа, а также потому, что очень просто и совершенно бесплатно создавать закрытый ключ, мы рекомендуем создавать новый закрытый ключ при создании CSR.
Выбор вариантов генерации ключей
При создании ключа вы должны решить три вещи:
- Алгоритм ключа Key Algorithm,
- размер ключа Key Size
- использование кодовой фразы Passphrase
Алгоритм ключа
Для ключевого алгоритма вам необходимо учитывать его совместимость. По этой причине мы рекомендуем использовать RSA. Однако, если у вас есть конкретная необходимость использовать другой алгоритм (например, ECDSA), вы также можете использовать его, но помните о проблемах совместимости, с которыми вы можете столкнуться.
Примечание. В этом руководстве рассматриваются только генераторы ключей с использованием алгоритма RSA.
Размер ключа
Для размера ключа вам необходимо выбрать длину бита не менее 2048 при использовании RSA и 256 при использовании ECDSA; это самый маленький размер ключа, разрешенные для сертификатов SSL. Если вам не нужен более крупный размер ключа, мы рекомендуем придерживаться 2048 с RSA и 256 с ECDSA.
Примечание. В старых версиях OpenSSL, если не задан размер ключа, используется размер ключа по умолчанию 512. Любой размер ключа ниже 2048 считается незащищенным и никогда не должен использоваться.
Passphrase
Для ключевой фразы вам нужно решить, хотите ли вы ее использовать. Если используется, закрытый ключ будет зашифрован с использованием указанного метода шифрования, и его невозможно будет использовать без кодовой фразы. Потому что есть плюсы и минусы с обоими опциями, важно понимать последствия использования или не использования кодовой фразы. В этом руководстве мы не будем использовать кодовую фразу в наших примерах.
Создание приватного ключа
После принятия решения по алгоритму и размеру ключа, а также использованию кодовой фразы вы можете приступить к генерации своего закрытого (приватного) ключа.
Используйте следующую команду для генерации вашего закрытого ключа с использованием алгоритма RSA:
openssl genrsa -out yourdomain.key 2048
Эта команда генерирует закрытый ключ в вашем текущем каталоге с именем yourdomain.key (-out yourdomain.key) с использованием алгоритма RSA (genrsa) с длиной ключа 2048 бит (2048). Сгенерированный ключ создается с использованием формата OpenSSL под названием PEM.
Используйте следующую команду для просмотра необработанного, закодированного содержимого (формат PEM) закрытого ключа:
cat yourdomain.key
Несмотря на то, что содержимое файла может выглядеть как случайный фрагмент текста, на самом деле он содержит важную информацию о ключе. Используйте следующую команду для декодирования закрытого ключа и просмотра его содержимого:
openssl rsa -text -in yourdomain.key -noout
Переключатель -noout отключает вывод кодированной версии закрытого ключа.
Извлечение открытого ключа
Файл закрытого ключа содержит как закрытый ключ, так и открытый ключ. Вы можете извлечь свой открытый ключ из своего файла закрытого ключа, если это необходимо.
Используйте следующую команду для извлечения открытого ключа:
openssl rsa -in yourdomain.key -pubout -out yourdomain_public.key
Создание CSR
После создания секретного ключа вы готовы создать свою CSR. CSR создается с использованием формата PEM и содержит часть открытого ключа закрытого ключа, а также информацию о вас (или вашей компании).
Используйте следующую команду для создания CSR с использованием только что созданного закрытого ключа:
openssl req -new -key yourdomain.key -out yourdomain.csr
После ввода команды вам будет задан ряд вопросов. Ваши ответы на эти вопросы будут включены в CSR. Ответьте на вопросы, как описано ниже:
Country Name (2 letter code) | The two-letter country code where your company is legally located. |
State or Province Name (full name) | The state/province where your company is legally located. |
Locality Name (e.g., city) | The city where your company is legally located. |
Organization Name (e.g., company) | Your company’s legally registered name (e.g., YourCompany, Inc.). |
Organizational Unit Name (e.g., section) | The name of your department within the organization. (You can leave this option blank; simply press Enter.) |
Common Name (e.g., server FQDN) | The fully-qualified domain name (FQDN) (e.g., www.example.com). |
Email Address | Your email address. (You can leave this option blank; simply press Enter.) |
A challenge password | Leave this option blank (simply press Enter). |
An optional company name | Leave this option blank (simply press Enter). |
Некоторые из вышеуказанных вопросов CSR имеют значения по умолчанию, которые будут использоваться, если вы оставите пустой ответ и нажмите Enter. Эти значения по умолчанию извлекаются из файла конфигурации OpenSSL, расположенного в OPENSSLDIR (см. Проверка версии OpenSSL). Если вы хотите оставить вопрос пустым, не используя значение по умолчанию, введите «.». (период) и нажмите Enter.
Использование переключателя -subj
Другим вариантом при создании CSR является предоставление всей необходимой информации внутри самой команды с помощью -subj-переключателя.
Используйте следующую команду, чтобы отключить приглашения к запросам при создании CSR:
openssl req -new -key yourdomain.key -out yourdomain.csr -subj "/C=US/ST=Utah/L=Lehi/O=Your Company, Inc./OU=IT/CN=yourdomain.com"
This command uses your private key file (-key yourdomain.key) to create a new CSR (-out yourdomain.csr) and disables question prompts by providing the CSR information (-subj).
Создание CSR с помощью одной команды
Вместо того, чтобы генерировать закрытый ключ, а затем создавая CSR двумя разными шагами, вы можете одновременно выполнять обе задачи.
Используйте следующую команду для создания как закрытого ключа, так и CSR:
openssl req -new -newkey rsa:2048 -nodes -keyout yourdomain.key -out yourdomain.csr -subj "/C=US/ST=Utah/L=Lehi/O=Your Company, Inc./OU=IT/CN=yourdomain.com"
Эта команда генерирует новый закрытый ключ (-newkey) с использованием алгоритма RSA с длиной ключа 2048 бит (rsa: 2048) без использования парольной фразы (-nodes), а затем создает файл ключа с именем yourdomain.key (- keyout yourdomain.key). Затем команда cгенерирует CSR с именем файла yourdomain.csr (-out yourdomain.csr), информация для CSR предоставляется (-subj).
Примечание. Хотя возможно добавление альтернативного имени объекта (SAN) в CSR с использованием OpenSSL, процесс немного сложнее. Если вам нужно добавить SAN в свой сертификат, это легко сделать, добавив их в виде примечания в форму заказа при покупке вашего сертификата ssl.
Проверка информации CSR
После создания вашей CSR с помощью секретного ключа мы рекомендуем проверить правильность информации, содержащейся в CSR, и что файл не был изменен или поврежден.
Используйте следующую команду для просмотра информации в вашей CSR перед отправкой ее в сертификационный центр.
openssl req -text -in yourdomain.csr -noout -verify
Переключатель -noout отключает вывод кодированной версии CSR. Переключатель -verify проверяет подпись файла, чтобы убедиться, что он не был изменен. Выполнение этой команды дает вам следующий результат:
verify OK Certificate Request: Data: Version: 0 (0x0) Subject: C=US, ST=Utah, L=Lehi, O=Your Company, Inc., OU=IT, CN=yourdomain.com Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:bb:31:71:40:81:2c:8e:fb:89:25:7c:0e:cb:76: [...17 lines removed] Exponent: 65537 (0x10001) Attributes: a0:00 Signature Algorithm: sha256WithRSAEncryption 0b:9b:23:b5:1f:8d:c9:cd:59:bf:b7:e5:11:ab:f0:e8:b9:f6: [...14 lines removed]
В первой строке выведенного выше вы увидите, что CSR была проверена (verify OK).
В четвертой строке поле Subject: содержит информацию, предоставленную вами при создании CSR. Убедитесь, что эта информация верна.
Если какая-либо информация неверна, вам нужно будет создать совершенно новІй запрос CSR для исправления ошибок. Это связано с тем, что файлы CSR имеют цифровую подпись, что означает, что даже если в файле изменяется один символ, он будет отклонен центром сертификации.
Отправка CSR в CA
Когда вы подготовите запрос CSR для оформления сертификата SSL, вам нужно использовать формат PEM — необработанный, закодированный текст CSR, который вы увидите при открытии его в текстовом редакторе.
Для того, чтобы просмотреть исходный вывод CSR:
cat yourdomain.csr
Вам надо скопировать содержимое (включая ——BEGIN CERTIFICATE REQUEST—— и ——END CERTIFICATE REQUEST—— вместе с черточками) вставить в текстовый документ и направить в компанию, которая оформляет для вас сертификат ssl.
Просмотр информации о сертификате
После получения сертификата от CA (например, DigiCert) мы рекомендуем убедиться, что информация в сертификате верна и соответствует вашему закрытому ключу. Вы делаете это, используя команду x509.
Используйте следующую команду для просмотра содержимого вашего сертификата:
openssl x509 -text -in yourdomain.crt -noout
Проверка соответствия ваших ключей
Чтобы проверить соответствие ваших общих и закрытых ключей, используйте ключ -modulus для генерации хэша вывода для всех трех файлов (закрытый ключ, CSR и сертификат).
Используйте следующие команды для генерации хэша модуля каждого файла:
openssl rsa -modulus -in yourdomain.key -noout | openssl sha256
openssl req -modulus -in yourdomain.csr -noout | openssl sha256
openssl x509 -modulus -in yourdomain.crt -noout | openssl sha256
Примечание. Вышеприведенные команды должны вводиться один за другим для генерации трех отдельных выходов.
Каждая команда выведет (stdin) =, а затем строку символов. Если результат каждой команды соответствует, то ключи для каждого файла одинаковы.
Однако, если есть какое-либо несоответствие, то ключи не совпадают, и сертификат не может быть установлен.
Ошибки рассогласования ключей обычно вызваны установкой сертификата на машине, отличной от той, которая используется для генерации CSR. Если вы столкнулись с ошибкой несоответствия ключа, вам необходимо выполнить одно из следующих действий:
- Перенесите закрытый ключ из машины, используемой для генерации CSR, к тому, к которому вы пытаетесь установить сертификат.
- Установите сертификат на машине с помощью закрытого ключа.
- Создайте совершенно новый ключ и создайте новый CSR на машине, которая будет использовать сертификат.
Преобразование форматов сертификатов
По умолчанию OpenSSL генерирует ключи и CSR, используя формат PEM. Однако могут быть случаи, когда вам нужно преобразовать свой ключ или сертификат в другой формат, чтобы экспортировать его в другую систему.
PEM для PKCS # 12
Формат PKCS # 12 представляет собой архивный файл, в котором хранятся как сертификат, так и закрытый ключ. Этот формат полезен для переноса сертификатов и ключей из одной системы в другую, так как содержит все необходимые файлы. Файлы PKCS # 12 используют либо расширение .pfx, либо .p12.
Используйте следующую команду для преобразования вашего ключа PEM и сертификата в формат PKCS # 12 (т. Е. Один файл .pfx):
openssl pkcs12 -export -name "yourdomain-digicert-(expiration date)" -out yourdomain.pfx -inkey yourdomain.key -in yourdomain.crt
Примечание. После ввода команды вам будет предложено указать пароль для шифрования файла. Поскольку формат PKCS # 12 часто используется для миграции системы, мы рекомендуем шифровать файл с помощью очень надежного пароля. Эта команда объединяет ваш закрытый ключ (-inkey yourdomain.key) и ваш сертификат (-in yourdomain.crt) в один файл .pfx (-out yourdomain.pfx) с дружественным именем (-name «yourdomain-digicert- (expiration дата) «), где дата истечения срока действия сертификата истекает.
PKCS № 12 для PEM
Поскольку формат PKCS # 12 содержит как сертификат, так и закрытый ключ, вам нужно использовать две отдельные команды для преобразования файла .pfx в формат PEM.
Используйте следующую команду, чтобы извлечь закрытый ключ из файла PKCS # 12 (.pfx) и преобразовать его в закрытый ключ, закодированный PEM:
openssl pkcs12 -in yourdomain.pfx -nocerts -out yourdomain.key -nodes
Используйте следующую команду для извлечения сертификата из файла PKCS # 12 (.pfx) и преобразования его в сертификат, закодированный PEM:
openssl pkcs12 -in yourdomain.pfx -nokeys -clcerts -out yourdomain.crt
Примечание. Вам необходимо указать пароль, используемый для шифрования файла .pfx, чтобы преобразовать ключ и сертификат в формат PEM.
PEM to DER
Формат DER использует кодировку ASN.1 для хранения сертификата или ключевой информации. Подобно формату PEM, DER хранит информацию о ключах и сертификатах в двух отдельных файлах и обычно использует те же расширения файлов (то есть .key, .crt и .csr). Расширение файла .der было использовано в приведенных ниже примерах для ясности.
Используйте следующую команду для преобразования сертификата, закодированного в PEM, в сертификат, закодированный DER:
openssl x509 -inform PEM -in yourdomain.crt -outform DER -out yourdomain.der
Используйте следующую команду для преобразования закрытого ключа, закодированного в PEM, в закрытый закрытый ключ DER:
openssl rsa -inform PEM -in yourdomain.key -outform DER -out yourdomain_key.der
DER to PEM Используйте следующую команду для преобразования закодированного DER сертификата в сертификат, закодированный PEM:
openssl x509 -inform DER -in yourdomain.der -outform PEM -out yourdomain.crt
Используйте следующую команду для преобразования закрытого ключа с кодировкой DER в закрытый секретный ключ PEM:
openssl rsa -inform DER -in yourdomain_key.der -outform PEM -out yourdomain.key
OpenSSL — проект с открытым исходным кодом, состоящий из криптографической библиотеки и набора инструментов SSL/TLS. Цитата с веб-сайта проекта:
Проект OpenSSL Project — это совместный труд по разработке надёжного полнофункционального Open Source-инструментария коммерческого класса, реализующего протоколы Secure Sockets Layer (SSL) и Transport Layer Security (TLS), а также полнофункциональную криптографическую библиотеку общего назначения. Проект управляется сообществом добровольцев со всего мира, использующим Интернет для взаимодействия, планирования и разработки инструментария OpenSSL, а также связанной с ним документации.
OpenSSL является стандартом де-факто в этой области и имеет продолжительную историю. Первоначально проект стартовал в 1995 году под названием SSLeay1, тогда его разработкой занимались Eric A. Young и Tim J. Hudson. Рождение проекта OpenSSL произошло в конце 1998 года, когда Эрик и Тим прекратили свою работу над SSLeay, чтобы работать над коммерческим инструментарием SSL/TLS под названием BSAFE SSL-C в RSA Australia.
Сегодня OpenSSL получил повсеместное распространение как на серверах, так и во многих клиентских программах. Его инструменты командной строки чаще всего выбираются для управления сертификатами, а также для их проверки. Что интересно, в браузерах исторически использовались другие библиотеки, но и это сейчас меняется, поскольку Google переводит Chrome на свой собственный форк OpenSSL, называемый BoringSSL2.
У OpenSSL две лицензии: OpenSSL и SSLeay. Обе схожи с лицензией BSD с оговорками о рекламе. Эти лицензии долгое время были источниками раздора, поскольку ни одна из них не считается совместимой с семейством лицензий GPL. Именно по этой причине программы, лицензированные по лицензии GPL, часто отдают предпочтение GnuTLS.
Начало работы
Если вы используете одну из Unix-платформ, начать работать с OpenSSL легко; практически гарантированно, что в вашей системе он уже есть. Единственная проблема, с которой вы можете столкнуться — то, что у вас может не оказаться последней версии. В данном разделе подразумевается, что вы используете Unix-платформу, потому что это естественная среда для OpenSSL.
Пользователи Windows, как правило, загружают двоичные файлы, что может немного усложнить ситуацию. В простейшем случае, если вам нужны только утилиты командной строки, на основном сайте OpenSSL для Windows-бинарников указана ссылка на сборку от Shining Light Productions3. Во всех остальных ситуациях вам необходимо убедиться, что вы не пытаетесь совместно использовать бинарники, скомпилированные на основе разных версий OpenSSL, иначе могут возникать сбои, которые трудно будет выявить и устранить. Наилучшим подходом будет использование единого пакета программ, который включает в себя всё, что вам нужно. Например, если вы хотите запускать Apache на Windows, вы можете получить требуемые бинарники в сборке Apache Lounge4.
Определение версии и конфигурации OpenSSL
Перед тем, как что-либо сделать, вам необходимо узнать, какую версию OpenSSL вы используете. Например, вот так я получаю информацию о версии с помощью команды openssl version
на Ubuntu 12.04 LTS — системе, которую я буду использовать в примерах этой главы:
$ openssl version OpenSSL 1.0.1 14 Mar 2012
На момент написания этого материала происходил переход от OpenSSL 0.9.x к OpenSSL 1.0.x. Версия 1.0.1 особенно важна, поскольку это первая версия, поддерживающая TLS 1.1 и 1.2. Поддержка более новых протоколов является частью глобального тренда, поэтому вполне вероятно, что в ближайший период мы нередко будем сталкиваться с проблемами совместимости.
Примечание: Часто сборщики различных операционных систем модифицируют исходный код OpenSSL, обычно для устранения выявленных проблем. Однако название проекта и номер версии, как правило, оставляют неизменными, и нет никаких признаков того, что данный код на самом деле является ответвлением исходного проекта и будет вести себя по-другому. Например, версия OpenSSL, используемая в Ubuntu 12.04 LTS5, основана на OpenSSL 1.0.1c. На момент написания этого материала полное имя установочного пакета было openssl 1.0.1-4ubuntu5.16
, и этот пакет включал исправления для многих проблем, которые были выявлены с течением времени.
Для получения полной информации о версии используйте опцию -a
:
$ openssl version -a OpenSSL 1.0.1 14 Mar 2012 built on: Fri Jun 20 18:54:15 UTC 2014 platform: debian-amd64 options: bn(64,64) rc4(8x,int) des(idx,cisc,16,int) blowfish(idx) compiler: cc -fPIC -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN ↩ -DHAVE_DLFCN_H -m64 -DL_ENDIAN -DTERMIO -g -O2 -fstack-protector --param=ssp-buffer-size↩ =4 -Wformat -Wformat-security -Werror=format-security -D_FORTIFY_SOURCE=2 ↩ -Wl,-Bsymbolic-functions -Wl,-z,relro -Wa,--noexecstack -Wall -DOPENSSL_NO_TLS1_2↩ _CLIENT -DOPENSSL_MAX_TLS1_2_CIPHER_LENGTH=50 -DMD32_REG_T=int -DOPENSSL_IA32_SSE2 ↩ -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256↩ _ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH↩ _ASM OPENSSLDIR: "/usr/lib/ssl"
Последняя строка в данном выводе (/usr/lib/ssl
) особенно интересна, поскольку она говорит вам о том, где OpenSSL будет искать собственную конфигурацию и сертификаты. В моей системе это местоположение, по существу, является псевдонимом для директории /etc/ssl
, где Ubuntu хранит файлы, связанные с TLS:
lrwxrwxrwx 1 root root 14 Apr 19 09:28 certs -> /etc/ssl/certs drwxr-xr-x 2 root root 4096 May 28 06:04 misc lrwxrwxrwx 1 root root 20 May 22 17:07 openssl.cnf -> /etc/ssl/openssl.cnf lrwxrwxrwx 1 root root 16 Apr 19 09:28 private -> /etc/ssl/private
Директория misc/
содержит несколько дополнительных скриптов, наиболее интересными из которых являются скрипты, позволяющие реализовать приватный центр сертификации или удостоверяющий центр (УЦ).
Сборка OpenSSL
В большинстве случаев вы будете использовать версию OpenSSL, поставляемую с операционной системой, но иногда есть веские причины для обновления. Например, ваша система могла застрять на OpenSSL 0.9.x, не поддерживающей новые версии протокола TLS, но даже если в вашей системе правильная версия OpenSSL, в ней может не быть необходимого вам функционала. Например, на Ubuntu 12.04 LTS нет поддержки SSL 2 в команде s_client
. Хотя отсутствие по умолчанию поддержки этой версии SSL является правильным решением, вам может понадобиться данный функционал, если вы регулярно тестируете другие серверы на поддержку SSL 2.
Вы можете начать с загрузки самой последней версии OpenSSL (в моем случае, 1.0.1p):
$ wget http://www.openssl.org/source/openssl-1.0.1p.tar.gz
Следующий шаг — конфигурирование OpenSSL перед компиляцией. В большинстве случаев системная версия оставляется в покое и OpenSSL устанавливается в другое место. Например:
$ ./config --prefix=/opt/openssl --openssldir=/opt/openssl enable-ec_nistp_64_gcc_128
Параметр enable-ec_nistp_64_gcc_128
активирует оптимизированные версии некоторых часто используемых эллиптических кривых. Данная оптимизация зависит от функции компилятора, которая не может быть обнаружена автоматически, поэтому по умолчанию этот параметр отключен.
Примечание: Если вы компилируете версию OpenSSL из ветки 1.1.x или выше, то, по крайней мере в некоторых системах, вам нужно будет использовать параметр no-shared
для создания статически скомпилированных инструментов командной строки. Вы поймёте, что нужно использовать этот параметр, если (после компиляции) при попытке вызвать бинарник OpenSSL он будет жаловаться на то, что не может найти некоторые требуемые ему разделяемые библиотеки.
Затем нужно будет выполнить следующие команды:
$ make depend $ make $ sudo make install
В итоге в директории /opt/openssl
у вас будет такое содержимое:
drwxr-xr-x 2 root root 4096 Jun 3 08:49 bin drwxr-xr-x 2 root root 4096 Jun 3 08:49 certs drwxr-xr-x 3 root root 4096 Jun 3 08:49 include drwxr-xr-x 4 root root 4096 Jun 3 08:49 lib drwxr-xr-x 6 root root 4096 Jun 3 08:48 man drwxr-xr-x 2 root root 4096 Jun 3 08:49 misc -rw-r--r-- 1 root root 10835 Jun 3 08:49 openssl.cnf drwxr-xr-x 2 root root 4096 Jun 3 08:49 private
Директория private/
пуста, но это нормально: у вас ещё нет каких-либо закрытых ключей. С другой стороны, вы, вероятно, удивитесь, узнав, что директория certs/
тоже пуста. В OpenSSL не включено никаких корневых сертификатов; подразумевается, что поддержание доверенного хранилища выходит за рамки проекта. К счастью, в состав вашей операционной системы, скорее всего, уже входит доверенное хранилище, которое можно использовать. Кроме того, как мы продемонстрируем в одном из следующих разделов, вы можете без особого труда построить своё собственное.
Примечание: При компиляции программного обеспечения важно хорошо разбираться с настройками по умолчанию вашего компилятора. Пакеты, распространяемые с системой, обычно компилируются с использованием всех доступных параметров повышения безопасности, но при самостоятельной компиляции какого-то программного обеспечения нет гарантии, что будут применяться те же параметры6.
Просмотр доступных команд
OpenSSL — это криптографический инструментарий, состоящий из множества различных утилит. В моей версии я насчитал 46. Тот самый случай, когда уместно употребить фразу Швейцарский армейский нож криптографии, так оно и есть. Даже если вы будете использовать всего несколько утилит, вам следует ознакомиться со всеми доступными, поскольку неизвестно, что может понадобиться в будущем.
Специального ключевого слова для вызова справки не существует, однако справочный текст отображается всякий раз, когда вы вводите что-то, что OpenSSL не может распознать:
$ openssl help openssl:Error: 'help' is an invalid command. Standard commands asn1parse ca ciphers cms crl crl2pkcs7 dgst dh dhparam dsa dsaparam ec ecparam enc engine errstr gendh gendsa genpkey genrsa nseq ocsp passwd pkcs12 pkcs7 pkcs8 pkey pkeyparam pkeyutl prime rand req rsa rsautl s_client s_server s_time sess_id smime speed spkac srp ts verify version x509
Первая часть справки выводит список всех доступных утилит. Чтобы получить больше информации о конкретной утилите, используйте man
с именем этой утилиты. Например, man ciphers
выдаст подробную информацию о том, как настроены наборы алгоритмов шифрования (наборы шифров).
Вывод справки этим не заканчивается, но остальное несколько менее интересно. Во второй части вы увидите список команд для работы с дайджестами сообщений (алгоритмами хэширования):
Message Digest commands (see the `dgst’ command for more details)
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 camellia-128-cbc camellia-128-ecb camellia-192-cbc camellia-192-ecb camellia-256-cbc camellia-256-ecb 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 seed seed-cbc seed-cfb seed-ecb seed-ofb zlib
Построение доверенного хранилища
Вместе с OpenSSL не поставляется каких-либо доверенных корневых сертификатов (ещё говорят доверенное хранилище), так что если вы выполняете установку с нуля, то придётся поискать их где-то на стороне. Один из возможных вариантов — использовать доверенное хранилище, встроенное в вашу операционную систему. Обычно этот вариант хорош, но доверенные хранилища, имеющиеся в операционной системе по умолчанию, могут не всегда быть актуальны. Лучший (но более трудоёмкий) вариант — обратиться к Mozilla, которые прилагают много усилий для поддержания надёжного доверенного хранилища. Далее будет приведён реальный пример, как я получал доверенное хранилище для своего инструмента оценки в SSL Labs.
Поскольку проекты Mozilla с открытым исходным кодом, их доверенное хранилище можно найти в репозитории исходного кода:
https://hg.mozilla.org/mozilla-central/raw-file/tip/security/nss/lib/ckfw/builtins/certdata.txt
К сожалению, их коллекция сертификатов находится в проприетарном формате, который в исходном состоянии нам бесполезен. Если у вас нет предрассудков в смысле получения этой коллекции от третьих лиц, проект Curl предоставляет регулярно обновляемую сконвертированную в формат Privacy-Enhanced Mail (PEM) версию, которую вы можете использовать сразу:
http://curl.haxx.se/docs/caextract.html
Но даже если вы скачаете коллекцию напрямую с сайта Mozilla, вам не придётся самостоятельно писать скрипт конвертации. Такие скрипты доступны на языках Perl и Go, их использование будет описано в следующих разделах.
Примечание: Если вы всё же решите написать собственный скрипт преобразования, имейте ввиду, что файл корневых сертификатов от Mozilla фактически содержит два типа сертификатов: доверенные (являющиеся частью хранилища), а также явно недоверенные. В Mozilla используют такой механизм для запрета скомпрометированных сертификатов промежуточных УЦ (например, старых сертификатов DigiNotar). Оба описанных далее инструмента работы с файлом Mozilla достаточно разборчивы и способны исключить недоверенные сертификаты в процессе конвертации.
Конвертация с использованием Perl
Проект Curl обнародовал Perl-срипт, написанный Guenter Knauf, который может быть использован для конвертации доверенного хранилища Mozilla:
https://raw.github.com/bagder/curl/master/lib/mk-ca-bundle.pl
После скачивания и запуска скрипта он извлечёт данные сертификатов из хранилища Mozilla и преобразует их в формат PEM:
$ ./mk-ca-bundle.pl Downloading 'certdata.txt' ... Processing 'certdata.txt' ... Done (156 CA certs processed, 19 untrusted skipped).
Если вы сохраняете ранее загруженные данные сертификатов, скрипт будет использовать их для определения того, что изменилось, и обрабатывать только обновления.
Конвертация с использованием Go
Если вы предпочитаете язык программирования Go, обратите внимание на инструмент конвертации от Adam Langley, который можно получить на GitHub:
https://github.com/agl/extract-nss-root-certs
Для выполнения конвертации сначала скачайте сам инструмент:
$ wget https://raw.github.com/agl/extract-nss-root-certs/master/convert_mozilla_certdata.go
А потом данные сертификатов от Mozilla:
$ wget https://hg.mozilla.org/mozilla-central/raw-file/tip/security/nss/lib/ckfw/builtins/certdata.txt --output-document certdata.txt
Наконец, переконвертируйте файл следующей командой:
$ go run convert_mozilla_certdata.go > ca-certificates 2012/06/04 09:52:29 Failed to parse certificate starting on line 23068: negative serial number
В моём случае имел место некорректный сертификат, который не смогла обработать библиотека X.509 языка Go, но обычно конвертация проходит без эксцессов. Версии Go, начиная с версии 1.6 и выше, не должны выдавать это предупреждение, поскольку они могут обрабатывать сертификаты с отрицательными серийными номерами.
Управление ключами и сертификатами
Большинство пользователей обращаются к OpenSSL, потому что хотят настроить и запустить веб-сервер с поддержкой SSL. Этот процесс состоит из трёх этапов: (1) генерация стойкого закрытого ключа, (2) создание запроса на подписание сертификата (Certificate Signing Request, CSR) и направление его в УЦ, и (3) инсталляция предоставленного УЦ сертификата в ваш веб-сервер. Об этих (и некоторых других) этапах пойдёт речь в данном разделе.
Генерация ключа
Первым шагом в подготовке к использованию асимметричного шифрования является создание закрытого ключа. Прежде чем начать, вы должны принять несколько решений:
- Ключевой алгоритм
-
OpenSSL поддерживает ключи RSA, DSA и ECDSA, но не все типы безоговорочно подходят для любого сценария использования. Например, в качестве ключа веб-сервера повсеместно используется RSA, поскольку ключи DSA по существу ограничены 1024 битами (Internet Explorer не поддерживает ничего более стойкого), а ключи ECDSA ещё не получили широкой поддержки УЦ. Для SSH везде используются DSA и RSA, поскольку ECDSA может не поддерживаться всеми клиентами.
- Размер ключа
-
Размер ключа по умолчанию может быть небезопасным, поэтому его всегда следует настраивать явно. Например, размер по умолчанию для ключей RSA всего 512 бит, что попросту небезопасно. Если в наши дни вы будете использовать на своём сервере ключ длиной 512 бит, злоумышленник, получив ваш сертификат, может простым перебором (методом «грубой силы») подобрать ваш закрытый ключ, после чего он или она сможет выдавать себя за ваш веб-сайт. В наши дни безопасными считаются ключи RSA в 2048 бит, их и нужно использовать. Также необходимо использовать ключи DSA длиной 2048 бит и не менее 256 бит для ECDSA.
- Кодовая фраза
-
Использовать кодовую фразу (passphrase) с ключом необязательно, но настоятельно рекомендуется. Защищённые ключи можно безопасно хранить, транспортировать и создавать резервные копии. С другой стороны, такие ключи неудобны, поскольку без ввода кодовой фразы их использовать нельзя. Например, запрос на ввод кодовой фразы может возникать каждый раз, когда вы захотите перезапустить ваш веб-сервер. В большинстве случаев это либо слишком неудобно, либо создаёт неприемлемые условия для доступности сервисов. Кроме того, использование защищённых ключей в рабочей среде на самом деле не сильно повышает безопасность (если вообще повышает). Это связано с тем, что после первоначальной активации закрытые ключи хранятся в незащищённом виде в памяти программы; злоумышленник, проникнувший на сервер, может получить ключи оттуда, приложив при этом лишь немного больше усилий. Так что кодовые фразы следует рассматривать только в качестве механизма защиты закрытого ключа, пока он не установлен в рабочей среде. Другими словами, нет ничего страшного в том, чтобы в рабочей среде хранить кодовые фразы рядом с ключами. Если же в рабочей среде вам требуется повышенная безопасность, стоит рассмотреть вариант с инвестированием в аппаратные решения7.
Для генерации ключа RSA используйте команду genrsa
:
$ openssl genrsa -aes128 -out fd.key 2048 Generating RSA private key, 2048 bit long modulus ....+++ ...................................................................................+++ e is 65537 (0x10001) Enter pass phrase for fd.key: **************** Verifying - Enter pass phrase for fd.key: ****************
Здесь я указал, что ключ будет защищён с помощью AES-128. Также вы можете использовать AES-192 или AES-256 (параметры -aes192
и -aes256
, соответственно), но лучше воздержаться от применения других алгоритмов (DES, 3DES и SEED).
Предупреждение: Значение e
, которое вы видите в выводе, относится к открытой экспоненте (public exponent), которая по умолчанию установлена в 65537. Это так называемая короткая открытая экспонента, и она значительно повышает производительность верификации RSA. При использовании параметра -3
можно выбрать в качестве открытой экспоненты число 3 и сделать верификацию ещё быстрее. Однако в истории было несколько неприятных происшествий, связанных с использованием числа 3 в качестве открытой экспоненты, поэтому, как правило, всем рекомендуется придерживаться числа 65537, обеспечивая тем самым запас прочности с исторически доказанной эффективностью.
Закрытые ключи хранятся в так называемом PEM-формате, представляющем собой просто текст:
$ cat fd.key -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,01EC21976A463CE36E9DB59FF6AF689A vERmFJzsLeAEDqWdXX4rNwogJp+y95uTnw+bOjWRw1+O1qgGqxQXPtH3LWDUz1Ym mkpxmIwlSidVSUuUrrUzIL+V21EJ1W9iQ71SJoPOyzX7dYX5GCAwQm9Tsb40FhV/ [21 lines removed...] 4phGTprEnEwrffRnYrt7khQwrJhNsw6TTtthMhx/UCJdpQdaLW/TuylaJMWL1JRW i321s5me5ej6Pr4fGccNOe7lZK+563d7v5znAx+Wo1C+F7YgF+g8LOQ8emC+6AVV -----END RSA PRIVATE KEY-----
Закрытый ключ — это не просто набор случайных данных, как может показаться на первый взгляд. Структуру ключа можно увидеть, используя следующую команду rsa
:
$ openssl rsa -text -in fd.key Enter pass phrase for fd.key: **************** Private-Key: (2048 bit) modulus: 00:9e:57:1c:c1:0f:45:47:22:58:1c:cf:2c:14:db: [...] publicExponent: 65537 (0x10001) privateExponent: 1a:12:ee:41:3c:6a:84:14:3b:be:42:bf:57:8f:dc: [...] prime1: 00:c9:7e:82:e4:74:69:20:ab:80:15:99:7d:5e:49: [...] prime2: 00:c9:2c:30:95:3e:cc:a4:07:88:33:32:a5:b1:d7: [...] exponent1: 68:f4:5e:07:d3:df:42:a6:32:84:8d:bb:f0:d6:36: [...] exponent2: 5e:b8:00:b3:f4:9a:93:cc:bc:13:27:10:9e:f8:7e: [...] coefficient: 34:28:cf:72:e5:3f:52:b2:dd:44:56:84:ac:19:00: [...] writing RSA key -----BEGIN RSA PRIVATE KEY----- [...] -----END RSA PRIVATE KEY-----
Если вам понадобится иметь отдельно только открытую часть ключа, выделить её можно следующей командой rsa
:
$ openssl rsa -in fd.key -pubout -out fd-public.key Enter pass phrase for fd.key: ****************
Заглянув во вновь созданный файл, можно увидеть метки, ясно указывающие на то, что содержимое действительно является открытой информацией:
$ cat fd-public.key -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnlccwQ9FRyJYHM8sFNsY PUHJHJzhJdwcS7kBptutf/L6OvoEAzCVHi/m0qAA4QM5BziZgnvv+FNnE3sgE5pz iovEHJ3C959mNQmpvnedXwfcOIlbrNqdISJiP0js6mDCzYjSO1NCQoy3UpYwvwj7 0ryR1F+abARehlts/Xs/PtX3VamrljiJN6JNgFICy3ZvEhLZEKxR7oob7TnyZDrj IHxBbqPNzeiqLCFLFPGgJPa0cH8DdovBTesvu7wr/ecsf8CYyUCdEwGkZh9DKtdU HFa9H8tWW2mX6uwYeHCnf2HTw0E8vjtOb8oYQxlQxtL7dpFyMgrpPOoOVkZZW/P0 NQIDAQAB -----END PUBLIC KEY-----
Лишний раз убедиться в том, что на выходе вы получили именно то, что хотели — это хорошая практика. Например, если вы забудете указать в командной строке параметр -pubout
, выходной файл будет содержать ваш закрытый ключ вместо открытого.
Генерация ключа DSA происходит в два этапа: на первом создаются параметры DSA, а на втором — ключ. Можно выполнять их последовательно один за другим, но мне больше нравится использовать следующие две команды как одну:
$ openssl dsaparam -genkey 2048 | openssl dsa -out dsa.key -aes128 Generating DSA parameters, 2048 bit long prime This could take some time [...] read DSA key writing DSA key Enter PEM pass phrase: **************** Verifying - Enter PEM pass phrase: ****************
Этот подход позволяет мне генерировать защищённый кодовой фразой ключ, не оставляя при этом никаких временных файлов (с параметрами DSA) и/или временных ключей на диске.
Для ключей ECDSA процесс аналогичен, за исключением того, что отсутствует возможность создать ключи произвольных размеров. Вместо этого для каждого ключа вы выбираете именованную кривую (named curve), которая контролирует размер ключа, а также другие параметры EC. В следующем примере создаётся 256-битный ключ ECDSA с использованием именованной кривой secp256r1
:
$ openssl ecparam -genkey -name secp256r1 | openssl ec -out ec.key -aes128 using curve name prime256v1 instead of secp256r1 read EC key writing EC key Enter PEM pass phrase: **************** Verifying - Enter PEM pass phrase: ****************
OpenSSL поддерживает много именованных кривых (полный список можно получить с помощью параметра -list_curves
), но для ключей веб-сервера выбор ограничен лишь двумя кривыми, которые поддерживаются всеми основными браузерами: secp256r1
(в OpenSSL используется имя prime256v1
) и secp384r1
.
Примечание: Если вы используете OpenSSL 1.0.2, вы можете сэкономить время, всегда генерируя ключи с помощью команды genpkey
, которая была усовершенствована для поддержки различных типов ключей и параметров конфигурации. В настоящее время она представляет собой унифицированный интерфейс для генерации ключей.
Создание запроса на подписание сертификата
Получив закрытый ключ, вы можете приступить к созданию запроса на подписание сертификата (Certificate Signing Request, CSR). Это формализованный запрос в УЦ о подписании сертификата, в котором содержится открытый ключ объекта, запрашивающего сертификат, а также некоторая информация об этом объекте. Все эти данные будут частью будущего сертификата. CSR всегда подписывается закрытым ключом, соответствующим тому открытому ключу, который содержится в запросе.
Обычно создание CSR представляет собой интерактивный процесс, в ходе которого вам потребуется предоставить элементы уникального имени объекта сертификата. Внимательно читайте инструкции, выдаваемые инструментом openssl
; если вы хотите оставить поле пустым, вы должны ввести в строку запроса символ точки (.
), а не просто нажать клавишу «Ввод» (в этом случае OpenSSL заполнит соответствующее поле CSR значением по умолчанию). Согласие со значениями по умолчанию не имеет никакого смысла, когда при генерации CSR используется конфигурация OpenSSL по умолчанию (весьма распространённая практика). И наоборот, вполне резонно соглашаться со значениями по умолчанию, когда вы их сами задали, либо поменяв конфигурацию OpenSSL, либо предоставив свои собственные файлы конфигурации.
$ openssl req -new -key fd.key -out fd.csr Enter pass phrase for fd.key: **************** You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:GB State or Province Name (full name) [Some-State]:. Locality Name (eg, city) []:London Organization Name (eg, company) [Internet Widgits Pty Ltd]:Feisty Duck Ltd Organizational Unit Name (eg, section) []: Common Name (e.g. server FQDN or YOUR name) []:www.feistyduck.com Email Address []:webmaster@feistyduck.com Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
Примечание: В соответствии с разделом 5.4.1 RFC 29858, проблемный пароль (challenge password) является необязательным полем, предназначенным для использования во время отзыва сертификата как способ идентификации исходного объекта, запросившего данный сертификат. Если этот пароль введен, он будет дословно включён в CSR и передан в УЦ. Редко можно найти УЦ, обрабатывающий данное поле; во всех инструкциях, которые я видел, рекомендуется оставить его незаполненным. Задание проблемного пароля никоим образом не повышает безопасность CSR. Кроме того, это поле не следует путать с кодовой фразой, которая является отдельной характеристикой.
После генерации CSR он используется для подписания своего собственного сертификата и/или отправки в публичный УЦ с просьбой подписать сертификат. Оба подхода будут описаны в последующих разделах. Но прежде чем сделать это, стоит ещё раз проверить правильность CSR. Это делается так:
$ openssl req -text -in fd.csr -noout Certificate Request: Data: Version: 0 (0x0) Subject: C=GB, L=London, O=Feisty Duck Ltd, CN=www.feistyduck.com↩ /emailAddress=webmaster@feistyduck.com Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:b7:fc:ca:1c:a6:c8:56:bb:a3:26:d1:df:e4:e3: [ещё 16 строк...] d1:57 Exponent: 65537 (0x10001) Attributes: a0:00 Signature Algorithm: sha1WithRSAEncryption a7:43:56:b2:cf:ed:c7:24:3e:36:0f:6b:88:e9:49:03:a6:91: [ещё 13 строк...] 47:8b:e3:28
Создание CSR из существующего сертификата
Если вы продлеваете сертификат и не хотите вносить какие-либо изменения в представленную в нём информацию, можно упростить себе жизнь и печатать немного поменьше. С помощью следующей команды вы сможете создать новенький CSR из существующего сертификата:
$ openssl x509 -x509toreq -in fd.crt -out fd.csr -signkey fd.key
Примечание: За исключением случаев применения некоторой формы привязывания открытого ключа (public key pinning), при которых вы захотите продолжать использовать существующий ключ, лучшей практикой считается генерация нового ключа каждый раз при запросе нового сертификата. Генерация ключей — быстрая и недорогая операция, к тому же значительно снижающая ваши риски.
Автоматизированная генерация CSR
Генерация CSR не обязательно должна быть интерактивной. Используя отличный от поставляемого по умолчанию файл конфигурации OpenSSL, вы можете решить сразу две задачи: автоматизировать процесс (как объясняется в этом разделе), а также сделать некоторые вещи, которые невозможны в интерактивном режиме (мы обсудим это в последующих разделах).
Например, предположим, что вы хотите автоматизировать генерацию CSR для www.feistyduck.com
. Для начала нужно создать файл fd.cnf
следующего содержания:
[req]
prompt = no
distinguished_name = dn
req_extensions = ext
input_password = PASSPHRASE
[dn]
CN = www.feistyduck.com
emailAddress = webmaster@feistyduck.com
O = Feisty Duck Ltd
L = London
C = GB
[ext]
subjectAltName = DNS:www.feistyduck.com,DNS:feistyduck.com
Ну а теперь можно создать CSR прямо из командной строки:
$ openssl req -new -config fd.cnf -key fd.key -out fd.csr
Подписание своего собственного сертификата
Если вы устанавливаете TLS-сервер для внутреннего использования, вам, вероятно, нет нужды обращаться в УЦ за публично доверенным сертификатом. Гораздо проще просто использовать самоподписанный сертификат. Если вы пользуетесь браузером Firefox, при первом посещении веб-сайта можно создать исключение для вашего сертификата, после чего этот сайт будет столь же безопасен, как если бы он был защищён публично доверенным сертификатом.
Если у вас уже есть CSR, создайте сертификат следующей командой:
$ openssl x509 -req -days 365 -in fd.csr -signkey fd.key -out fd.crt Signature ok subject=/CN=www.feistyduck.com/emailAddress=webmaster@feistyduck.com/O=Feisty Duck Ltd↩ /L=London/C=GB Getting Private key Enter pass phrase for fd.key: ****************
На самом деле вам не нужно отдельно создавать CSR. С помощью следующей команды можно создать самоподписанный сертификат, имея в наличии только ключ:
$ openssl req -new -x509 -days 365 -key fd.key -out fd.crt
Чтобы не отвечать ни на какие вопросы, используйте параметр -subj
для предоставления информации о субъекте сертификата в командной строке:
$ openssl req -new -x509 -days 365 -key fd.key -out fd.crt -subj "/C=GB/L=London/O=Feisty Duck Ltd/CN=www.feistyduck.com"
Создание сертификата, действительного для нескольких имен хостов
По умолчанию сертификаты, созданные OpenSSL, имеют только одно поле для общепринятого имени (common name) и действительны только для одного имени хоста. По этой причине, даже если у вас есть связанные веб-сайты, вы будете вынуждены использовать отдельный сертификат для каждого из них. В данной ситуации более оправданным представляется использование одного мультидоменного сертификата. Кроме того, даже если у вас один веб-сайт, необходимо убедиться, что сертификат действителен для всех возможных путей, по которым конечные пользователи могут пытаться получить к нему доступ. На практике это означает использование как минимум двух имен, одно из которых будет с префиксом www
, а второе — без него (например, www.feistyduck.com
и feistyduck.com
).
Существует два механизма поддержки нескольких имен хостов в сертификате. Первый — перечислить все желательные имена, используя расширение X.509, которое называется Альтернативное имя субъекта (Subject Alternative Name, SAN). Второй — использовать шаблоны подстановки (wildcard). Также можно использовать комбинацию этих двух подходов (если это более удобно). На практике, для большинства сайтов можно указать просто доменное имя и шаблон подстановки для охвата всех возможных поддоменов (например, feistyduck.com
и *.feistyduck.com
).
Предупреждение: Когда в сертификате содержатся альтернативные имена, все общепринятые имена игнорируются. Более новые сертификаты, выпускаемые УЦ, могут даже не содержать общепринятых имён. Поэтому нужно включать все желаемые имена хостов в список альтернативных имён.
Сначала поместите информацию расширения в отдельный текстовый файл. У меня он будет называться fd.ext
. В этом файле укажите имя расширения (subjectAltName
) и список желаемых имён хостов, как в данном примере:
subjectAltName = DNS:*.feistyduck.com, DNS:feistyduck.com
Затем, используя команду x509
, оформите сертификат, указав файл с расширением с помощью параметра -extfile
:
$ openssl x509 -req -days 365 -in fd.csr -signkey fd.key -out fd.crt -extfile fd.ext
В остальном процесс ничем не отличается от рассмотренного ранее. Но когда вы в дальнейшем исследуете сгенерированный сертификат, вы обнаружите, что он содержит расширение SAN:
X509v3 extensions: X509v3 Subject Alternative Name: DNS:*.feistyduck.com, DNS:feistyduck.com
Исследование сертификата
На первый взгляд сертификаты могут выглядеть как куча случайных данных, но они содержат много информации; вам нужно только знать, как до неё добраться. Команда x509
делает именно это, поэтому воспользуемся ею, чтобы рассмотреть самоподписанные сертификаты, которые вы сгенерировали.
В следующем примере я использовал параметр -text
для печати содержимого сертификата, а также параметр -noout
, чтобы не выводить сам закодированный сертификат (что выполняется по умолчанию) и не отвлекать нас от главного:
$ openssl x509 -text -in fd.crt -noout Certificate: Data: Version: 1 (0x0) Serial Number: 13073330765974645413 (0xb56dcd10f11aaaa5) Signature Algorithm: sha1WithRSAEncryption Issuer: CN=www.feistyduck.com/emailAddress=webmaster@feistyduck.com, O=Feisty ↩ Duck Ltd, L=London, C=GB Validity Not Before: Jun 4 17:57:34 2012 GMT Not After : Jun 4 17:57:34 2013 GMT Subject: CN=www.feistyduck.com/emailAddress=webmaster@feistyduck.com, O=Feisty ↩ Duck Ltd, L=London, C=GB Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:b7:fc:ca:1c:a6:c8:56:bb:a3:26:d1:df:e4:e3: [ещё 16 строк...] d1:57 Exponent: 65537 (0x10001) Signature Algorithm: sha1WithRSAEncryption 49:70:70:41:6a:03:0f:88:1a:14:69:24:03:6a:49:10:83:20: [ещё 13 строк...] 74:a1:11:86
Самоподписанные сертификаты обычно содержат только самые базовые данные сертификата, как можно увидеть на примере выше. Для сравнения, сертификаты, выданные публичными удостоверяющими центрами, гораздо интереснее, поскольку они содержат ряд дополнительных полей (добавляемых через механизм расширений X.509). Давайте их бегло рассмотрим.
Расширение Basic Constraints используется для маркировки того, что рассматриваемый сертификат является сертификатом удостоверяющего центра, у которого есть возможность подписи других сертификатов. У сертификатов, которые не являются сертификатами УЦ, это расширение будет либо опущено, либо иметь значение CA, установленное в FALSE
. Это расширение является критичным, что означает, что все программы, использующие в работе сертификаты, должны понимать его значение.
X509v3 Basic Constraints: critical CA:FALSE
Расширения Key Usage (KU) и Extended Key Usage (EKU) ограничивают то, для чего могут быть использованы сертификаты. Если эти расширения присутствуют, то для сертификата разрешены только перечисленные варианты использования. Если эти расширения отсутствуют, значит ограничений на использование не накладывается. В примере ниже приведены типичные варианты использования для сертификата веб-сервера, который, например, нельзя использовать для подписания кода:
X509v3 Key Usage: critical Digital Signature, Key Encipherment X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication
В расширении CRL Distribution Points перечислены адреса, по которым можно найти списки отзыва сертификатов (Certificate Revocation List, CRL) удостоверяющего центра. Эта информация важна в тех случаях, когда сертификаты необходимо отозвать. CRL представляют собой подписанные УЦ списки отозванных сертификатов, регулярно публикуемые через определённые промежутки времени (например, раз в семь дней).
X509v3 CRL Distribution Points: Full Name: URI:http://crl.starfieldtech.com/sfs3-20.crl
Примечание: Возможно вы заметили, что CRL доставляются по незащищённому соединению и задумались, безопасно ли пользоваться такими списками? На самом деле всё в порядке. Поскольку каждый CRL подписывается выпускающим его УЦ, браузеры могут проверить его целостность. Фактически, если бы CRL распространялись через защищённое с помощью TLS соединение, браузеры бы могли столкнуться с проблемой курицы и яйца, пытаясь проверить статус отзыва сертификата, используемого самим сервером, распространяющим CRL!
Расширение Certificate Policies используется для указания политики, в соответствии с которой был выпущен сертификат. Например, именно здесь можно найти индикаторы extended validation (EV) (как в представленном ниже примере). Эти индикаторы представлены в форме уникальных идентификаторов объектов (OID), и они являются уникальными для выпускающего УЦ. Кроме того, это расширение часто содержит один или несколько пунктов Certificate Policy Statement (CPS), которые обычно являются либо веб-страницами, либо документами PDF.
X509v3 Certificate Policies: Policy: 2.16.840.1.114414.1.7.23.3 CPS: http://certificates.starfieldtech.com/repository/
Расширение Authority Information Access (AIA) обычно содержит информацию, состоящую из двух важных частей. Во первых, в нём перечислены адреса серверов-ответчиков Online Certificate Status Protocol (OCSP) удостоверяющего центра, которые могут быть использованы для проверки статуса отзыва сертификата в режиме реального времени. Данное расширение также может содержать ссылку, по которой можно найти сертификат издателя (следующий сертификат в цепочке). В наши дни сертификаты серверов редко подписываются непосредственно доверенными корневыми сертификатами УЦ, и это означает, что администраторы сервера должны включать в свою конфигурацию один или несколько промежуточных сертификатов. Здесь легко допустить ошибку, и тогда сертификат сервера будет признан недействительным. Некоторые клиенты (например, Internet Explorer) будут использовать приведённую в данном расширении информацию для исправления неполных цепочек сертификатов, но так поступают далеко не все клиенты.
Authority Information Access: OCSP - URI:http://ocsp.starfieldtech.com/ CA Issuers - URI:http://certificates.starfieldtech.com/repository/sf_intermediate.crt
Расширения Subject Key Identifier и Authority Key Identifier устанавливают уникальные идентификаторы ключа субъекта и ключа удостоверяющего центра соответственно. Значение, указанное в расширении Authority Key Identifier сертификата, должно совпадать со значением, указанным в расширении Subject Key Identifier того сертификата, которым подписан рассматриваемый сертификат. Эта информация очень полезна в процессе построения пути сертификации, когда клиент пытается найти все возможные пути от конечного сертификата (серверного) до доверенного корневого сертификата. Часто удостоверяющие центры используют один закрытый ключ с более чем одним сертификатом, и это поле позволяет программам надёжно определять, какой сертификат с каким ключом может быть сопоставлен. В реальном мире многие предоставляемые серверами цепочки сертификатов являются некорректными, но это часто остаётся незамеченным, поскольку браузеры способны находить альтернативные пути доверия.
X509v3 Subject Key Identifier: 4A:AB:1C:C3:D3:4E:F7:5B:2B:59:71:AA:20:63:D6:C9:40:FB:14:F1 X509v3 Authority Key Identifier: keyid:49:4B:52:27:D1:1B:BC:F2:A1:21:6A:62:7B:51:42:7A:8A:D7:D5:56
Наконец, расширение Subject Alternative Name используется для перечисления имён хостов, для которых данный сертификат является действительным. Это расширение считается необязательным. Если оно отсутствует, клиенты возвращаются к использованию информации, предоставляемой в атрибуте Common Name (CN), являющемся частью поля Subject. Если это расширение присутствует, то содержимое поля CN в процессе валидации игнорируется.
X509v3 Subject Alternative Name: DNS:www.feistyduck.com, DNS:feistyduck.com
Преобразование ключей и сертификатов
Закрытые ключи и сертификаты могут храниться в различных форматах, а значит вам часто придётся преобразовывать их из одного формата в другой. Наиболее распространённые форматы:
- Бинарный сертификат (DER)
-
Содержит сертификат X.509 в необработанном виде с использованием закодированных в DER структур ASN.1.
- ASCII сертификат (сертификаты) (PEM)
-
Содержит сертификат DER в кодировке base64, перед которым помещается маркер
-----BEGIN CERTIFICATE-----
, а после — маркер-----END CERTIFICATE-----
. Обычно в файле присутствует только один сертификат, хотя некоторые программы, в зависимости от контекста, допускают наличие более одного сертификата в файле. Например, в старых версиях веб-сервера Apache требовалось, чтобы сертификат сервера находился отдельно в одном файле, а все промежуточные сертификаты вместе — в другом файле. - Бинарный ключ (DER)
-
Содержит закрытый ключ в необработанном виде с использованием закодированных в DER структур ASN.1. OpenSSL создаёт ключи в своём собственном традиционном формате (SSLeay). Существует также альтернативный формат, называемый PKCS#8 (определён в RFC 5208), но он не получил широкого распространения. OpenSSL может преобразовывать как в формат PKCS#8, так и из него с помощью команды
pkcs8
. - ASCII ключ (PEM)
-
Содержит ключ DER в кодировке base64, иногда с дополнительными метаданными (например, указанием алгоритма, используемого для парольной защиты).
- Сертификат (сертификаты) PKCS#7
-
Комплексный формат, предназначенный для транспортировки подписанных или зашифрованных данных, определён в RFC 2315. Файлы обычно имеют расширения
.p7b
и.p7c
и, при необходимости, могут включать целиком цепочку сертификатов. Этот формат поддерживается Java-утилитойkeytool
. - Ключ и сертификат (сертификаты) PKCS#12 (PFX)
-
Комплексный формат, в котором может храниться в защищённом состоянии ключ сервера и полная цепочка сертификатов. Файлы обычно имеют расширения
.p12
и.pfx
. Этот формат обычно используется в продуктах Microsoft, но также может использоваться для клиентских сертификатов. В наши дни имя PFX используется как синоним для PKCS#12, хотя раньше (довольно давно) PFX указывал на другой формат (раннюю версию PKCS#12). Вряд ли вы сейчас встретите где-либо старую версию.
Преобразование в PEM и DER
Преобразование сертификата между форматами PEM и DER выполняется с помощью команды x509
. Конвертация сертификата из PEM в DER:
$ openssl x509 -inform PEM -in fd.pem -outform DER -out fd.der
Конвертация сертификата из DER в PEM:
$ openssl x509 -inform DER -in fd.der -outform PEM -out fd.pem
Аналогичный синтаксис применяется для преобразования закрытых ключей между форматами DER и PEM, но в этом случае используются другие команды: rsa
для ключей RSA, и dsa
для ключей DSA.
Преобразование PKCS#12 (PFX)
Всего лишь одной команды достаточно для преобразования ключа и сертификатов, представленных в формате PEM, в PKCS#12. В следующем примере ключ (fd.key
), сертификат (fd.crt
) и промежуточные сертификаты (fd-chain.crt
) конвертируются в один эквивалентный файл PKCS#12:
$ openssl pkcs12 -export -name "My Certificate" -out fd.p12 -inkey fd.key -in fd.crt -certfile fd-chain.crt Enter Export Password: **************** Verifying - Enter Export Password: ****************
С обратным преобразованием не всё так просто. Можно использовать одну команду, но в этом случае вы получите всё содержимое в одном файле:
$ openssl pkcs12 -in fd.p12 -out fd.pem -nodes
Теперь вам нужно открыть полученный файл fd.pem
в вашем любимом редакторе и вручную разделить на отдельные файлы с ключом, сертификатом и промежуточными сертификатами. При этом вы заметите дополнительный контент перед каждым компонентом. Например:
Bag Attributes localKeyID: E3 11 E4 F1 2C ED 11 66 41 1B B8 83 35 D2 DD 07 FC DE 28 76 subject=/1.3.6.1.4.1.311.60.2.1.3=GB/2.5.4.15=Private Organization/serialNumber=06694169↩ /C=GB/ST=London/L=London/O=Feisty Duck Ltd/CN=www.feistyduck.com issuer=/C=US/ST=Arizona/L=Scottsdale/O=Starfield Technologies, Inc./OU=http:/↩ /certificates.starfieldtech.com/repository/CN=Starfield Secure Certification Authority -----BEGIN CERTIFICATE----- MIIF5zCCBM+gAwIBAgIHBG9JXlv9vTANBgkqhkiG9w0BAQUFADCB3DELMAkGA1UE BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAj [...]
Эти дополнительные метаданные очень удобны для быстрой идентификации сертификатов. Очевидно, вы должны убедиться, что основной файл сертификата содержит конечный сертификат сервера, а не что-то ещё. Кроме того, вы также должны убедиться, что промежуточные сертификаты представлены в правильном порядке, когда сертификат, с помощью которого производилось подписание, следует за подписанным сертификатом. Если вы заметите самоподписанный корневой сертификат, можете смело его удалить или сохранить в другом месте; он не должен входить в цепочку сертификатов.
Предупреждение: Конечный результат преобразования не должен содержать ничего, кроме закодированных ключа и сертификатов. Хотя некоторые инструменты достаточно умны, чтобы проигнорировать то, что не требуется, рассчитывать на это нельзя. Оставляя лишнюю информацию в файлах PEM, вы рискуете столкнуться со сложнодиагностируемыми проблемами.
Разделение пакета на компоненты можно переложить и на OpenSSL, но при этом придётся несколько раз вызывать команду pkcs12
(и каждый раз вводить пароль к пакету):
$ openssl pkcs12 -in fd.p12 -nocerts -out fd.key -nodes $ openssl pkcs12 -in fd.p12 -nokeys -clcerts -out fd.crt $ openssl pkcs12 -in fd.p12 -nokeys -cacerts -out fd-chain.crt
К сожалению, такой подход не приведёт к существенной экономии времени. Вам по-прежнему придётся проверять каждый файл, чтобы убедиться, что в нём находится именно то, что нужно, а также удалить метаданные.
Преобразование PKCS#7
Для преобразования из PEM в PKCS#7 используйте команду crl2pkcs7
:
$ openssl crl2pkcs7 -nocrl -out fd.p7b -certfile fd.crt -certfile fd-chain.crt
Для преобразования из PKCS#7 в PEM используйте команду pkcs7
с параметром -print_certs
:
openssl pkcs7 -in fd.p7b -print_certs -out fd.pem
Как и в случае с преобразованием из PKCS#12, нужно будет отредактировать файл fd.pem
, очистив его и разделив на желаемые компоненты.
Конфигурация
В этом разделе мы обсудим две темы, относящиеся к развертыванию TLS. Первая — конфигурация наборов алгоритмов шифрования или наборов шифров, в которой вы указываете, какие именно из множества доступных в TLS наборов вы хотите использовать в процессе коммуникации. Эта тема важна, поскольку практически каждая программа, использующая OpenSSL, применяет её механизм конфигурации наборов. Это означает, что изучив однажды, каким образом настраиваются наборы шифров для одной программы, вы сможете повторно использовать эти знания где угодно. Вторая тема — измерение производительности низкоуровневых криптографических операций.
Выбор набора шифров
Распространённая задача в конфигурации сервера TLS — выбор того, какие наборы шифров будут поддерживаться. Для безопасной коммуникации программному обеспечению TLS необходимо определиться, какие именно криптографические примитивы использовать для достижения своих целей (например, обеспечения конфиденциальности). Это достигается путём выбора подходящего набора шифров, на основании которого принимается ряд решений о том, как будут выполняться аутентификация, обмен ключами, шифрование и другие операции. Программы, использующие в своей работе OpenSSL, обычно применяют тот же подход к настройке наборов шифров, что и OpenSSL, просто задавая те же параметры конфигурации. Например, в настройках сервера httpd
от Apache конфигурация наборов шифров может выглядеть так:
SSLHonorCipherOrder On SSLCipherSuite "HIGH:!aNULL:@STRENGTH"
Параметр конфигурации в первой строке управляет приоритезацией наборов шифров (а также настраивает httpd
на активный выбор наборов). Параметр конфигурации во второй строке управляет тем, какие наборы будут поддерживаться.
Создание хорошей конфигурации наборов может занять довольно много времени, при этом нужно учитывать множество деталей. Лучшим подходом в данном случае будет использование команды OpenSSL ciphers
для определения того, какие именно наборы будут задействованы при выборе конкретной строки конфигурации.
Получение списка поддерживаемых наборов
Перед тем как продолжать, вам следует определиться с тем, какие наборы поддерживаются вашей инсталляцией OpenSSL. Для этого вызовите команду ciphers
с параметром -v
и указанием ключевых слов ALL:COMPLEMENTOFALL
(очевидно, ALL
в данном случае вовсе на означает «все»):
$ openssl ciphers -v 'ALL:COMPLEMENTOFALL' ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA384 ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA384 ECDHE-RSA-AES256-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA1 [ещё 106 строк...]
Совет: При использовании OpenSSL 1.0.0 или более поздней версии, вы также можете применить параметр -V
(в верхнем регистре), чтобы сделать вывод ещё подробнее. В этом режиме в вывод попадут также идентификаторы наборов, которые в любом случае полезно иметь под рукой. Например, OpenSSL не всегда использует для наборов шифров имена из RFC; в таких случаях вы должны использовать эти идентификаторы для обеспечения перекрёстной проверки.
В моём случае в вывод попали 111 наборов. Каждая строка содержит информацию об одном наборе в виде следующих полей:
-
Имя набора
-
Минимально допустимая версия протокола
-
Алгоритм обмена ключами
-
Алгоритм аутентификации
-
Алгоритм и стойкость шифрования
-
Алгоритм MAC (обеспечения целостности)
-
Индикатор экспортного набора
Если изменить параметр ciphers
на что-то отличное от ALL:COMPLEMENTOFALL
, OpenSSL покажет только те наборы, которые будут соответствовать указанной настройке. Например, вы можете запросить вывод только тех наборов шифров, которые основаны на RC4, следующей командой:
$ openssl ciphers -v 'RC4' ECDHE-RSA-RC4-SHA SSLv3 Kx=ECDH Au=RSA Enc=RC4(128) Mac=SHA1 ECDHE-ECDSA-RC4-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=RC4(128) Mac=SHA1 AECDH-RC4-SHA SSLv3 Kx=ECDH Au=None Enc=RC4(128) Mac=SHA1 ADH-RC4-MD5 SSLv3 Kx=DH Au=None Enc=RC4(128) Mac=MD5 ECDH-RSA-RC4-SHA SSLv3 Kx=ECDH/RSA Au=ECDH Enc=RC4(128) Mac=SHA1 ECDH-ECDSA-RC4-SHA SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=RC4(128) Mac=SHA1 RC4-SHA SSLv3 Kx=RSA Au=RSA Enc=RC4(128) Mac=SHA1 RC4-MD5 SSLv3 Kx=RSA Au=RSA Enc=RC4(128) Mac=MD5 PSK-RC4-SHA SSLv3 Kx=PSK Au=PSK Enc=RC4(128) Mac=SHA1 EXP-ADH-RC4-MD5 SSLv3 Kx=DH(512) Au=None Enc=RC4(40) Mac=MD5 export EXP-RC4-MD5 SSLv3 Kx=RSA(512) Au=RSA Enc=RC4(40) Mac=MD5 export
В выводе будут содержаться все наборы, соответствующие заданному вами ограничению, даже если они небезопасны. Очевидно, что при настройке того или иного приложения вы должны тщательно выбирать строки конфигурации, чтобы активировать только то, что безопасно. Кроме того, порядок, в котором наборы появляются в выходных данных, имеет значение. Когда вы настраиваете свой TLS-сервер на активный выбор того набора шифров, который будет использоваться при соединении (что является лучшей практикой и рекомендуемым методом), приоритет будут иметь перечисленные вначале наборы шифров.
Ключевые слова
Ключевые слова набора шифров являются базовыми строительными блоками конфигурации наборов шифров. Каждое имя набора (например, RC4-SHA
) является ключевым словом, с помощью которого выбирается ровно один набор. Все остальные ключевые слова отбирают группу наборов в соответствии с некоторыми критериями. Имена ключевых слов чувствительны к регистру символов. Конечно, можно было бы просто перенаправить вас на документацию OpenSSL для просмотра всего списка ключевых слов, но оказывается, что раздел по шифрам в ней не актуален: в нём не хватает нескольких последних добавлений. По этой причине я попытался задокументировать все ключевые слова в этом разделе.
Групповые ключевые слова — это сокращения для выбора часто используемых наборов шифров. Например, при наличии ключевого слова HIGH
будут отобраны только очень стойкие наборы шифров.
Таблица 1.1. Групповые ключевые слова
Ключевое слово | Значение |
---|---|
DEFAULT |
Список шифров по умолчанию. Определяется во время компиляции, для OpenSSL 1.0.0, как правило, ALL:!aNULL:!eNULL . При настройке отбора наборов шифров в приложении это ключевое слово должно быть указано первым в конфигурационной строке. |
COMPLEMENTOFDEFAULT |
Шифры, входящие в ALL , но не задействованные по умолчанию. В настоящий момент это ADH . Обратите внимание, что это правило не распространяется на шифры eNULL , которые не входят в ALL (если это необходимо, используйте COMPLEMENTOFALL ). |
ALL |
Все наборы шифров, кроме шифров eNULL , которые должны быть включены явно. |
COMPLEMENTOFALL |
Наборы шифров, не включённые в ALL , в настоящий момент это eNULL . |
HIGH |
Наборы шифров «высокой» криптографической стойкости. В настоящий момент это означает наборы шифров с ключами, имеющими уровень криптостойкости более 128 бит, а также некоторые наборы шифров с уровнем криптостойкости в 128 бит. |
MEDIUM |
Наборы шифров «средней» криптографической стойкости, в настоящий момент некоторые из них используют шифрование с уровнем криптостойкости 128 бит. |
LOW |
Наборы шифров «низкой» криптографической стойкости. В настоящее время это те из них, в которых используются криптографические алгоритмы с уровнем криптостойкости 64 или 56 бит, за исключением экспортных наборов шифров. Небезопасные. |
EXP, EXPORT |
Экспортные криптографические алгоритмы. Включая алгоритмы с уровнем криптостойкости 40 и 56 бит. Небезопасные. |
EXPORT40 |
Экспортные алгоритмы с уровнем криптостойкости 40 бит. Небезопасные. |
EXPORT56 |
Экспортные алгоритмы с уровнем криптостойкости 56 бит. Небезопасные. |
TLSv1, SSLv3, SSLv2 |
Наборы шифров TLS 1.0, SSL 3 и SSL 2, соответственно. |
С помощью ключевых слов алгоритмов хэширования выбираются наборы, использующие конкретный алгоритм хэширования. Например, MD5
отбирает все наборы, которые для проверки целостности полагаются на MD5.
Таблица 1.2. Ключевые слова алгоритмов хэширования
Ключевое слово | Значение |
---|---|
MD5 |
Наборы шифров, использующие MD5. Устаревшие и небезопасные. |
SHA , SHA1 |
Наборы шифров, использующие SHA1. |
SHA256 (v1.0.0+) |
Наборы шифров, использующие SHA256. |
SHA384 (v1.0.0+) |
Наборы шифров, использующие SHA384. |
Примечание: С помощью ключевых слов алгоритмов хэширования выбираются только те наборы шифров, которые проверяют целостность данных на уровне протокола. В TLS 1.2 появилась поддержка аутентифицированного шифрования, представляющего собой механизм, который связывает шифрование с проверкой целостности. При использовании так называемых наборов AEAD (Authenticated Encryption with Associated Data), протоколу не требуется обеспечивать дополнительную проверку целостности. По этой причине вы не сможете использовать ключевые слова алгоритмов хэширования для выбора наборов AEAD (в настоящее время это наборы, в названии которых присутствует GCM). В названиях таких наборов используются суффиксы SHA256
и SHA384
, но в данном случае они указывают на хэш-функции, используемые для построения используемой с набором псевдослучайной функции (что вносит некоторую путаницу).
С помощью ключевых слов аутентификации наборы выбираются на основании тех методов аутентификации, которые они используют. Сегодня для аутентификации практически во всех публичных сертификатах используется RSA. Со временем мы, вероятно, увидим очень медленный прирост использования сертификатов Elliptic Curve (ECDSA).
Табица 1.3. Ключевые слова аутентификации
Ключевое слово | Значение |
---|---|
aDH |
Наборы шифров, фактически использующие аутентификацию DH, то есть сертификаты содержат ключи DH. (v1.0.2+) |
aDSS , DSS |
Наборы шифров, использующие аутентификацию DSS, то есть сертификаты содержат ключи DSS. |
aECDH (v1.0.0+) |
Наборы шифров, использующие аутентификацию ECDH. |
aECDSA (v1.0.0+) |
Наборы шифров, использующие аутентификацию ECDSA. |
aNULL |
Наборы шифров, не предлагающие аутентификацию. В настоящее время это анонимные алгоритмы DH. Небезопасные. |
aRSA |
Наборы шифров, использующие аутентификацию RSA, то есть сертификаты содержат ключи RSA. |
PSK |
Наборы шифров, использующие аутентификацию PSK (Pre-Shared Key). |
SRP |
Наборы шифров, использующие аутентификацию SRP (Secure Remote Password). |
С помощью ключевых слов обмена ключами наборы выбираются на основании алгоритма обмена ключами. Когда речь заходит о наборах с эфемерным обменом по протоколу Диффи-Хеллмана, разработчики OpenSSL непоследовательны в именовании наборов и ключевых слов. В названиях наборов эфемерные алгоритмы обмена ключами, как правило обозначаются буквой E
на конце названия алгоритма (например, ECDHE-RSA-RC4-SHA
и DHE-RSA-AES256-SHA
), а в ключевых словах отбора буква E
указывается в начале (например, EECDH
и EDH
). Чтобы усугубить ситуацию, в некоторых старых наборах шифров буква E
ставится в начале названия алгоритма обмена ключами (например, EDH-RSA-DES-CBC-SHA
).
Таблица 1.4. Ключевые слова обмена ключами
Ключевое слово | Значение |
---|---|
ADH |
Наборы шифров с анонимным обменом DH. Небезопасные. |
AECDH (v1.0.0+) |
Наборы шифров с анонимным обменом ECDH. Небезопасные. |
DH |
Наборы шифров, использующие обмен DH (в том числе эфемерный и анонимный обмен DH). |
ECDH (v1.0.0+) |
Наборы шифров, использующие обмен ECDH (в том числе эфемерный и анонимный обмен ECDH). |
EDH (v1.0.0+) |
Наборы шифров, использующие эфемерное согласование ключей DH. |
EECDH (v1.0.0+) |
Наборы шифров, использующие эфемерный обмен ECDH. |
kECDH (v1.0.0+) |
Наборы шифров, использующие эфемерное согласование ключей ECDH. |
kEDH |
Наборы шифров, использующие эфемерное согласование ключей DH (включая анонимный обмен DH). |
kEECDH (v1.0.0+) |
Наборы шифров, использующие эфемерное согласование ключей ECDH (включая анонимный обмен ECDH). |
kRSA , RSA |
Наборы шифров, использующие алгоритм обмена ключами RSA. |
С помощью ключевых слов шифров наборы выбираются на основании используемых ими шифров.
Таблица 1.5. Ключевые слова шифров
Ключевое слово | Значение |
---|---|
3DES |
Наборы шифров, использующие Triple DES. Устаревшие и небезопасные. |
AES |
Наборы шифров, использующие AES. |
AESGCM (v1.0.0+) |
Наборы шифров, использующие AES GCM. |
CAMELLIA |
Наборы шифров, использующие Camellia. Устаревшие. |
DES |
Наборы шифров, использующие Single DES. Устаревшие и небезопасные. |
eNULL , NULL |
Наборы шифров не использующие шифрование. Небезопасные. |
IDEA |
Наборы шифров, использующие IDEA. Устаревшие. |
RC2 |
Наборы шифров, использующие RC2. Устаревшие и небезопасные. |
RC4 |
Наборы шифров, использующие RC4. Небезопасные. |
SEED |
Наборы шифров, использующие SEED. Устаревшие. |
Остаётся ряд наборов, которые не вписываются ни в одну из рассмотренных ранее категорий. Основная их часть связана со стандартами ГОСТ, которые актуальны для стран, входящих в Содружество Независимых Государств, образовавшееся после распада Советского Союза.
Таблица 1.6. Прочие ключевые слова
Ключевое слово | Значение |
---|---|
@STRENGTH |
Сортирует текущий список наборов шифров в порядке длины ключа алгоритма шифрования.. |
aGOST |
Наборы шифров, использующие аутентификацию GOST R 34.10 (как 2001, так и 94). Для работы требуется модуль обеспечения совместимости с ГОСТ. |
aGOST01 |
Наборы шифров, использующие аутентификацию GOST R 34.10-2001. |
aGOST94 |
Наборы шифров, использующие аутентификацию GOST R 34.10-94. Устаревшие. Вместо них используйте GOST R 34.10-2001. |
kGOST |
Наборы шифров, использующие обмен ключами VKO 34.10, определённый в RFC 4357. |
GOST94 |
Наборы шифров, использующие HMAC, основанный на GOST R 34.11-94. |
GOST89MAC |
Наборы шифров, использующие GOST 28147-89 MAC вместо HMAC. |
Комбинирование ключевых слов
Чаще всего вы будете использовать ключевые слова по отдельности, но также возможно комбинировать их, чтобы отбирать только те наборы, которые удовлетворяют сразу нескольким требованиям. Это делается путём соединения двух или более ключевых слов символом +
. В следующем примере мы выбираем наборы, использующие RC4 и SHA:
$ openssl ciphers -v 'RC4+SHA' ECDHE-RSA-RC4-SHA SSLv3 Kx=ECDH Au=RSA Enc=RC4(128) Mac=SHA1 ECDHE-ECDSA-RC4-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=RC4(128) Mac=SHA1 AECDH-RC4-SHA SSLv3 Kx=ECDH Au=None Enc=RC4(128) Mac=SHA1 ECDH-RSA-RC4-SHA SSLv3 Kx=ECDH/RSA Au=ECDH Enc=RC4(128) Mac=SHA1 ECDH-ECDSA-RC4-SHA SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=RC4(128) Mac=SHA1 RC4-SHA SSLv3 Kx=RSA Au=RSA Enc=RC4(128) Mac=SHA1 PSK-RC4-SHA SSLv3 Kx=PSK Au=PSK Enc=RC4(128) Mac=SHA1
Построение списков наборов шифров
Ключевой концепцией при построении конфигурации наборов шифров является концепция текущего списка наборов. Первоначально этот список всегда пуст, в нём нет ни одного набора шифров, но каждое ключевое слово, добавляемое вами в строку конфигурации, тем или иным способом меняет этот список. По умолчанию новые наборы добавляются в конец списка. Например, чтобы выбрать все наборы, использующие шифрование RC4 и AES, применяется такая строка конфигурации:
$ openssl ciphers -v 'RC4:AES'
Обычно для разделения ключевых слов используется символ двоеточия, но также приемлемы пробелы и запятые. Следующая команда производит тот же вывод, что и в предыдущем примере:
$ openssl ciphers -v 'RC4 AES'
Модификаторы ключевых слов
Модификаторы ключевых слов — это символы, которые можно поместить перед ключевым словом для того, чтобы изменить действие по умолчанию (добавление в список) на что-то другое. Поддерживаются следующие действия:
- Добавление в конец
-
Добавляет наборы в конец списка. Если какие-то из этих наборов уже были в текущем списке, они останутся на своей нынешней позиции. Это действие по умолчанию, выполняемое, когда перед ключевым словом нет модификатора.
- Удаление (
-
) -
Удаляет все соответствующие наборы из текущего списка. Потенциально позволяет некоторым другим ключевым словам повторно ввести эти наборы позже.
- Удаление навсегда (
!
) -
Удаляет все соответствующие наборы из текущего списка и предотвращает дальнейшее их добавление в помощью других ключевых слов. Этот модификатор полезен для указания тех наборов, которые вы не хотите использовать ни при каких обстоятельствах; тем самым упрощается дальнейший отбор и предотвращаются ошибки.
- Перемещение в конец (
+
) -
Перемещает все соответствующие наборы в конец текущего списка. Работает только для тех наборов, которые уже в списке; новые наборы в список не добавляются. Этот модификатор полезен, если вы хотите, чтобы некоторые более слабые наборы были включены, но отдаёте предпочтение более сильным. Например, строка
RC4:+MD5
включает все наборы RC4, но помещает те из них, которые основаны на MD5, в конец списка.
Сортировка
Ключевое слово @STRENGTH
отличается от других ключевых слов (не зря же в его названии есть символ @
): оно не добавляет и не удаляет никаких наборов, но сортирует их в порядке уменьшения стойкости шифра. Автоматическая сортировка — интересная идея, но она имеет смысл только в идеальном мире, в котором наборы шифров можно было бы сопоставить лишь по формальному уровню криптостойкости шифра.
Возьмём для примера следующую конфигурацию наборов шифров:
$ openssl ciphers -v 'DES-CBC-SHA DES-CBC3-SHA RC4-SHA AES256-SHA @STRENGTH' AES256-SHA SSLv3 Kx=RSA Au=RSA Enc=AES(256) Mac=SHA1 DES-CBC3-SHA SSLv3 Kx=RSA Au=RSA Enc=3DES(168) Mac=SHA1 RC4-SHA SSLv3 Kx=RSA Au=RSA Enc=RC4(128) Mac=SHA1 DES-CBC-SHA SSLv3 Kx=RSA Au=RSA Enc=DES(56) Mac=SHA1
В теории вывод команды отсортирован в порядке стойкости шифров. На практике вам, скорее всего, захочется более детально контролировать этот порядок:
-
Например,
AES256-SHA
(набор CBC) уязвим для атак BEAST при использовании с протоколом TLS 1.0 и более ранними версиями. Если вы хотите уменьшить вероятность атаки BEAST на стороне сервера, вы предпочтёте отдать приоритет пакету RC4-SHA, который не подвержен этой проблеме. -
Уровень криптостойкости 3DES только номинально оценивается в 168 бит; так называемая атака встреча посередине (meet-in-the-middle) уменьшает его стойкость до 112 бит9, а дальнейшие оптимизации подбора и вовсе снижают стойкость до 108 бит10. Этот факт делает
DES-CBC3-SHA
хуже 128-битных наборов шифров. Строго говоря, трактовка 3DES как 168-битного шифра — это баг в OpenSSL, который был исправлен в более поздних версиях.
Обработка ошибок
При работе со своей конфигурацией вы можете столкнуться с двумя типами ошибок. Одни из них возникают в результате опечатки или попытки использовать несуществующее ключевое слово:
$ openssl ciphers -v '@HIGH' Error in cipher list 140460843755168:error:140E6118:SSL routines:SSL_CIPHER_PROCESS_RULESTR:invalid ↩ command:ssl_ciph.c:1317:
Вывод, конечно, загадочный, но в нём содержится сообщение об ошибке.
Другая возможная ошибка состоит в том, что вы получите пустой список наборов шифров. В этом случае вывод будет примерно такой:
$ openssl ciphers -v 'SHA512' Error in cipher list 140202299557536:error:1410D0B9:SSL routines:SSL_CTX_set_cipher_list:no cipher match:ssl↩ _lib.c:1312:
Собираем всё вместе
Для демонстрации того, как объединяются различные функции конфигурации наборов шифров, рассмотрим один законченный пример реального использования. Но не забывайте о том, что это всего лишь пример. Поскольку при выборе реальной конфигурации обычно необходимо учитывать множество аспектов, не существует такого понятия, как единственно возможная идеальная конфигурация.
По этой причине, прежде чем вы приступите к работе над своей конфигурацией, у вас должно быть чёткое представление о том, чего вы хотите достичь. В рассматриваемом случае я хотел получить достаточно безопасную и эффективную конфигурацию, которую можно определить следующим образом:
-
Используются только стойкие шифры с фактическим уровнем криптостойкости 128 бит и выше (это исключает 3DES).
-
Используются только наборы, обеспечивающие строгую аутентификацию (это исключает анонимные и экспортные наборы).
-
Не используются любые наборы, полагающиеся на уязвимые исходные алгоритмы (например, MD5).
-
Реализуется надежная поддержка прямой секретности, независимо от того, какие ключи и протоколы применяются. С этим требованием связано небольшое снижение производительности, потому что не будет возможности использовать быстрый обмен ключами RSA. Чтобы минимизировать это снижение, мы будем отдавать приоритет ECDHE, которые значительно быстрее, чем DHE.
-
Предпочтение отдаётся ECDSA над RSA. Это требование имеет смысл только при использовании в системе двух вариантов шифрования. То есть мы хотим использовать более быстрые операции ECDSA там, где это только возможно, но откатываться на RSA при взаимодействии с клиентами, которые ещё не поддерживают ECDSA.
-
При работе с клиентами TLS 1.2 предпочтение отдаётся наборам AES GCM, обеспечивающим наилучший уровень безопасности, который только может предложить TLS.
-
Поскольку недавно выяснилось, что шифры RC4 слабее, чем это считалось ранее11, поместим их в конец нашего списка. Это почти также эффективно, как и полное их отключение. Хотя BEAST всё ещё может быть проблемой в некоторых ситуациях, предполагается, что о минимизации этой атаки позаботились на стороне клиента.
Обычно лучший подход — начать с полного удаления всех компонентов и наборов, которые вы не хотите использовать; это уменьшает беспорядок и гарантирует, что нежелательные наборы не будут случайно добавлены в конфигурацию по ошибке.
Слабые наборы могут быть идентифицированы следующими ключевыми словами:
-
aNULL
; без аутентификации -
eNULL
; без шифрования -
LOW
; наборы с низкой стойкостью -
3DES
; фактическая стойкость — 108 бит -
MD5
; наборы, использующие MD5 -
EXP
; устаревшие экспортные наборы
Для уменьшения количества выводимых наборов я собираюсь полностью устранить все наборы DSA, PSK, SRP и ECDH, поскольку они используются крайне редко. Также я удалю шифры IDEA и SEED, которые устарели, но все еще могут поддерживаться OpenSSL. В своей конфигурации я также не буду использовать CAMELLIA, потому что он медленнее и не так хорошо поддерживается, как AES (например, на практике нет вариантов GCM или ECDHE).
!aNULL !eNULL !LOW !3DES !MD5 !EXP !DSS !PSK !SRP !kECDH !CAMELLIA !IDEA !SEED
Теперь мы можем сосредоточиться на том, чего хотим достичь. Поскольку нашим приоритетом является прямая секретность, мы можем начать с ключевых слов kEECDH
и kEDH
:
kEECDH kEDH !aNULL !eNULL !LOW !3DES !MD5 !EXP !DSS !PSK !SRP !kECDH !CAMELLIA !IDEA ↩ !SEED
Если протестировать эту конфигурацию, обнаружится, что наборы RSA перечислены первыми, хотя мы хотели бы видеть первыми ECDSA:
ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA384 ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA384 ECDHE-RSA-AES256-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA1 ECDHE-ECDSA-AES256-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA1 ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(128) Mac=AEAD [...]
Чтобы это исправить, поместим kEECDH+ECDSA
в начало конфигурации:
kEECDH+ECDSA kEECDH kEDH !aNULL !eNULL !LOW !3DES !MD5 !EXP !DSS !PSK !SRP !kECDH ↩ !CAMELLIA !IDEA !SEED
Следующая проблема — то, что более старые наборы (SSL 3) перемешаны с более новыми (TLS 1.2). Для обеспечения максимальной безопасности хотелось бы, чтобы клиенты, поддерживающие TLS 1.2, всегда согласовывали именно TLS 1.2. Чтобы переместить более старые наборы в конец списка, я использую ключевое слово +SHA
(наборы TLS 1.2 всегда используют либо SHA256, либо SHA384, то есть под это условие они не попадут):
kEECDH+ECDSA kEECDH kEDH +SHA !aNULL !eNULL !LOW !3DES !MD5 !EXP !DSS !PSK !SRP !kECDH ↩ !CAMELLIA !IDEA !SEED
В таком виде конфигурация практически полностью отвечает нашим требованиям. Осталось поместить оставшиеся ещё неохваченными безопасные наборы в конец списка; сделаем это с помощью ключевого слова HIGH
. Кроме того, нужно удостовериться, что наборы RC4 являются последними; с помощью ключевого слова +RC4
мы переместим уже существующие наборы RC4 в конец списка, а с помощью ключевого слова RC4
добавим туда же ещё незадействованные наборы RC4:
kEECDH+ECDSA kEECDH kEDH HIGH +SHA +RC4 RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !DSS ↩ !PSK !SRP !kECDH !CAMELLIA !IDEA !SEED
Давайте рассмотрим окончательный результат, который состоит из 28 наборов. В первой группе у нас наборы TLS 1.2:
ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA384 ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(128) Mac=AEAD ECDHE-ECDSA-AES128-SHA256 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA256 ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA384 ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(128) Mac=AEAD ECDHE-RSA-AES128-SHA256 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(128) Mac=SHA256 DHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(256) Mac=AEAD DHE-RSA-AES256-SHA256 TLSv1.2 Kx=DH Au=RSA Enc=AES(256) Mac=SHA256 DHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(128) Mac=AEAD DHE-RSA-AES128-SHA256 TLSv1.2 Kx=DH Au=RSA Enc=AES(128) Mac=SHA256 AES256-GCM-SHA384 TLSv1.2 Kx=RSA Au=RSA Enc=AESGCM(256) Mac=AEAD AES256-SHA256 TLSv1.2 Kx=RSA Au=RSA Enc=AES(256) Mac=SHA256 AES128-GCM-SHA256 TLSv1.2 Kx=RSA Au=RSA Enc=AESGCM(128) Mac=AEAD AES128-SHA256 TLSv1.2 Kx=RSA Au=RSA Enc=AES(128) Mac=SHA256
Сначала идут наборы ECDHE, затем — DHE, а за ними уже все остальные наборы TLS 1.2. В каждой из подгрупп приоритет имеют ECDSA и GCM.
Во второй группе представлены наборы, которые будут использоваться клиентами TLS 1.0. Приоритеты здесь такие же, как и в первой группе:
ECDHE-ECDSA-AES256-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA1 ECDHE-ECDSA-AES128-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA1 ECDHE-RSA-AES256-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA1 ECDHE-RSA-AES128-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(128) Mac=SHA1 DHE-RSA-AES256-SHA SSLv3 Kx=DH Au=RSA Enc=AES(256) Mac=SHA1 DHE-RSA-AES128-SHA SSLv3 Kx=DH Au=RSA Enc=AES(128) Mac=SHA1 DHE-RSA-SEED-SHA SSLv3 Kx=DH Au=RSA Enc=SEED(128 ) Mac=SHA1 AES256-SHA SSLv3 Kx=RSA Au=RSA Enc=AES(256) Mac=SHA1 AES128-SHA SSLv3 Kx=RSA Au=RSA Enc=AES(128) Mac=SHA1
И наконец, наборы RC4 представлены в конце списка:
ECDHE-ECDSA-RC4-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=RC4(128) Mac=SHA1 ECDHE-RSA-RC4-SHA SSLv3 Kx=ECDH Au=RSA Enc=RC4(128) Mac=SHA1 RC4-SHA SSLv3 Kx=RSA Au=RSA Enc=RC4(128) Mac=SHA1
Рекомендуемая конфигурация
В предыдущем разделе мы разработали конфигурацию-пример для того чтобы показать, как конфигурации собираются с помощью ключевых слов наборов шифров OpenSSL. Но всё-таки она получилась не самой лучшей из всех возможных. На самом деле, нет ни одной конфигурации, которая удовлетворила бы всех. В этом разделе мы рассмотрим несколько конфигураций, из которых можно будет выбрать ту, которая вам больше подойдёт, исходя из ваших предпочтений и оценки рисков.
Принципы проектирования для всех конфигураций здесь, в основном, те же, что и в предыдущем разделе, но я собираюсь сделать пару изменений для достижения лучшей производительности. Во-первых, я собираюсь поместить наборы, шифры которых имеют уровень криптостойкости 128 бит, в начало списка. Хотя 256-битные наборы обеспечивают некоторое повышение безопасности, для большинства сайтов оно не имеет смысла и сопровождается снижением производительности. Во-вторых, я собираюсь отдать предпочтение наборам с HMAC-SHA, а не с HMAC-SHA256 и HMAC-SHA384, которые гораздо медленнее и также не обеспечивают значительного повышения безопасности.
Кроме того, я собираюсь поменять подход к конфигурированию наборов, отказавшись от использования ключевых слов в пользу непосредственно имён наборов. Концептуально, использование ключевых слов — неплохая идея: вы определяете свои требования безопасности, а библиотека делает всё остальное, и вам не приходится вдаваться в подробности о тех наборах, которые в итоге будут использоваться. К сожалению, на практике такой подход уже неэффективен, поскольку мы стали довольно разборчивы в том, какие наборы хотим включить и в каком порядке.
Использовать имена наборов в конфигурации также просто: вы просто перечисляете наборы, которые хотите применять. И когда вы будете просматривать чью-либо конфигурацию, вам сразу станет понятно, какие именно наборы используются, нет необходимости пропускать настройки через OpenSSL.
Вот моя стартовая конфигурация по умолчанию, спроектированная для обеспечения высокого уровня безопасности и хорошей производительности:
ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES128-SHA ECDHE-ECDSA-AES256-SHA ECDHE-ECDSA-AES128-SHA256 ECDHE-ECDSA-AES256-SHA384 ECDHE-RSA-AES128-GCM-SHA256 ECDHE-RSA-AES256-GCM-SHA384 ECDHE-RSA-AES128-SHA ECDHE-RSA-AES256-SHA ECDHE-RSA-AES128-SHA256 ECDHE-RSA-AES256-SHA384 DHE-RSA-AES128-GCM-SHA256 DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES128-SHA DHE-RSA-AES256-SHA DHE-RSA-AES128-SHA256 DHE-RSA-AES256-SHA256
Примечание: Начиная с ветки 1.1.x, OpenSSL поддерживает наборы ChaCha20/Poly130512. Эти наборы с проверкой аутентификации (например, ECDHE-ECDSA-CHACHA20-POLY1305
и ECDHE-RSA-CHACHA20-POLY1305
) обеспечивают высокий уровень безопасности и альтернативу наборам AES. Сообщается, что они обеспечивают более высокую производительность для пользователей мобильных устройств, но наборы AES GCM всё ещё работают быстрее на современных настольных компьютерах, где доступно аппаратное ускорение. Поместите их в начало списка или сразу за вашими наборами GCM, в зависимости от того, какая часть вашей аудитории использует мобильные устройства. Во время написания этого материала OpenSSL ещё не поддерживал одинаковый уровень предпочтения наборов (в отличие, например, от BoringSSL), что позволяло бы клиенту самому выбрать между наборами AES-GCM и ChaCha20.
В этой конфигурации используются только наборы с поддержкой прямой секретности и обеспечением стойкого шифрования. Большинство современных браузеров и других клиентов смогут установить соединение, но некоторые очень старые клиенты, возможно, нет. Например, старые версии Internet Explorer, работающие на Windows XP, будут выдавать ошибку.
Если вам действительна нужна поддержка очень старых клиентов (и только в этом случае), рассмотрите вариант добавления в конец списка следующих наборов шифров:
EDH-RSA-DES-CBC3-SHA AES128-SHA AES256-SHA DES-CBC3-SHA ECDHE-RSA-RC4-SHA RC4-SHA
Большинство из этих старых наборов используют обмен ключами RSA, а значит не обеспечивают прямую секретность. Предпочтение отдаётся шифрам AES, но 3DES и (небезопасные) RC4 также поддерживаются для максимальной совместимости с как можно большим числом клиентов. Если нельзя обойтись без использования RC4, предпочтение должно отдаваться наборам с ECDHE, обеспечивающим прямую секретность.
Производительность
Как вы, скорее всего, знаете, скорость вычислений является существенным ограничивающим фактором для любой криптографической операции. В OpenSSL есть встроенный инструмент тестирования производительности, который вы можете использовать для получения представления о возможностях и ограничениях системы. Запустить тестирование можно с помощью команды speed
.
Если выполнить команду speed
без параметров, OpenSSL сгенерирует большое количество выводных данных, но полезного в них будет немного. Лучше тестировать только те алгоритмы, которые вас непосредственно интересуют. Например, для защиты веб-сервера вам могут понадобиться алгоритмы RC4, AES, RSA, ECDH и SHA:
$ openssl speed rc4 aes rsa ecdh sha
Вывод команды состоит из трёх частей. В первой части показан номер версии OpenSSL и параметры компиляции, с которым был собран этот экземпляр OpenSSL. Эта информация полезна, если вы тестируете различные версии OpenSSL с отличающимися параметрами компиляции:
OpenSSL 0.9.8k 25 Mar 2009 built on: Wed May 23 00:02:00 UTC 2012 options:bn(64,64) md2(int) rc4(ptr,char) des(idx,cisc,16,int) aes(partial) ↩ blowfish(ptr2) compiler: cc -fPIC -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN ↩ -DHAVE_DLFCN_H -m64 -DL_ENDIAN -DTERMIO -O3 -Wa,--noexecstack -g -Wall -DMD32_REG_T=int ↩ -DOPENSSL_BN_ASM_MONT -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM available timing options: TIMES TIMEB HZ=100 [sysconf value] timing function used: times The 'numbers' are in 1000s of bytes per second processed.
Во второй части приводятся результаты тестирования симметричной криптографии (хэш-функций и криптографических алгоритмов):
type 16 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes sha1 29275.44k 85281.86k 192290.28k 280526.68k 327553.12k rc4 160087.81k 172435.03k 174264.75k 176521.50k 176700.62k aes-128 cbc 90345.06k 140108.84k 170027.92k 179704.12k 182388.44k aes-192 cbc 104770.95k 134601.12k 148900.05k 152662.30k 153941.11k aes-256 cbc 95868.62k 116430.41k 124498.19k 127007.85k 127430.81k sha256 23354.37k 54220.61k 99784.35k 126494.48k 138266.71k sha512 16022.98k 64657.88k 113304.06k 178301.77k 214539.99k
Наконец, в третьей части результаты тестирования асимметричной криптографии:
sign verify sign/s verify/s rsa 512 bits 0.000120s 0.000011s 8324.9 90730.0 rsa 1024 bits 0.000569s 0.000031s 1757.0 31897.1 rsa 2048 bits 0.003606s 0.000102s 277.3 9762.0 rsa 4096 bits 0.024072s 0.000376s 41.5 2657.4 op op/s 160 bit ecdh (secp160r1) 0.0003s 2890.2 192 bit ecdh (nistp192) 0.0006s 1702.9 224 bit ecdh (nistp224) 0.0006s 1743.5 256 bit ecdh (nistp256) 0.0007s 1513.3 384 bit ecdh (nistp384) 0.0015s 689.6 521 bit ecdh (nistp521) 0.0029s 340.3 163 bit ecdh (nistk163) 0.0009s 1126.2 233 bit ecdh (nistk233) 0.0012s 818.5 283 bit ecdh (nistk283) 0.0028s 360.2 409 bit ecdh (nistk409) 0.0060s 166.3 571 bit ecdh (nistk571) 0.0130s 76.8 163 bit ecdh (nistb163) 0.0009s 1061.3 233 bit ecdh (nistb233) 0.0013s 755.2 283 bit ecdh (nistb283) 0.0030s 329.4 409 bit ecdh (nistb409) 0.0067s 149.7 571 bit ecdh (nistb571) 0.0146s 68.4
Чем может быть полезен вывод этой команды? Вы можете сравнить как опции компиляции влияют на скорость, или насколько отличается скорость работы разных версий OpenSSL на одной платформе. Например, предыдущие результаты получены на реальном сервере с использованием OpenSSL 0.9.8k (с исправлениями от поставщика дистрибутива). Я планирую перейти на OpenSSL 1.0.1h, поскольку хочу иметь поддержку TLS 1.1 и TLS 1.2; окажет ли это какое-либо влияние на производительность? Для тестирования я скачал и скомпилировал OpenSSL 1.0.1h. Давайте посмотрим:
$ ./openssl-1.0.1h speed rsa [...] OpenSSL 1.0.1h 5 Jun 2014 built on: Thu Jul 3 18:30:06 BST 2014 options:bn(64,64) rc4(8x,int) des(idx,cisc,16,int) aes(partial) idea(int) blowfish(idx) compiler: gcc -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H ↩ -Wa,--noexecstack -m64 -DL_ENDIAN -DTERMIO -O3 -Wall -DOPENSSL_IA32_SSE2 -DOPENSSL_BN↩ _ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512↩ _ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM sign verify sign/s verify/s rsa 512 bits 0.000102s 0.000008s 9818.0 133081.7 rsa 1024 bits 0.000326s 0.000020s 3067.2 50086.9 rsa 2048 bits 0.002209s 0.000068s 452.8 14693.6 rsa 4096 bits 0.015748s 0.000255s 63.5 3919.4
Как видите, для моего варианта использования (2048-битный ключ RSA) OpenSSL 1.0.1h почти в два раза быстрее на этом сервере: производительность возросла в 277 до 450 электронных подписей в секунду. Это означает, что в случае обновления я получу более высокую производительность. Замечательная новость!
Использовать подобные результаты тестирования для оценки производительности будущего развертывания не совсем объективно из-за большого числа факторов, влияющих на производительность в реальной жизни. Более того, многие из этих факторов лежат за пределами TLS (например, настройки HTTP Keep-Alive, кэширование и т.д.). В лучшем случае вы можете использовать эти цифры только для приблизительной оценки.
Также нельзя упускать из виду кое-что ещё. По умолчанию команда speed
будет использовать только один процесс. У большинства серверов несколько ядер процессора, поэтому для определения того, как много операций TLS поддерживается сервером в целом, нужно указать в команде speed
использовать несколько экземпляров в параллельном режиме. Это достигается с помощью параметра -multi
. У моего сервера четыре ядра, поэтому я собираюсь использовать такую команду:
$ openssl speed -multi 4 rsa [...] OpenSSL 0.9.8k 25 Mar 2009 built on: Wed May 23 00:02:00 UTC 2012 options:bn(64,64) md2(int) rc4(ptr,char) des(idx,cisc,16,int) aes(partial) ↩ blowfish(ptr2) compiler: cc -fPIC -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN ↩ -DHAVE_DLFCN_H -m64 -DL_ENDIAN -DTERMIO -O3 -Wa,--noexecstack -g -Wall -DMD32_REG_T=int ↩ -DOPENSSL_BN_ASM_MONT -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM available timing options: TIMES TIMEB HZ=100 [sysconf value] timing function used: sign verify sign/s verify/s rsa 512 bits 0.000030s 0.000003s 33264.5 363636.4 rsa 1024 bits 0.000143s 0.000008s 6977.9 125000.0 rsa 2048 bits 0.000917s 0.000027s 1090.7 37068.1 rsa 4096 bits 0.006123s 0.000094s 163.3 10652.6
Как и ожидалось, производительность возросла почти в четыре раза (я опять сужу по количеству сформированных электронных подписей RSA в секунду, поскольку эта выполняемая на сервере криптографическая операция потребляет больше всего ресурсов процессора и всегда является самым узким местом). Результат в 1090 подписей в секунду говорит о том, что этот сервер может обработать около 1000 новых TLS-соединений в секунду. В моем случае этого достаточно, даже с хорошим запасом прочности. Поскольку у меня на сервере также включено возобновление сеанса, я уверен, что он сможет поддерживать более 1000 TLS-соединений в секунду. Надеюсь, что когда-нибудь на этом сервере будет столько трафика, чтобы мне пришлось беспокоиться о производительности TLS.
Другая причина, по которой вам не следует слишком уж доверять выводу команды speed
, — то, что по умолчанию она не использует наиболее быстрые из доступных реализаций шифров. В некотором смысле, вывод по умолчанию не отражает истинного состояния дел. Например, на серверах, поддерживающих установку инструкции AES-NI для ускорения вычислений AES, эта функция не будет использоваться по умолчанию при тестировании:
$ openssl speed aes-128-cbc [...] The 'numbers' are in 1000s of bytes per second processed. type 16 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes aes-128 cbc 67546.70k 74183.00k 69278.82k 155942.87k 156486.38k
Для активации аппаратного ускорения нужно использовать параметр командной строки -evp
:
$ openssl speed -evp aes-128-cbc [...] The 'numbers' are in 1000s of bytes per second processed. type 16 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes aes-128-cbc 188523.36k 223595.37k 229763.58k 203658.58k 206452.14k
Создание частного удостоверяющего центра
Если вы хотите настроить свой собственный УЦ, всё необходимое для этого уже включено в OpenSSL. Пользовательский интерфейс этой задачи основан исключительно на командной строке и потому не очень удобен для пользователя, но, возможно, это и к лучшему. Прохождение процесса шаг за шагом очень познавательно, поскольку заставляет задуматься о каждом аспекте и даже о мельчайших деталях.
Образовательный аспект настройки частного УЦ — главная причина, по которой я бы рекомендовал этим заняться, но есть и другие. УЦ на базе OpenSSL, каким бы кустарным на первый взгляд он ни казался, вполне может удовлетворить потребности отдельного человека или небольшой группы. К примеру, в экспериментальной среде значительно лучше использовать частный УЦ, чем повсеместно пользоваться самоподписанными сертификатами. Кроме того, клиентские сертификаты, служащие для обеспечения двухфакторной аутентификации, могут значительно повысить безопасность ваших конфиденциальных веб-приложений.
Самая большая трудность в запуске частного УЦ состоит даже не в качественной настройке всего, а в обеспечении безопасности инфраструктуры. Например, корневой ключ должен храниться автономно (оффлайн), поскольку безопасность всего УЦ зависит от его конфиденциальности. С другой стороны, CRL и сертификаты ответчиков OCSP должны регулярно обновляться, что невозможно без применения корневого ключа.
По ходу работы с данным разделом вы создадите два конфигурационных файла: один для управления корневым УЦ (root-ca.conf
), а другой для управления подчинённым УЦ (sub-ca.conf
). Их можно создавать с нуля, следуя представленным здесь инструкциям, а можно скачать шаблоны этих конфигурационных файлов из моего GitHub-репозитория13. В последнем случае вы сэкономите какое-то время, однако при ручном составлении понимание процесса будет лучше.
Основной функционал и ограничения
Далее в этом разделе мы будем создавать частный УЦ, аналогичный по своей структуре публичным УЦ. Будет создан один корневой УЦ, от которого можно будет создавать подчинённые УЦ. Информацию об отзыве сертификатов мы будем предоставлять через CRL и ответчики OCSP. Для поддержания автономности корневого УЦ у ответчиков OCSP будут свои собственные идентификационные сущности. Это не самый простой частный удостоверяющий центр, который можно было бы организовать, но зато его защита будет построена правильным образом. В качестве бонуса мы сделаем подчинённый УЦ технически ограниченным, то есть ему будет разрешено выдавать сертификаты только для разрешённых имён хостов.
По окончании развёртывания УЦ корневой сертификат должен быть безопасно распространён среди всех предполагаемых клиентов. После этого можно начинать выпуск клиентских и серверных сертификатов. Основным ограничением данного варианта установки будет то, что ответчик OCSP предназначен главным образом для тестирования и не рассчитан на высокие нагрузки.
Создание корневого УЦ
Создание нового УЦ состоит из нескольких этапов: настройка, создание структуры каталогов и инициализация значимых для УЦ файлов, и, наконец, генерация корневых ключа и сертификата. В данном разделе мы рассмотрим весь этот процесс, а также основные операции, выполняемые в рамках УЦ.
Конфигурация корневого УЦ
Перед тем, как мы сможем приступить к собственно созданию УЦ, нам необходимо подготовить конфигурационный файл (root-ca.conf
), в котором мы укажем OpenSSL, что же именно хотим получить в итоге. Большую часть времени (при повседневном использовании OpenSSL) подобные файлы конфигурации не требуются, однако для выполнения сложных операций, таких как создание корневого УЦ, они необходимы. Конфигурационные файлы OpenSSL весьма мощные; прежде чем продолжать, есть смысл ознакомиться с их возможностями (выполните man config
в командной строке).
Первая часть конфигурационного файла содержит основную информацию об УЦ, такую как имя и базовый URL, а также компоненты отличительного имени УЦ. Из-за гибкости синтаксиса, эту информацию нужно предоставить лишь один раз:
[default] name = root-ca domain_suffix = example.com aia_url = http://$name.$domain_suffix/$name.crt crl_url = http://$name.$domain_suffix/$name.crl ocsp_url = http://ocsp.$name.$domain_suffix:9080 default_ca = ca_default name_opt = utf8,esc_ctrl,multiline,lname,align [ca_dn] countryName = "GB" organizationName = "Example" commonName = "Root CA"
Вторая часть файла напрямую контролирует работу УЦ. Для получения полной информации о каждом параметре обратитесь к документации по команде ca
(выполните man ca
в командной строке). Большинство настроек говорят сами за себя; в основном мы сообщаем OpenSSL, где хотим хранить наши файлы. Поскольку этот корневой УЦ будет использоваться только для выпуска ключей и сертификатов подчиненных УЦ, я решил, что его сертификат будет действителен в течение 10 лет. Для формирования электронной подписи по умолчанию будет использован безопасный алгоритм хэширования SHA256.
Политика по умолчанию (policy_c_o_match
) сконфигурирована таким образом, что все сертификаты, издаваемые данным УЦ, будут иметь те же значения в полях countryName
и organizationName
, что и в сертификате самого УЦ. Обычно в публичных УЦ так не делается, но для частного УЦ это вполне приемлемый вариант:
[ca_default] home = . database = $home/db/index serial = $home/db/serial crlnumber = $home/db/crlnumber certificate = $home/$name.crt private_key = $home/private/$name.key RANDFILE = $home/private/random new_certs_dir = $home/certs unique_subject = no copy_extensions = none default_days = 3650 default_crl_days = 365 default_md = sha256 policy = policy_c_o_match [policy_c_o_match] countryName = match stateOrProvinceName = optional organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional
Третья часть файла содержит конфигурацию для команды req
, которая будет использоваться только один раз при создании самоподписанного корневого сертификата. Самой важной частью здесь являются расширения: значение в basicConstraints
указывает на то, что это сертификат УЦ, а в keyUsage
содержатся настройки, соответствующие этому сценарию:
[req] default_bits = 4096 encrypt_key = yes default_md = sha256 utf8 = yes string_mask = utf8only prompt = no distinguished_name = ca_dn req_extensions = ca_ext [ca_ext] basicConstraints = critical,CA:true keyUsage = critical,keyCertSign,cRLSign subjectKeyIdentifier = hash
В четвёртой части конфигурационного файла содержится информация, которая будет использоваться при создании сертификатов, издаваемых корневым удостоверяющим центром. Все эти сертификаты будут сертификатами УЦ (на что указывает содержимое расширения basicConstraints
), но мы также задаём pathlen
в ноль, а это означает, что создание дальнейших подчинённых УЦ (более глубокой вложенности) не допускается.
Все наши подчинённые УЦ будут ограничены в том смысле, что выданные ими сертификаты будут действительны только для определённых подмножеств доменных имён и только для ограниченного использования. Во-первых, в расширении extendedKeyUsage
заданы только значения clientAuth
и serverAuth
, то есть ключи могут быть использованы только для аутентификации клиента и сервера TLS. Во-вторых, расширение nameConstraints
ограничивает разрешённые имена хостов только значениями в пределах доменных имён example.com
и example.org
. В теории, такая настройка позволяет вам передать управление подчинёнными УЦ кому-то ещё, но при этом оставаться уверенным, что они не смогут выдавать сертификаты для произвольных имён хостов. При желании можно ограничить каждый подчинённый УЦ своим строго определённым (возможно, небольшим) пространством доменных имён. Требование об исключении двух диапазонов IP-адресов продиктовано «Базовыми требованиями» CA/Browser Forum14, в которых имеется определение технически ограниченного подчинённого УЦ.
На практике, установление ограничений на имена хостов работает не в полной мере, поскольку в настоящее время некоторые крупные платформы не распознают расширение nameConstraints
. Если вы пометите это расширение как критичное, такие платформы будут отклонять ваши сертификаты. Этих проблем не возникнет, если вы не станете помечать расширение как критичное (как в нашем примере), но тогда некоторые другие платформы не будут его применять.
[sub_ca_ext] authorityInfoAccess = @issuer_info authorityKeyIdentifier = keyid:always basicConstraints = critical,CA:true,pathlen:0 crlDistributionPoints = @crl_info extendedKeyUsage = clientAuth,serverAuth keyUsage = critical,keyCertSign,cRLSign nameConstraints = @name_constraints subjectKeyIdentifier = hash [crl_info] URI.0 = $crl_url [issuer_info] caIssuers;URI.0 = $aia_url OCSP;URI.0 = $ocsp_url [name_constraints] permitted;DNS.0=example.com permitted;DNS.1=example.org excluded;IP.0=0.0.0.0/0.0.0.0 excluded;IP.1=0:0:0:0:0:0:0:0/0:0:0:0:0:0:0:0
В финальной пятой части нашего файла указываются расширения, которые будут использоваться с сертификатом для подписи ответов OCSP. Чтобы иметь возможность запустить ответчик OCSP, мы генерируем специальный ключ (и сертификат) и делегируем ему возможность подписи OCSP. Как можно установить из расширений, этот сертификат не будет сертификатом УЦ:
[ocsp_ext] authorityKeyIdentifier = keyid:always basicConstraints = critical,CA:false extendedKeyUsage = OCSPSigning keyUsage = critical,digitalSignature subjectKeyIdentifier = hash
Структура каталогов корневого УЦ
На следующем шаге мы создаём определённую в предыдущем разделе структуру каталогов и инициализируем некоторые файлы, которые будут использованы при выполнении операций УЦ:
$ mkdir root-ca $ cd root-ca $ mkdir certs db private $ chmod 700 private $ touch db/index $ openssl rand -hex 16 > db/serial $ echo 1001 > db/crlnumber
Будут использоваться следующие поддиректории:
certs/
-
Хранилище сертификатов; новые сертификаты будут размещаться здесь по мере их выдачи.
db/
-
В данной директории находится база данных сертификатов (index), а также файлы, в которых хранятся серийные номера следующих сертификата и CRL. По мере необходимости OpenSSL будет создавать здесь дополнительные файлы.
private/
-
В этой директории будут храниться закрытые ключи, один для корневого УЦ и ещё один для ответчика OCSP. Важно, чтобы у других пользователей не было доступа к этой директории. На самом деле, если вы собираетесь серьёзно относиться к этому УЦ, на машине, где хранятся корневые материалы, должно быть минимально возможное количество учётных записей пользователей.
Примечание: При создании нового сертификата удостоверяющего центра важно инициализировать серийные номера сертификатов с помощью генератора случайных чисел, как сделано у меня в этом разделе. Это очень полезно, если вам когда-нибудь придётся создавать и развёртывать несколько сертификатов УЦ с одинаковым отличительным именем (обычно такое случается, если вы допустили ошибку и вынуждены начинать всё заново); конфликтов не будет, потому что сертификаты будут иметь разные серийные номера.
Генерация корневого УЦ
Мы разобьём создание корневого УЦ на два этапа. На первом мы сгенерируем ключ и CSR. Вся необходимая информация будет взята из конфигурационного файла, который мы зададим в параметре -config
:
$ openssl req -new -config root-ca.conf -out root-ca.csr -keyout private/root-ca.key
На втором этапе мы создадим самоподписанный сертификат. Параметр -extensions
указывает на раздел ca_ext
конфигурационного файла, активирующий расширения, предназначенные для корневого удостоверяющего центра:
$ openssl ca -selfsign -config root-ca.conf -in root-ca.csr -out root-ca.crt -extensions ca_ext
Структура файла базы данных
База данных в файле db/index
представляет собой обычный текстовый файл, содержащий информацию о сертификатах, по одному сертификату в каждой строке. Сразу после создания корневого УЦ в нём будет содержаться одна строка:
V 240706115345Z 1001 unknown /C=GB/O=Example/CN=Root CA
В каждой строке шесть значений, разделённых знаками табуляции:
-
Флаг статуса (
V
для валидного сертификата,R
для отозванного,E
сертификата с истёкшим сроком действия). -
Дата окончания срока действия (в формате
YYMMDDHHMMSSZ
). -
Дата отзыва, либо пустое поле, если сертификат не отозван.
-
Серийный номер (в шестнадцатеричном формате).
-
Расположение файла или
unknown
, если оно неизвестно. -
Уникальное (отличительное) имя.
Операции, выполняемые в рамках корневого УЦ
Для генерации CRL в новом УЦ используйте параметр -gencrl
команды ca
:
$ openssl ca -gencrl -config root-ca.conf -out root-ca.crl
Для выпуска сертификата выполняйте команду ca
с нужными параметрами. Важно, чтобы параметр -extensions
указывал на требуемый раздел конфигурационного файла (вы же не собираетесь создать ещё один корневой удостоверяющий центр).
$ openssl ca -config root-ca.conf -in sub-ca.csr -out sub-ca.crt -extensions sub_ca_ext
Для отзыва сертификата используйте параметр -revoke
команды ca
; вам необходимо иметь копию сертификата, который вы хотите отозвать. Поскольку все сертификаты хранятся в директории certs/
, вам нужно знать только его серийный номер. Если вы знаете уникальное имя субъекта сертификата, можно найти серийный номер в базе данных.
Выберите корректную причину отзыва и укажите её в параметре -crl_reason
. Возможные варианты: unspecified
, keyCompromise
, CACompromise
, affiliationChanged
, superseded
, cessationOfOperation
, certificateHold
и removeFromCRL
.
$ openssl ca -config root-ca.conf -revoke certs/1002.pem -crl_reason keyCompromise
Создание сертификата для подписи ответов OCSP
Сначала надо создать ключ и CSR для ответчика OCSP. Поскольку ключ и будущий сертификат не будут ключом и сертификатом удостоверяющего центра, при выполнении этой оперции мы не будем ссылаться на наш конфигурационный файл:
$ openssl req -new -newkey rsa:2048 -subj "/C=GB/O=Example/CN=OCSP Root Responder" -keyout private/root-ocsp.key -out root-ocsp.csr
Затем мы выпустим сертификат ответчика OCSP, используя наш корневой УЦ. В качестве значения параметра -extensions
мы укажем ocsp_ext
, в этом разделе конфигурационного файла заданы расширения, относящиеся к подписанию ответов OCSP. Я сократил срок действия нового сертификата до 365 дней (вместо установленных по умолчанию 3650 дней). Поскольку в подобных сертификатах OCSP не содержится информация об отзыве, они не могут быть отозваны. По этой причине целесообразно установить срок действия такого сертификата настолько коротким, насколько это возможно. Хорошим выбором будет 30 дней, при условии, что вы готовы создавать новые сертификаты с такой частотой:
$ openssl ca -config root-ca.conf -in root-ocsp.csr -out root-ocsp.crt -extensions ocsp_ext -days 30
Теперь мы полностью готовы к запуску ответчика OCSP. Для тестирования можно сделать это с той же машины, на которой размещается корневой УЦ, но в реальной производственной среде необходимо переместить ключ и сертификат ответчика OCSP в другое место.
$ openssl ocsp -port 9080 -index db/index -rsigner root-ocsp.crt -rkey private/root-ocsp.key -CA root-ca.crt -text
Работу ответчика OCSP можно протестировать следующей командой:
$ openssl ocsp -issuer root-ca.crt -CAfile root-ca.crt -cert root-ocsp.crt -url http://127.0.0.1:9080
В выводе команды verify OK
означает, что проверка подписей прошла успешно, а good
— что сертификат не был отозван.
Response verify OK root-ocsp.crt: good This Update: Jul 9 18:45:34 2014 GMT
Создание подчинённого УЦ
Процесс создания подчиненного УЦ во многом аналогичен тому, который мы выполняли для корневого УЦ. В этом разделе мы главным образом будем останавливаться на их различиях, всё остальное можно найти в предыдущем разделе.
Конфигурация подчинённого УЦ
Чтобы составить конфигурационный файл для подчинённого УЦ (sub-ca.conf
), возьмём за основу файл, который мы использовали для корневого УЦ, и внесём в него перечисленные ниже изменения. Мы изменим имя на sub-ca
и будем использовать другое отличительное имя. Ответчик OCSP будет принимать запросы на другом порту, но лишь потому, что команда ocsp
не умеет работать с виртуальными хостами. Если для организации ответчика OCSP используется полноценный веб-сервер, можно вообще обойтись без специализированных портов. По умолчанию срок действия новых сертификатов составит 365 дней, свежий CRL мы будем генерировать каждые 30 дней.
Изменение параметра copy_extensions
на значение copy
означает, что указанные в CSR расширения будут скопированы в сертификат, но только в том случае, если аналогичные расширения не были заданы в нашей конфигурации. При такой настройке те, кто готовят CSR, могут поместить в него необходимые альтернативные имена, и информация о них будет собрана и помещена в сертификат. Эта функция может быть потенциально опасна (вы позволяете стороннему лицу иметь ограниченный прямой контроль над тем, что попадёт в сертификат), но в небольших окружениях это вполне приемлемо:
[default] name = sub-ca ocsp_url = http://ocsp.$name.$domain_suffix:9081 [ca_dn] countryName = "GB" organizationName = "Example" commonName = "Sub CA" [ca_default] default_days = 365 default_crl_days = 30 copy_extensions = copy
В конце конфигурационного файла добавим два новых профиля: для клиента и для сервера. Различия между ними будут только в расширениях keyUsage
и extendedKeyUsage
. Обратите внимание, что мы указали расширение basicConstraints
, но задали его в false
. Это сделано потому, что мы копируем расширения из CSR. Если бы мы пропустили данное расширение, то вполне могли бы получить его из CSR с тем значением, которое указано там:
[server_ext] authorityInfoAccess = @issuer_info authorityKeyIdentifier = keyid:always basicConstraints = critical,CA:false crlDistributionPoints = @crl_info extendedKeyUsage = clientAuth,serverAuth keyUsage = critical,digitalSignature,keyEncipherment subjectKeyIdentifier = hash [client_ext] authorityInfoAccess = @issuer_info authorityKeyIdentifier = keyid:always basicConstraints = critical,CA:false crlDistributionPoints = @crl_info extendedKeyUsage = clientAuth keyUsage = critical,digitalSignature subjectKeyIdentifier = hash
После того, как вы доведёте до ума конфигурационный файл, создайте структуру каталогов, следуя тем же инструкциям, что и для корневого УЦ, только не забудьте указать другое имя директории, например, sub-ca
.
Генерация подчинённого УЦ
Как и в прошлый раз, создание подчинённого УЦ будем выполнять в два этапа. На первом сгенерируем ключ и CSR. Всю необходимую информацию получим из конфигурационного файла, используя параметр -config
.
$ openssl req -new -config sub-ca.conf -out sub-ca.csr -keyout private/sub-ca.key
На втором этапе мы воспользуемся корневым УЦ для выпуска сертификата. Параметр -extensions
указывает на раздел конфигурационного файла sub_ca_ext
, в котором активируются расширения, соответствующие подчинённому УЦ.
$ openssl ca -config root-ca.conf -in sub-ca.csr -out sub-ca.crt -extensions sub_ca_ext
Операции, выполняемые в рамках подчинённого УЦ
Для выпуска сертификата сервера при обработке CSR в параметре -extensions
указывается server_ext
:
$ openssl ca -config sub-ca.conf -in server.csr -out server.crt -extensions server_ext
Для выпуска сертификата клиента при обработке CSR в параметре -extensions
указывается client_ext
:
$ openssl ca -config sub-ca.conf -in client.csr -out client.crt -extensions client_ext
Примечание: При поступлении нового запроса на подписание сертификата, вся содержащаяся в нём информация должна быть представлена вам для проверки перед выполнением операции выпуска сертификата. Всегда следует проверить информацию и убедиться в том, что всё в порядке, но особенно в том случае, если CSR был подготовлен сторонним лицом. Обращайте особое внимание на отличительное имя сертификата, а также расширения basicConstraints
и subjectAlternativeName
.
Генерация CRL и отзыв сертификата осуществляются также, как и для корневого УЦ. Отличается лишь порт ответчика OCSP, для подчинённого УЦ это будет 9081. Рекомендуется, чтобы ответчик использовал свой собственный сертификат, что позволит избежать хранения подчинённого УЦ на общедоступном сервере.
Примечания
[1] Буквы “eay” в названии SSLeay представляют собой инициалы разработчика Eric A. Young.
[2] BoringSSL (Chromium, проверено 30 июня 2015 г.)
[3] Win32 OpenSSL (Shining Light Productions, проверено 3 июля 2014 г.)
[4] Бинарники и модули Apache 2.4 VC14 (Apache Lounge, проверено 15 июля 2015 г.)
[5] Пакет исходных кодов “openssl” в Precise (Ubuntu, проверено 3 июля 2014 г.)
[6] Компиляция с усиленной защитой в Ubuntu и Debian (Kees Cook, 3 февраля 2014 г.)
[7] Существуют организации, в которых придерживаются очень строгих требований обеспечения безопасности, в частности, защита закрытых ключей в них должна быть обеспечена любой ценой. Решением для таких организаций может стать инвестирование в Аппаратные модули безопасности (Hardware Security Module, HSM) — продукты, специально разработанные для того, чтобы сделать извлечение ключей невозможным даже при физическом доступе к серверу. Для достижения этого HSM не только генерируют и хранят ключи, но также выполняют все необходимые операции (например, генерацию электронной подписи). Обычно HSM очень дороги.
[8] RFC 2985: PKCS #9: Избранные объектные классы и типы атрибутов, версия 2.0 (M. Nystrom и B. Kaliski, ноябрь 2000 г.)
[9] Криптография/Атака «встреча посередине» (Wikibooks, проверено 31 марта 2014 г.)
[10] Публикация «Attacking Triple Encryption» («Техники атак на 3DES») (Stefan Lucks, 1998 г.)
[11] Публикация «On the Security of RC4 in TLS and WPA» («О безопасности RC4 в TLS и WPA») (AlFardan и другие, 13 марта 2013 г.)
[12] RFC 7905: Наборы алгоритмов шифрования для TLS ChaCha20-Poly1305 (Langley и другие, июнь 2016 г.)
[13] Шаблоны конфигурации УЦ для OpenSSL (GitHub-репозиторий книги «Bulletproof SSL and TLS», проверено 31 марта 2017 г.)
[14] «Базовые требования» (The CA/Browser Forum, проверено 9 июля 2014 г.)
Copyright © 2020 Feisty Duck. Все права защищены.
Переведено участниками проекта Pro-LDAP.ru в 2020 году.
I have a pre-built OpenSSL library (libssl.a and libcrypto.a) which are being used for my C++ application. I don’t know the version of the OpenSSL library.
Is there any way to get the version number from these pre-built libraries?
asked Apr 27, 2014 at 7:13
Naseef ChowdhuryNaseef Chowdhury
2,3373 gold badges27 silver badges52 bronze badges
0
There is a string inside the library containing the version details called SSLEAY_VERSION — it looks like:
OpenSSL 0.9.5a 1 Apr 2000
OpenSSL 1.0.1e-fips 11 Feb 2013
You can find this from the binary library using strings and grep:
strings libcrypto.so | grep "^OpenSSL S+ [0-9]+ S+ [0-9]+"
answered Oct 29, 2014 at 16:11
John SladeJohn Slade
11.8k2 gold badges24 silver badges20 bronze badges
2
You can do this programatically by reading the following:
OPENSSL_VERSION_NUMBER(3)
and
SSLeay_version(3)
Basically, you will need to use the following functions:
SSLeay()
SSLeay_version()
jww
95k88 gold badges396 silver badges860 bronze badges
answered Apr 27, 2014 at 7:53
László PappLászló Papp
51k39 gold badges110 silver badges135 bronze badges
14
Well the filtering may may not always work. You could do
strings libssl.so | grep "^OpenSSL"
OpenSSLDie
OpenSSL 1.0.2n 7 Dec 2017
strings libcrypto.so | grep "^OpenSSL"
OpenSSLDie
OpenSSL_add_all_ciphers
OpenSSL_add_all_digests
OpenSSL 1.0.2n 7 Dec 2017
OpenSSL HMAC method
OpenSSL EC algorithm
OpenSSL RSA method
OpenSSL DSA method
OpenSSL ECDSA method
OpenSSL DH Method
OpenSSL X9.42 DH method
OpenSSL PKCS#3 DH method
OpenSSL ECDH method
OpenSSL 'dlfcn' shared library method
OpenSSL default
OpenSSL default user interface
OpenSSL CMAC method
m00am
5,67211 gold badges55 silver badges67 bronze badges
answered Dec 15, 2017 at 9:45
Divakar YDivakar Y
1511 silver badge5 bronze badges
I needed a variant of https://stackoverflow.com/a/26635393/597742 that would work on systems without strings
installed. It’s sufficiently different that it seemed worthwhile to post as its own answer:
grep --text -o 'OpenSSL [[:digit:]][^ ]*' /file/to/check
--text
allows the binary to be checked directly, -o
accounts for the lack of line separators by only printing the matching text.
A point worth noting for both this answer and the strings
based answer: in addition to being useful to check the OpenSSL version of libssl
or libcrypto
, they also work to check OpenSSL versions in statically linked binaries.
answered Sep 16, 2022 at 3:43
ncoghlanncoghlan
39.4k10 gold badges71 silver badges79 bronze badges
OpenSSL is very long running project which have passed a lot of versions. Newer versions provides more features, bug fixes and security patches. For example in year 2014 a serious security hole Heart Bleed discovered in OpenSSL versions and affected OpenSSL libraries are defined as versions.Following versions was vulnerable to Hear Bleed.
- OpenSSL 1.0.1 trough 1.0.1f inclusive
- OpenSSL 1.0.1g is not vulnerable
So version is important part of the OpenSSL library.
We will use version
verb with the OpenSSL command like below.
Print OpenSSL Directory
We can print the OpenSSL directory with version -d
option like below.
$ openssl version -d
Print Detailed Version Information
We can print more detailed version information like following
- Built time
- Platform and Architecture like 32 bit or 64
- Options
- Compiler flags
$ openssl version -a
We can see in detailed version info that which cryptographic extensions and libraries are enabled like `-DSHA512 which specifies SHA512 is enabled.
Материал из Xgu.ru
Перейти к: навигация, поиск
OpenSSL — универсальный криптографический инструмент,
построенный вокруг протоколов SSL/TLS и сертификатов X.509.
Помимо того, что этот инструмент позволяет
работать с соединениями SSL/TLS, сертификатами X.509,
он может делать множество других полезных вещей:
шифровать и расшифровывать файлы,
создавать и проверять цифровые подписи,
проверять числа на простоту,
тестировать производительность компьютера
и другое.
Содержание
- 1 Вопросы и ответы
- 1.1 Введение
- 1.1.1 Как определить какую версию OpenSSL я использую?
- 1.1.2 Как получить список доступных команд?
- 1.1.3 Как посмотреть список доступных шифров?
- 1.2 Измерение производительности
- 1.2.1 Как измерить производительность системы с помощью openssl?
- 1.2.2 Как измерить производительность сетевого соединения?
- 1.3 Сертификаты
- 1.3.1 Как сгенерировать самоподписной сертификат?
- 1.3.2 Как сгенерировать запрос сертификата у VeriSign?
- 1.3.3 Как проверить новый сертификат?
- 1.3.4 Как получить удалённый сертификат?
- 1.3.5 Как извлечь какую-либо информацию из сертификата?
- 1.3.6 Как экспортировать или импортировать сертификат PKCS#12?
- 1.4 Проверка сертификата
- 1.4.1 Как проверить сертификат?
- 1.4.2 Какие центры сертификации распознаёт OpenSSL?
- 1.4.3 Как мне заставить OpenSSL признавать сертификат?
- 1.5 Клиенты и серверы для командной строки
- 1.5.1 Как подключиться к безопасному SMTP-серверу?
- 1.5.2 Как подключиться к [какому-либо] безопасному серверу?
- 1.5.3 Как запустить SSL-сервер из командной строки?
- 1.6 Дайджесты
- 1.6.1 Как создавать дайджесты MD5 или SHA1?
- 1.6.2 Как подписать дайджест?
- 1.6.3 Как проверить подписанный дайджест?
- 1.6.4 Как создать запись типа digest для файла паролей Apache?
- 1.6.5 Какие ещё есть дайджесты?
- 1.7 Шифрование/расшифровка
- 1.7.1 Как закодировать что-то по методу base64?
- 1.7.2 Как зашифровать файл?
- 1.8 Ошибки
- 1.8.1 Как интерпретировать сообщения об ошибках SSL?
- 1.9 Ключи
- 1.9.1 Как сгенерировать ключ RSA?
- 1.9.2 Как сгенерировать открытый ключ RSA?
- 1.9.3 Как сгенерировать ключ DSA?
- 1.9.4 Как создать ключ, основанный на эллиптических кривых (elliptic curve key)?
- 1.9.5 Как создать открытый EC ключ?
- 1.9.6 Как удалить парольную фразу у ключа?
- 1.10 Хэши для паролей
- 1.10.1 Как сгенерировать хэш в стиле crypt?
- 1.10.2 Как сгенерировать хэш пароля в стиле shadow?
- 1.11 Простые числа
- 1.11.1 Как проверить, является ли число простым?
- 1.11.2 Как сгенерировать набор простых чисел?
- 1.12 Случайные данные
- 1.12.1 Как генерировать случайные данные?
- 1.13 S/MIME
- 1.13.1 Как проверить подписанное сообщение S/MIME?
- 1.13.2 Как зашифровать сообщение S/MIME?
- 1.13.3 Как подписать сообщение S/MIME?
- 1.1 Введение
- 2 Подключение сертифицированного СКЗИ Рутокен ЭЦП к OpenSSL
- 3 Дополнительная информация
- 4 Примечания
Вопросы и ответы
- Раздел написан на основе 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/,
в котором находятся файлы трёх разных типов:
- Большой файл под названием cert.pem, объёмистый сборник многих сертификатов от признанных общеизвестных центров сертификации, таких как VeriSign и Thawte.
- Множество маленьких файлов с расширением .pem, каждый из которых содержит сертификат от отдельного центра сертификации;
- Символические ссылки в со странными именами вида 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:%sn" "$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 и родственных инструментов
|
||
---|---|---|
Основы | Криптография | |
AAA | Kerberos • EAP • Host-based аутентификация в OpenSSH | |
Шифрование данных на диске | Шифрование LVM • LUKS | |
Шифрование сетевых данных | VPN • IPsec • OpenVPN • SSL • OpenSSL • TLS • SSH | |
Криптография в VoIP | Шифрование звонков в Asterisk • SRTP |
Примечания
- ↑ http://www.madboa.com/geek/openssl/