# 16.8.OpenSSL

OpenSSL 是一款加密工具包，实现在网络协议中使用的安全套接字层（SSL）和传输层安全性（TLS）协议，并提供许多加密功能。

openssl 程序是一款命令行工具，能通过 shell 使用 OpenSSL 加密库的各种加密功能。它可以用于：

* 创建和管理私钥、公钥和参数
* 公钥加密操作
* 创建 X.509 证书、证书签名请求（CSR）和证书撤销列表（CRL）
* 计算消息摘要
* 使用密码进行加密和解密
* SSL/TLS 客户端和服务器测试
* 处理 S/MIME 签名或加密邮件
* 时间戳请求、生成和验证
* 基准测试加密例程

有关 OpenSSL 的更多信息，请阅读免费的 [OpenSSL Cookbook](https://www.feistyduck.com/books/openssl-cookbook/)。

## 16.8.1. 生成证书

OpenSSL 支持生成证书，无论是通过 [CA](https://en.wikipedia.org/wiki/Certificate_authority) 验证的证书，还是供自用的证书。

运行命令 [openssl(1)](https://man.freebsd.org/cgi/man.cgi?query=openssl\&sektion=1\&format=html) 来生成一个有效的证书，向 [CA](https://en.wikipedia.org/wiki/Certificate_authority) 请求证书。此命令将在当前目录创建两个文件。证书请求文件 **req.pem** 可以发送给一个 [CA](https://en.wikipedia.org/wiki/Certificate_authority)，该 CA 会验证输入的凭据，签名请求并返回签名后的证书。第二个文件 **cert.key** 是证书的私钥，应存放在安全的地方。如果此文件被他人获取，它可以用于冒充用户或服务器。

执行以下命令来生成证书：

```sh
# openssl req -new -nodes -out req.pem -keyout cert.key -sha3-512 -newkey rsa:4096
```

输出类似如下：

```sh
Generating a RSA private key
..................................................................................................................................+++++
......................................+++++
writing new private key to 'cert.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]:ES
State or Province Name (full name) [Some-State]:Valencian Community
Locality Name (eg, city) []:Valencia
Organization Name (eg, company) [Internet Widgits Pty Ltd]:My Company
Organizational Unit Name (eg, section) []:Systems Administrator
Common Name (e.g. server FQDN or YOUR name) []:localhost.example.org
Email Address []:user@FreeBSD.org

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:123456789
An optional company name []:Another name
```

或者，如果不需要 [CA](https://en.wikipedia.org/wiki/Certificate_authority) 签名，则可以创建一个自签名证书。这样会在当前目录创建两个新文件：一个是私钥文件 **cert.key**，另一个是证书文件 **cert.crt**。这些文件应放置在一个目录中，最好是在 **/etc/ssl/** 下，该目录仅对 `root` 用户可读。将文件的权限设置为 `0700`，可以使用 `chmod` 设置。

执行以下命令来生成证书：

```sh
# openssl req -new -x509 -days 365 -sha3-512 -keyout /etc/ssl/private/cert.key -out /etc/ssl/certs/cert.crt
```

输出类似如下：

```sh
Generating a RSA private key
........................................+++++
...........+++++
writing new private key to '/etc/ssl/private/cert.key'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
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]:ES
State or Province Name (full name) [Some-State]:Valencian Community
Locality Name (eg, city) []:Valencia
Organization Name (eg, company) [Internet Widgits Pty Ltd]:My Company
Organizational Unit Name (eg, section) []:Systems Administrator
Common Name (e.g. server FQDN or YOUR name) []:localhost.example.org
Email Address []:user@FreeBSD.org
```

## 16.8.2. 配置 FIPS 提供程序

在 FreeBSD 14 及更高版本中，OpenSSL 3 被引入到基本系统，并且引入了提供程序模块的概念。除了库中内置的默认提供程序模块外，*legacy* 模块实现了现已过时的、可选的加密算法，而 *fips* 模块则将 OpenSSL 的实现限制为符合 [FIPS](https://en.wikipedia.org/wiki/Federal_Information_Processing_Standards) 标准集的加密算法。OpenSSL 中这一部分得到了 [特别关注](https://www.openssl.org/docs/fips.html)，包括 [相关安全问题的列表](https://www.openssl.org/news/fips-cve.html)，并且定期接受 [FIPS 140 验证过程](https://github.com/openssl/openssl/blob/master/README-FIPS.md)。也可以查阅 [FIPS 验证版本的列表](https://www.openssl.org/source/)，以确保用户在使用 OpenSSL 时符合 FIPS 标准。

重要的是， [fips\_module(7)](https://man.freebsd.org/cgi/man.cgi?query=fips_module\&sektion=7\&format=html) 受到额外的安全措施保护，禁止在未通过完整性检查的情况下使用该模块。此检查可以由本地系统管理员进行设置，允许每个 OpenSSL 3 的用户加载该模块。如果配置不正确，FIPS 模块将按以下方式失败：

```sh
# echo test | openssl aes-128-cbc -a -provider fips -pbkdf2
```

输出应类似如下：

```sh
aes-128-cbc: unable to load provider fips
Hint: use -provider-path option or OPENSSL_MODULES environment variable.
00206124D94D0000:error:1C8000D5:Provider routines:SELF_TEST_post:missing config data:crypto/openssl/providers/fips/self_test.c:275:
00206124D94D0000:error:1C8000E0:Provider routines:ossl_set_error_state:fips module entering error state:crypto/openssl/providers/fips/self_test.c:373:
00206124D94D0000:error:1C8000D8:Provider routines:OSSL_provider_init_int:self test post failure:crypto/openssl/providers/fips/fipsprov.c:707:
00206124D94D0000:error:078C0105:common libcrypto routines:provider_init:init fail:crypto/openssl/crypto/provider_core.c:932:name=fips
```

可以通过在 **/etc/ssl/fipsmodule.cnf** 中创建文件来配置检查，然后在 OpenSSL 的主配置文件 **/etc/ssl/openssl.cnf** 中引用该文件。OpenSSL 提供了 [openssl-fipsinstall(1)](https://man.freebsd.org/cgi/man.cgi?query=openssl-fipsinstall\&sektion=1\&format=html) 工具来帮助完成此过程，可以按如下方式使用：

```sh
# openssl fipsinstall -module /usr/lib/ossl-modules/fips.so -out /etc/ssl/fipsmodule.cnf
```

输出应类似如下：

```sh
INSTALL PASSED
```

然后应该修改 **/etc/ssl/openssl.cnf** 文件，以便：

* 包含上述生成的 **/etc/ssl/fipsmodule.cnf** 文件，
* 暴露 FIPS 模块以供可能使用，
* 并显式激活默认模块。

```ini
[...]
# 对于 FIPS
# 可选地包含一个由 OpenSSL fipsinstall 应用程序生成的文件。该文件包含 OpenSSL fips 提供者所需的配置数据。
# 它包含一个命名的部分，例如 [fips_sect]，该部分在下面的 [provider_sect] 中被引用。
# 有关更多信息，请参阅 OpenSSL 安全策略。
.include /etc/ssl/fipsmodule.cnf

[...]

# 要加载的提供者列表
[provider_sect]
default = default_sect
# fips 部分名称应与包含的 fipsmodule.cnf 中的部分名称匹配。
fips = fips_sect

# 如果没有显式激活提供者，则默认提供者会被隐式激活。
# 有关更多细节，请参见 man 7 OSSL_PROVIDER-default。
#
# 如果显式添加一个部分来激活任何其他提供者，你很可能需要显式激活默认提供者，否则它
# 将在 openssl 中不可用。结果，依赖于 OpenSSL 的应用程序可能无法正常工作，这可能会导致
# 系统出现重大问题，包括无法远程访问系统。
[default_sect]
activate = 1
```

完成此操作后，应该可以确认 FIPS 模块有效并且可以正常工作：

```sh
# echo test | openssl aes-128-cbc -a -provider fips -pbkdf2
```

输出应类似如下：

```ini
enter AES-128-CBC encryption password:
Verifying - enter AES-128-CBC encryption password:
U2FsdGVkX18idooW6e3LqWeeiKP76kufcOUClh57j8U=
```

每当修改 FIPS 模块时，例如在进行系统更新或应用 OpenSSL 相关的安全修复后，都必须重复此过程。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://handbook.bsdcn.org/di-16-zhang-an-quan/16.8.-openssl.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
