Как проверить версию openssl на windows

In this SIMPLE Updated Tutorial Learn How to Check the OpenSSL Version Number. Learn How To Determine which OpenSSL version you have!

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, or compiler: information not available otherwise.

OPENSSL_BUILT_ON

The date of the build process in the form built on: ... if available or built 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, or platform: information not available otherwise.

OPENSSL_DIR

The OPENSSLDIR setting of the library build in the form OPENSSLDIR: "..." if available, or OPENSSLDIR: N/A otherwise.

OPENSSL_ENGINES_DIR

The ENGINESDIR setting of the library build in the form ENGINESDIR: "..." if available, or ENGINESDIR: 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, or MODULESDIR: 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 or CPUINFO: 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 наборов. Каждая строка содержит информацию об одном наборе в виде следующих полей:

  1. Имя набора

  2. Минимально допустимая версия протокола

  3. Алгоритм обмена ключами

  4. Алгоритм аутентификации

  5. Алгоритм и стойкость шифрования

  6. Алгоритм MAC (обеспечения целостности)

  7. Индикатор экспортного набора

Если изменить параметр 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:

Собираем всё вместе

Для демонстрации того, как объединяются различные функции конфигурации наборов шифров, рассмотрим один законченный пример реального использования. Но не забывайте о том, что это всего лишь пример. Поскольку при выборе реальной конфигурации обычно необходимо учитывать множество аспектов, не существует такого понятия, как единственно возможная идеальная конфигурация.

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

  1. Используются только стойкие шифры с фактическим уровнем криптостойкости 128 бит и выше (это исключает 3DES).

  2. Используются только наборы, обеспечивающие строгую аутентификацию (это исключает анонимные и экспортные наборы).

  3. Не используются любые наборы, полагающиеся на уязвимые исходные алгоритмы (например, MD5).

  4. Реализуется надежная поддержка прямой секретности, независимо от того, какие ключи и протоколы применяются. С этим требованием связано небольшое снижение производительности, потому что не будет возможности использовать быстрый обмен ключами RSA. Чтобы минимизировать это снижение, мы будем отдавать приоритет ECDHE, которые значительно быстрее, чем DHE.

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

  6. При работе с клиентами TLS 1.2 предпочтение отдаётся наборам AES GCM, обеспечивающим наилучший уровень безопасности, который только может предложить TLS.

  7. Поскольку недавно выяснилось, что шифры 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

В каждой строке шесть значений, разделённых знаками табуляции:

  1. Флаг статуса (V для валидного сертификата, R для отозванного, E сертификата с истёкшим сроком действия).

  2. Дата окончания срока действия (в формате YYMMDDHHMMSSZ).

  3. Дата отзыва, либо пустое поле, если сертификат не отозван.

  4. Серийный номер (в шестнадцатеричном формате).

  5. Расположение файла или unknown, если оно неизвестно.

  6. Уникальное (отличительное) имя.

Операции, выполняемые в рамках корневого УЦ

Для генерации 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 Chowdhury's user avatar

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 Slade's user avatar

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's user avatar

jww

95k88 gold badges396 silver badges860 bronze badges

answered Apr 27, 2014 at 7:53

László Papp's user avatar

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's user avatar

m00am

5,67211 gold badges55 silver badges67 bronze badges

answered Dec 15, 2017 at 9:45

Divakar Y's user avatar

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

ncoghlan's user avatar

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.

Check and Print OpenSSL Version 

Check and Print OpenSSL Version 

Print OpenSSL Directory

We can print the OpenSSL directory with version -d option like below.

$ openssl version -d

Print OpenSSL Directory

Print OpenSSL Directory

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

Print Detailed Version Information

Print Detailed Version Information

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?
  • 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/,
в котором находятся файлы трёх разных типов:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Дайджесты

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

#!/bin/bash

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

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

printf "n%s:%s:%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 и родственных инструментов
 Просмотр этого шаблона Криптография на Xgu.ru
Основы Криптография ciphrdsk.gif
AAA Kerberos  • EAP  • Host-based аутентификация в OpenSSH
Шифрование данных на диске Шифрование LVM  • LUKS
Шифрование сетевых данных VPN  • IPsec  • OpenVPN  • SSL  • OpenSSL  • TLS  • SSH
Криптография в VoIP Шифрование звонков в Asterisk • SRTP

Примечания

  1. ↑ http://www.madboa.com/geek/openssl/

Понравилась статья? Поделить с друзьями:
  • Как проверить direct3d на windows 10
  • Как проверить версию opengl на windows 10
  • Как проверить checksum файла windows 7
  • Как проверить активирована ли windows 10 pro
  • Как проверить версию node js windows