标签 OpenSSL 下的文章

OpenSSL 是一个实用工具,它可以确保其他人员无法打开你的敏感和机密消息。

 title=

加密是对消息进行编码的一种方法,这样可以保护消息的内容免遭他人窥视。一般有两种类型:

  1. 密钥加密或对称加密
  2. 公钥加密或非对称加密

密钥加密 secret-key encryption 使用相同的密钥进行加密和解密,而 公钥加密 public-key encryption 使用不同的密钥进行加密和解密。每种方法各有利弊。密钥加密速度更快,而公钥加密更安全,因为它解决了安全共享密钥的问题,将它们结合在一起可以最大限度地利用每种类型的优势。

公钥加密

公钥加密使用两组密钥,称为密钥对。一个是公钥,可以与你想要秘密通信的任何人自由共享。另一个是私钥,应该是一个秘密,永远不会共享。

公钥用于加密。如果某人想与你交流敏感信息,你可以将你的公钥发送给他们,他们可以使用公钥加密消息或文件,然后再将其发送给你。私钥用于解密。解密发件人加密的消息的唯一方法是使用私钥。因此,它们被称为“密钥对”,它们是相互关联的。

如何使用 OpenSSL 加密文件

OpenSSL 是一个了不起的工具,可以执行各种任务,例如加密文件。本文使用安装了 OpenSSL 的 Fedora 计算机。如果你的机器上没有,则可以使用软件包管理器进行安装:

alice $ cat /etc/fedora-release
Fedora release 33 (Thirty Three)
alice $
alice $ openssl version
OpenSSL 1.1.1i FIPS  8 Dec 2020
alice $

要探索文件加密和解密,假如有两个用户 Alice 和 Bob,他们想通过使用 OpenSSL 交换加密文件来相互通信。

步骤 1:生成密钥对

在加密文件之前,你需要生成密钥对。你还需要一个 密码短语 passphrase ,每当你使用 OpenSSL 时都必须使用该密码短语,因此务必记住它。

Alice 使用以下命令生成她的一组密钥对:

alice $ openssl genrsa -aes128 -out alice_private.pem 1024

此命令使用 OpenSSL 的 genrsa 命令生成一个 1024 位的公钥/私钥对。这是可以的,因为 RSA 算法是不对称的。它还使用了 aes128 对称密钥算法来加密 Alice 生成的私钥。

输入命令后,OpenSSL 会提示 Alice 输入密码,每次使用密钥时,她都必须输入该密码:

alice $ openssl genrsa -aes128 -out alice_private.pem 1024
Generating RSA private key, 1024 bit long modulus (2 primes)
..........+++++
..................................+++++
e is 65537 (0x010001)
Enter pass phrase for alice_private.pem:
Verifying - Enter pass phrase for alice_private.pem:
alice $
alice $
alice $ ls -l alice_private.pem
-rw-------. 1 alice alice 966 Mar 22 17:44 alice_private.pem
alice $
alice $ file alice_private.pem
alice_private.pem: PEM RSA private key
alice $

Bob 使用相同的步骤来创建他的密钥对:

bob $ openssl genrsa -aes128 -out bob_private.pem 1024
Generating RSA private key, 1024 bit long modulus (2 primes)
..................+++++
............................+++++
e is 65537 (0x010001)
Enter pass phrase for bob_private.pem:
Verifying - Enter pass phrase for bob_private.pem:
bob $
bob $ ls -l bob_private.pem
-rw-------. 1 bob bob 986 Mar 22 13:48 bob_private.pem
bob $
bob $ file bob_private.pem
bob_private.pem: PEM RSA private key
bob $

如果你对密钥文件感到好奇,可以打开命令生成的 .pem 文件,但是你会看到屏幕上的一堆文本:

alice $ head alice_private.pem
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,E26FAC1F143A30632203F09C259200B9

pdKj8Gm5eeAOF0RHzBx8l1tjmA1HSSvy0RF42bOeb7sEVZtJ6pMnrJ26ouwTQnkL
JJjUVPPHoKZ7j4QpwzbPGrz/hVeMXVT/y33ZEEA+3nrobwisLKz+Q+C9TVJU3m7M
/veiBO9xHMGV01YBNeic7MqXBkhIrNZW6pPRfrbjsBMBGSsL8nwJbb3wvHhzPkeM
e+wtt9S5PWhcnGMj3T+2mtFfW6HWpd8Kdp60z7Nh5mhA9+5aDWREfJhJYzl1zfcv
Bmxjf2wZ3sFJNty+sQVajYfk6UXMyJIuWgAjnqjw6c3vxQi0KE3NUNZYO93GQgEF
pyAnN9uGUTBCDYeTwdw8TEzkyaL08FkzLfFbS2N9BDksA3rpI1cxpxRVFr9+jDBz
alice $

要查看密钥的详细信息,可以使用以下 OpenSSL 命令打开 .pem 文件并显示内容。你可能想知道在哪里可以找到另一个配对的密钥,因为这是单个文件。你观察的很细致,获取公钥的方法如下:

alice $ openssl rsa -in alice_private.pem -noout -text
Enter pass phrase for alice_private.pem:
RSA Private-Key: (1024 bit, 2 primes)
modulus:
    00:bd:e8:61:72:f8:f6:c8:f2:cc:05:fa:07:aa:99:
    47:a6:d8:06:cf:09:bf:d1:66:b7:f9:37:29:5d:dc:
    c7:11:56:59:d7:83:b4:81:f6:cf:e2:5f:16:0d:47:
    81:fe:62:9a:63:c5:20:df:ee:d3:95:73:dc:0a:3f:
    65:d3:36:1d:c1:7d:8b:7d:0f:79:de:80:fc:d2:c0:
    e4:27:fc:e9:66:2d:e2:7e:fc:e6:73:d1:c9:28:6b:
    6a:8a:e8:96:9d:65:a0:8a:46:e0:b8:1f:b0:48:d4:
    db:d4:a3:7f:0d:53:36:9a:7d:2e:e7:d8:f2:16:d3:
    ff:1b:12:af:53:22:c0:41:51
publicExponent: 65537 (0x10001)

<< 截断 >>

exponent2:
    6e:aa:8c:6e:37:d0:57:37:13:c0:08:7e:75:43:96:
    33:01:99:25:24:75:9c:0b:45:3c:a2:39:44:69:84:
    a4:64:48:f4:5c:bc:40:40:bf:84:b8:f8:0f:1d:7b:
    96:7e:16:00:eb:49:da:6b:20:65:fc:a9:20:d9:98:
    76:ca:59:e1
coefficient:
    68:9e:2e:fa:a3:a4:72:1d:2b:60:61:11:b1:8b:30:
    6e:7e:2d:f9:79:79:f2:27:ab:a0:a0:b6:45:08:df:
    12:f7:a4:3b:d9:df:c5:6e:c7:e8:81:29:07:cd:7e:
    47:99:5d:33:8c:b7:fb:3b:a9:bb:52:c0:47:7a:1c:
    e3:64:90:26
alice $

步骤 2:提取公钥

注意,公钥是你可以与他人自由共享的密钥,而你必须将私钥保密。因此,Alice 必须提取她的公钥,并将其保存到文件中:

alice $ openssl rsa -in alice_private.pem -pubout > alice_public.pem
Enter pass phrase for alice_private.pem:
writing RSA key
alice $
alice $ ls -l *.pem
-rw-------. 1 alice alice 966 Mar 22 17:44 alice_private.pem
-rw-rw-r--. 1 alice alice 272 Mar 22 17:47 alice_public.pem
alice $

你可以使用与之前相同的方式查看公钥详细信息,但是这次,输入公钥 .pem 文件:

alice $
alice $ openssl rsa -in alice_public.pem -pubin -text -noout
RSA Public-Key: (1024 bit)
Modulus:
    00:bd:e8:61:72:f8:f6:c8:f2:cc:05:fa:07:aa:99:
    47:a6:d8:06:cf:09:bf:d1:66:b7:f9:37:29:5d:dc:
    c7:11:56:59:d7:83:b4:81:f6:cf:e2:5f:16:0d:47:
    81:fe:62:9a:63:c5:20:df:ee:d3:95:73:dc:0a:3f:
$

Bob 可以按照相同的过程来提取他的公钥并将其保存到文件中:

bob $ openssl rsa -in bob_private.pem -pubout > bob_public.pem
Enter pass phrase for bob_private.pem:
writing RSA key
bob $
bob $ ls -l *.pem
-rw-------. 1 bob bob 986 Mar 22 13:48 bob_private.pem
-rw-r--r--. 1 bob bob 272 Mar 22 13:51 bob_public.pem
bob $

步骤 3:交换公钥

这些公钥在 Alice 和 Bob 彼此交换之前没有太大用处。有几种共享公钥的方法,例如使用 scp 命令将密钥复制到彼此的工作站。

将 Alice 的公钥发送到 Bob 的工作站:

alice $ scp alice_public.pem bob@bob-machine-or-ip:/path/

将 Bob 的公钥发送到 Alice 的工作站:

bob $ scp bob_public.pem alice@alice-machine-or-ip:/path/

现在,Alice 有了 Bob 的公钥,反之亦然:

alice $ ls -l bob_public.pem
-rw-r--r--. 1 alice alice 272 Mar 22 17:51 bob_public.pem
alice $
bob $ ls -l alice_public.pem
-rw-r--r--. 1 bob bob 272 Mar 22 13:54 alice_public.pem
bob $

步骤 4:使用公钥交换加密的消息

假设 Alice 需要与 Bob 秘密交流。她将秘密信息写入文件中,并将其保存到 top_secret.txt 中。由于这是一个普通文件,因此任何人都可以打开它并查看其内容,这里并没有太多保护:

alice $
alice $ echo "vim or emacs ?" > top_secret.txt
alice $
alice $ cat top_secret.txt
vim or emacs ?
alice $

要加密此秘密消息,Alice 需要使用 openssls -encrypt 命令。她需要为该工具提供三个输入:

  1. 秘密消息文件的名称
  2. Bob 的公钥(文件)
  3. 加密后新文件的名称
alice $ openssl rsautl -encrypt -inkey bob_public.pem -pubin -in top_secret.txt -out top_secret.enc
alice $
alice $ ls -l top_secret.*
-rw-rw-r--. 1 alice alice 128 Mar 22 17:54 top_secret.enc
-rw-rw-r--. 1 alice alice  15 Mar 22 17:53 top_secret.txt
alice $
alice $

加密后,原始文件仍然是可见的,而新创建的加密文件在屏幕上看起来像乱码。这样,你可以确定秘密消息已被加密:

alice $ cat top_secret.txt
vim or emacs ?
alice $
alice $ cat top_secret.enc
�s��uM)M&>��N��}dmCy92#1X�q?��v���M��@��E�~��1�k~&PU�VhHL�@^P��(��zi�M�4p�e��g+R�1�Ԁ���s�������q_8�lr����C�I-��alice $
alice $
alice $
alice $ hexdump -C ./top_secret.enc
00000000  9e 73 12 8f e3 75 4d 29  4d 26 3e bf 80 4e a0 c5  |.s...uM)M&>..N..|
00000010  7d 64 6d 43 79 39 32 23  31 58 ce 71 f3 ba 95 a6  |}dmCy92#1X.q....|
00000020  c0 c0 76 17 fb f7 bf 4d  ce fc 40 e6 f4 45 7f db  |[email protected]..|
00000030  7e ae c0 31 f8 6b 10 06  7e 26 50 55 b5 05 56 68  |~..1.k..~&PU..Vh|
00000040  48 4c eb 40 5e 50 fe 19  ea 28 a8 b8 7a 13 69 d7  |HL.@^P...(..z.i.|
00000050  4d b0 34 70 d8 65 d5 07  95 67 2b 52 ea 31 aa d4  |M.4p.e...g+R.1..|
00000060  80 b3 a8 ec a1 73 ed a7  f9 17 c3 13 d4 fa c1 71  |.....s.........q|
00000070  5f 38 b9 6c 07 72 81 a6  fe af 43 a6 49 2d c4 ee  |_8.l.r....C.I-..|
00000080
alice $
alice $ file top_secret.enc
top_secret.enc: data
alice $

删除秘密消息的原始文件是安全的,这样确保任何痕迹都没有:

alice $ rm -f top_secret.txt

现在,Alice 需要再次使用 scp 命令将此加密文件通过网络发送给 Bob 的工作站。注意,即使文件被截获,其内容也会是加密的,因此内容不会被泄露:

alice $  scp top_secret.enc bob@bob-machine-or-ip:/path/

如果 Bob 使用常规方法尝试打开并查看加密的消息,他将无法看懂该消息:

bob $ ls -l top_secret.enc
-rw-r--r--. 1 bob bob 128 Mar 22 13:59 top_secret.enc
bob $
bob $ cat top_secret.enc
�s��uM)M&>��N��}dmCy92#1X�q?��v���M��@��E�~��1�k~&PU�VhHL�@^P��(��zi�M�4p�e��g+R�1�Ԁ���s�������q_8�lr����C�I-��bob $
bob $
bob $ hexdump -C top_secret.enc
00000000  9e 73 12 8f e3 75 4d 29  4d 26 3e bf 80 4e a0 c5  |.s...uM)M&>..N..|
00000010  7d 64 6d 43 79 39 32 23  31 58 ce 71 f3 ba 95 a6  |}dmCy92#1X.q....|
00000020  c0 c0 76 17 fb f7 bf 4d  ce fc 40 e6 f4 45 7f db  |[email protected]..|
00000030  7e ae c0 31 f8 6b 10 06  7e 26 50 55 b5 05 56 68  |~..1.k..~&PU..Vh|
00000040  48 4c eb 40 5e 50 fe 19  ea 28 a8 b8 7a 13 69 d7  |HL.@^P...(..z.i.|
00000050  4d b0 34 70 d8 65 d5 07  95 67 2b 52 ea 31 aa d4  |M.4p.e...g+R.1..|
00000060  80 b3 a8 ec a1 73 ed a7  f9 17 c3 13 d4 fa c1 71  |.....s.........q|
00000070  5f 38 b9 6c 07 72 81 a6  fe af 43 a6 49 2d c4 ee  |_8.l.r....C.I-..|
00000080
bob $

步骤 5:使用私钥解密文件

Bob 需要使用 OpenSSL 来解密消息,但是这次使用的是 -decrypt 命令行参数。他需要向工具程序提供以下信息:

  1. 加密的文件(从 Alice 那里得到)
  2. Bob 的私钥(用于解密,因为文件是用 Bob 的公钥加密的)
  3. 通过重定向保存解密输出的文件名
bob $ openssl rsautl -decrypt -inkey bob_private.pem -in top_secret.enc > top_secret.txt
Enter pass phrase for bob_private.pem:
bob $

现在,Bob 可以阅读 Alice 发送给他的秘密消息:

bob $ ls -l top_secret.txt
-rw-r--r--. 1 bob bob 15 Mar 22 14:02 top_secret.txt
bob $
bob $ cat top_secret.txt
vim or emacs ?
bob $

Bob 需要回复 Alice,因此他将秘密回复写在一个文件中:

bob $ echo "nano for life" > reply_secret.txt
bob $
bob $ cat reply_secret.txt
nano for life
bob $

步骤 6:使用其他密钥重复该过程

为了发送消息,Bob 采用和 Alice 相同的步骤,但是由于该消息是发送给 Alice 的,因此他需要使用 Alice 的公钥来加密文件:

bob $ openssl rsautl -encrypt -inkey alice_public.pem -pubin -in reply_secret.txt -out reply_secret.enc
bob $
bob $ ls -l reply_secret.enc
-rw-r--r--. 1 bob bob 128 Mar 22 14:03 reply_secret.enc
bob $
bob $ cat reply_secret.enc
�F݇��.4"f�1��\��{o԰$�M��I{5�|�\�l͂�e��Y�V��{�|!$c^a
                                                 �*Ԫ\vQ�Ϡ9����'��ٮsP��'��Z�1W�n��k���J�0�I;P8������&:bob $
bob $
bob $ hexdump -C ./reply_secret.enc
00000000  92 46 dd 87 04 bc a7 2e  34 22 01 66 1a 13 31 db  |.F......4".f..1.|
00000010  c4 5c b4 8e 7b 6f d4 b0  24 d2 4d 92 9b 49 7b 35  |.\..{o..$.M..I{5|
00000020  da 7c ee 5c bb 6c cd 82  f1 1b 92 65 f1 8d f2 59  |.|.\.l.....e...Y|
00000030  82 56 81 80 7b 89 07 7c  21 24 63 5e 61 0c ae 2a  |.V..{..|!$c^a..*|
00000040  d4 aa 5c 76 51 8d cf a0  39 04 c1 d7 dc f0 ad 99  |..\vQ...9.......|
00000050  27 ed 8e de d9 ae 02 73  50 e0 dd 27 13 ae 8e 5a  |'......sP..'...Z|
00000060  12 e4 9a 31 57 b3 03 6e  dd e1 16 7f 6b c0 b3 8b  |...1W..n....k...|
00000070  4a cf 30 b8 49 3b 50 38  e0 9f 84 f6 83 da 26 3a  |J.0.I;P8......&:|
00000080
bob $
bob $ # remove clear text secret message file
bob $ rm -f reply_secret.txt

Bob 通过 scp 将加密的文件发送至 Alice 的工作站:

$ scp reply_secret.enc alice@alice-machine-or-ip:/path/

如果 Alice 尝试使用常规工具去阅读加密的文本,她将无法理解加密的文本:

alice $
alice $ ls -l reply_secret.enc
-rw-r--r--. 1 alice alice 128 Mar 22 18:01 reply_secret.enc
alice $
alice $ cat reply_secret.enc
�F݇��.4"f�1��\��{o԰$�M��I{5�|�\�l͂�e��Y�V��{�|!$c^a
                                                 �*Ԫ\vQ�Ϡ9����'��ٮsP��'��Z�1W�n��k���J�0�I;P8������&:alice $
alice $
alice $
alice $ hexdump -C ./reply_secret.enc
00000000  92 46 dd 87 04 bc a7 2e  34 22 01 66 1a 13 31 db  |.F......4".f..1.|
00000010  c4 5c b4 8e 7b 6f d4 b0  24 d2 4d 92 9b 49 7b 35  |.\..{o..$.M..I{5|
00000020  da 7c ee 5c bb 6c cd 82  f1 1b 92 65 f1 8d f2 59  |.|.\.l.....e...Y|
00000030  82 56 81 80 7b 89 07 7c  21 24 63 5e 61 0c ae 2a  |.V..{..|!$c^a..*|
00000040  d4 aa 5c 76 51 8d cf a0  39 04 c1 d7 dc f0 ad 99  |..\vQ...9.......|
00000050  27 ed 8e de d9 ae 02 73  50 e0 dd 27 13 ae 8e 5a  |'......sP..'...Z|
00000060  12 e4 9a 31 57 b3 03 6e  dd e1 16 7f 6b c0 b3 8b  |...1W..n....k...|
00000070  4a cf 30 b8 49 3b 50 38  e0 9f 84 f6 83 da 26 3a  |J.0.I;P8......&:|
00000080
alice $

所以,她使用 OpenSSL 解密消息,只不过这次她提供了自己的私钥并将输出保存到文件中:

alice $ openssl rsautl -decrypt -inkey alice_private.pem -in reply_secret.enc > reply_secret.txt
Enter pass phrase for alice_private.pem:
alice $
alice $ ls -l reply_secret.txt
-rw-rw-r--. 1 alice alice 14 Mar 22 18:02 reply_secret.txt
alice $
alice $ cat reply_secret.txt
nano for life
alice $

了解 OpenSSL 的更多信息

OpenSSL 在加密界是真正的瑞士军刀。除了加密文件外,它还可以执行许多任务,你可以通过访问 OpenSSL 文档页面来找到使用它的所有方式,包括手册的链接、 《OpenSSL Cookbook》、常见问题解答等。要了解更多信息,尝试使用其自带的各种加密算法,看看它是如何工作的。


via: https://opensource.com/article/21/4/encryption-decryption-openssl

作者:Gaurav Kamathe 选题:lujun9972 译者:MjSeven 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

Grafana、Loki 和 Tempo 改用 AGPLv3 许可证

过去几年,多个知名的开源项目如 Elastic、Redis Labs 和 MongoDB 出于盈利考虑而修改许可证,切换到非自由的商业授权许可证(SSPL)。开发 Grafana 以及 Loki 和 Tempo 等开源项目的 Grafana Labs 公司决定不这么做,它宣布旗下核心开源项目采用的许可证从 Apache License 2.0 切换到 AGPL v3,允许其他人自由修改和提供服务,但修改的版本需要回馈上游。Grafana Labs 公司表示,它这么做是试图在开源和社区的“价值创造”以及商业化策略的“价值获取”上取得平衡。

这也是一个不错的尝试,就是不知道 AGPL 是否能适当的保护开源项目,并与商业组织取得合适的平衡。

明尼苏达大学开发者被禁止向 Linux 内核提供代码

明尼苏达大学的 Qiushi Wu(博士生)和 Kangjie Lu(助理教授)提交了一篇研究论文《通过伪装的提交在开源软件中隐蔽地引入漏洞》,以看似有益的提交实际上引入了其他关键问题。而根据最近 Linux 内核接到的一些补丁来看,他们选择了 Linux 内核项目来进行他们的实验。

负责维护 Linux 内核的格雷(GKH)是仅次于 Linus 的负责人,他对这种行为进行了强烈谴责!但是发送这些补丁的人认为这只是他们写的一个静态分析器提交的补丁,最多只是质量不佳。格雷认为这些是谎言,愤怒之下决定禁止该大学向 Linux 内核提交代码,并撤销了他们之前提交的补丁。

简直是够了,Linux 内核不是试验场,供任何人随意摆弄。

Google 资助开发 OpenSSL 的替代品 Rustls

许多 SSL/TLS 库由于是用 C 语言编写的,所以安全问题由来已久。通过使用 Rust 开发的 OpenSSL 替代品 Rustls,开发人员可以尽可能确保代码是内存安全的,这将大大减少安全问题的数量。

互联网安全研究组(ISRG)宣布,谷歌已经为 Rust 开发者提供了资金,以对 Rustls 进行改进。ISRG 将使用 Rustls 来使 Apache HTTP 服务器更加安全。

期待看到 Rustls 能证明 Rust 的成功。

通过 OpenSSL 深入了解密码学的细节:哈希值、数字签名、数字证书等。

本系列的第一篇文章通过 OpenSSL 库和命令行实用程序介绍了哈希、加密/解密、数字签名和数字证书。这第二篇文章将对细节进行深入探讨。让我们从计算中无处不在的哈希开始,并考虑是什么使哈希函数具备密码学意义

密码学哈希

OpenSSL 源代码的下载页面包含了一个带有最新版本的表格。每个版本都有两个 哈希值 hash :160 位 SHA1 和 256 位 SHA256。这些值可以用来验证下载的文件是否与存储库中的原始文件相匹配:下载者在本地重新计算下载文件的哈希值,然后将结果与原始文件进行比较。现代系统有计算这种哈希值的实用程序。例如,Linux 有 md5sumsha256sum。OpenSSL 本身也提供了类似的命令行实用程序。

哈希值被用于计算的许多领域。例如,比特币区块链使用 SHA256 哈希值作为区块标识符。挖比特币就是生成一个低于指定阈值的 SHA256 哈希值,也就是至少有 N 个前导零的哈希值。(N 的值可以上升或下降,这取决于特定时间的挖矿生产力)。作为一个兴趣点,如今的矿机是为并行生成 SHA256 哈希值而设计的硬件集群。在 2018 年的一个高峰期,全球的比特币矿工每秒产生约 7500 万个 太哈希值 terahash —— 这真是一个不可思议的数字。

网络协议也使用哈希值(在这里通常叫做“ 校验和 checksum ”)来支持消息的完整性;也就是说,保证收到的消息与发送的消息是一样的。消息发送者计算消息的校验和,并将结果与消息一起发送。当消息到达时,接收方重新计算校验和。如果发送的校验和与重新计算的校验和不一致,那么消息在传输过程中可能出现了一些问题,或者发送的校验和出现了问题,或者两者都出现了问题。在这种情况下,应该重新发送消息和它的校验和,或者至少应该触发一个错误情况。(如 UDP 这样的低级网络协议不会理会校验和。)

哈希的其他例子大家都很熟悉。比如一个网站,要求用户用密码进行验证,用户在浏览器中输入密码,然后,他们通过 HTTPS 连接到服务器,密码从浏览器加密发送到服务器。一旦密码到达服务器,就会被解密,然后进行数据库表的查询。

在这个查询表中应该存储什么?存储密码本身是有风险的。风险要小得多的方式是存储一个由密码生成的哈希值,也许在计算哈希值之前“加一些 salt (额外的位)改善口味”。你的密码可能会被发送到 Web 服务器上,但网站可以向你保证,密码不会存储在那里。

哈希值还出现在安全的各个领域。例如, 基于哈希值的消息认证码 hash-based message authentication code HMAC)使用一个哈希值和一个秘密的 加密密钥 cryptographic key 来认证通过网络发送的消息。HMAC 码轻量级且易于在程序中使用,在 Web 服务中很受欢迎。一个 X509 数字证书包括一个称为 指纹 fingerprint 的哈希值,它可以方便证书验证。一个存放于内存中的 可信存储 truststore 可以实现为一个以这种指纹为键的查找表 —— 作为一个支持恒定查找时间的 哈希映射 hash map 。来自传入的证书的指纹可以与可信存储中的密钥进行比较,以确定是否匹配。

密码学哈希函数 cryptographic hash function 应该具有什么特殊属性?它应该是 单向 one-way 的,这意味着很难被逆转。一个加密哈希函数应该是比较容易计算的,但是计算它的反函数(将哈希值映射回输入位串的函数)在计算上应该是困难的。下面是一个描述,用 chf 作为加密哈希函数,我的密码 foobar 作为样本输入。

        +---+
foobar—>|chf|—>hash value ## 简单直接
        +--–+

相比之下,逆向操作是不可行的:

            +-----------+
hash value—>|chf inverse|—>foobar ## 棘手困难
            +-----------+

例如,回忆一下 SHA256 哈希函数。对于一个任意长度为 N > 0 的输入位串,这个函数会生成一个 256 位的固定长度的哈希值;因此,这个哈希值甚至不会反映出输入位串的长度 N,更不用说字符串中每个位的值了。顺便说一下,SHA256 不容易受到 长度扩展攻击 length extension attack 。唯一有效的逆向工程方法是通过蛮力搜索将计算出的 SHA256 哈希值逆向返回到输入位串,这意味着需要尝试所有可能的输入位串,直到找到与目标哈希值匹配的位串。这样的搜索在 SHA256 这样一个完善的加密哈希函数上是不可行的。

现在,最后一个回顾的知识点是 有序 in order 。加密哈希值是统计学上的唯一,而不是无条件的唯一,这意味着两个不同的输入位串产生相同的哈希值是不太可能的,但也不是不可能的 —— 这称之为 碰撞 collision 生日问题提供了一个很好的反直觉的碰撞例子。对各种哈希算法的 抗碰撞性 collision resistance 有着广泛的研究。例如,MD5(128 位哈希值)在大约 2 21 次哈希之后,抗碰撞能力就会崩溃。对于 SHA1(160 位哈希值),大约在 2 61 次哈希后开始崩溃。

对于 SHA256 的抗碰撞能力的剖析,目前还没有一个很好的估计。这个事实并不奇怪。SHA256 有 2 256 个不同的哈希值范围,这个数字的十进制表示法有 78 位之多!那么,SHA256 哈希会不会发生碰撞呢?当然可能,但可能性极小。

在下面的命令行示例中,有两个输入文件被用作位串源:hashIn1.txthashIn2.txt。第一个文件包含 abc,第二个文件包含 1a2b3c

为了便于阅读,这些文件包含的是文本,但也可以使用二进制文件代替。

在命令行(百分号 % 是提示符)使用 Linux sha256sum 实用程序对这两个文件进行处理产生以下哈希值(十六进制):

% sha256sum hashIn1.txt
9e83e05bbf9b5db17ac0deec3b7ce6cba983f6dc50531c7a919f28d5fb3696c3 hashIn1.txt

% sha256sum hashIn2.txt
3eaac518777682bf4e8840dd012c0b104c2e16009083877675f00e995906ed13 hashIn2.txt

OpenSSL 哈希对应的结果与预期相同:

% openssl dgst -sha256 hashIn1.txt
SHA256(hashIn1.txt)= 9e83e05bbf9b5db17ac0deec3b7ce6cba983f6dc50531c7a919f28d5fb3696c3

% openssl dgst -sha256 hashIn2.txt
SHA256(hashIn2.txt)= 3eaac518777682bf4e8840dd012c0b104c2e16009083877675f00e995906ed13

这种对密码学哈希函数的研究,为我们仔细研究数字签名及其与密钥对的关系奠定了基础。

数字签名

顾名思义, 数字签字 digital signature 可以附在文件或其他一些电子 工件 artifact (如程序)上,以证明其真实性。因此,这种签名类似于纸质文件上的手写签名。验证数字签名就是要确认两件事:第一,被担保的工件在签名被附上后没有改变,因为它部分是基于文件的加密学哈希值。第二,签名属于一个人(例如 Alice),只有她才能获得一对密钥中的私钥。顺便说一下,对代码(源码或编译后的代码)进行数字签名已经成为程序员的普遍做法。

让我们来了解一下数字签名是如何创建的。如前所述,没有公钥和私钥对就没有数字签名。当使用 OpenSSL 创建这些密钥时,有两个独立的命令:一个是创建私钥,另一个是从私钥中提取匹配的公钥。这些密钥对用 base64 编码,在这个过程中可以指定它们的大小。

私钥 private key 由数值组成,其中两个数值(一个 模数 modulus 和一个 指数 exponent )组成了公钥。虽然私钥文件包含了 公钥 public key ,但提取出来的公钥并不会透露相应私钥的值。

因此,生成的带有私钥的文件包含了完整的密钥对。将公钥提取到自己的文件中是很实用的,因为这两把钥匙有不同的用途,而这种提取方式也将私钥可能被意外公开的危险降到最低。

接下来,这对密钥的私钥被用来生成目标工件(如电子邮件)的哈希值,从而创建签名。在另一端,接收者的系统使用这对密钥的公钥来验证附在工件上的签名。

现在举个例子。首先,用 OpenSSL 生成一个 2048 位的 RSA 密钥对:

openssl genpkey -out privkey.pem -algorithm rsa 2048

在这个例子中,我们可以舍去 -algorithm rsa 标志,因为 genpkey 默认为 RSA 类型。文件的名称(privkey.pem)是任意的,但是 隐私增强邮件 Privacy Enhanced Mail (PEM)扩展名 .pem 是默认 PEM 格式的惯用扩展名。(如果需要的话,OpenSSL 有命令可以在各种格式之间进行转换。)如果需要更大的密钥大小(例如 4096),那么最后一个参数 2048 可以改成 4096。这些大小总是二的幂。

下面是产生的 privkey.pem 文件的一个片断,它是 base64 编码的:

-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANnlAh4jSKgcNj/Z
JF4J4WdhkljP2R+TXVGuKVRtPkGAiLWE4BDbgsyKVLfs2EdjKL1U+/qtfhYsqhkK
...
-----END PRIVATE KEY-----

接下来的命令就会从私钥中提取出这对密钥的公钥:

openssl rsa -in privkey.pem -outform PEM -pubout -out pubkey.pem

由此产生的 pubkey.pem 文件很小,可以在这里完整地显示出来:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZ5QIeI0ioHDY/2SReCeFnYZJY
z9kfk11RrilUbT5BgIi1hOAQ24LMilS37NhHYyi9VPv6rX4WLKoZCmkeYaWk/TR5
4nbH1E/AkniwRoXpeh5VncwWMuMsL5qPWGY8fuuTE27GhwqBiKQGBOmU+MYlZonO
O0xnAKpAvysMy7G7qQIDAQAB
-----END PUBLIC KEY-----

现在,有了密钥对,数字签名就很容易了 —— 在本例中,源文件 client.c 是要签名的工件:

openssl dgst -sha256 -sign privkey.pem -out sign.sha256 client.c

client.c 源文件的摘要是 SHA256,私钥在前面创建的 privkey.pem 文件中。由此产生的二进制签名文件是 sign.sha256,这是一个任意的名字。要得到这个文件的可读版本(比如 base64),后续命令是:

openssl enc -base64 -in sign.sha256 -out sign.sha256.base64

文件 sign.sha256.base64 现在包含如下内容:

h+e+3UPx++KKSlWKIk34fQ1g91XKHOGFRmjc0ZHPEyyjP6/lJ05SfjpAJxAPm075
VNfFwysvqRGmL0jkp/TTdwnDTwt756Ej4X3OwAVeYM7i5DCcjVsQf5+h7JycHKlM
o/Jd3kUIWUkZ8+Lk0ZwzNzhKJu6LM5KWtL+MhJ2DpVc=

或者,可执行文件 client 也可以被签名,由此产生的 base64 编码签名将如预期的不同:

VMVImPgVLKHxVBapJ8DgLNJUKb98GbXgehRPD8o0ImADhLqlEKVy0HKRm/51m9IX
xRAN7DoL4Q3uuVmWWi749Vampong/uT5qjgVNTnRt9jON112fzchgEoMb8CHNsCT
XIMdyaPtnJZdLALw6rwMM55MoLamSc6M/MV1OrJnk/g=

这一过程的最后一步是用公钥验证数字签名。作为验证的一个重要步骤,应重新计算用于签署工件(在本例中,是可执行的 client 程序)的哈希值,因为验证过程应表明工件在签署后是否发生了变化。

有两个 OpenSSL 命令用于这个目的。第一条命令是对 base64 签名进行解码。

openssl enc -base64 -d -in sign.sha256.base64 -out sign.sha256

第二条是核实签名:

openssl dgst -sha256 -verify pubkey.pem -signature sign.sha256 client

第二条命令的输出,应该是这样的:

Verified OK

为了了解验证失败时的情况,一个简短但有用的练习是将最后一个 OpenSSL 命令中的可执行的 client 文件替换为源文件 client.c,然后尝试验证。另一个练习是改变 client 程序,无论多么轻微,然后再试一次。

数字证书

数字证书 digital certificate 汇集了到目前为止所分析的各个部分:哈希值、密钥对、数字签名和加密/解密。生产级证书的第一步是创建一个 证书签名请求 certificate signing request (CSR),然后将其发送给 证书颁发机构 certificate authority (CA)。在 OpenSSL 的例子中,要做到这一点,请运行:

openssl req -out myserver.csr -new -newkey rsa:4096 -nodes -keyout myserverkey.pem

这个例子生成了一个 CSR 文档,并将该文档存储在文件 myserver.csr(base64 文本)中。这里的目的是:CSR 文档要求 CA 保证与指定域名相关联的身份,域名也就是 CA 所说的 通用名 common name (CN)。

尽管可以使用现有的密钥对,但这个命令也会生成一个新的密钥对。请注意,在诸如 myserver.csrmyserverkey.pem 等名称中使用 server 暗示了数字证书的典型用途:作为与 www.google.com 等域名相关的 Web 服务器的身份担保。

然而,无论数字证书如何使用,同样使用这个命令都会创建一个 CSR。它还会启动一个问题/回答的交互式会话,提示有关域名的相关信息,以便与请求者的数字证书相连接。这个交互式会话可以通过在命令中提供基本的信息,用反斜杠来续行一步完成。-subj 标志提供了所需的信息。

% openssl req -new \
-newkey rsa:2048 -nodes -keyout privkeyDC.pem \
-out myserver.csr \
-subj "/C=US/ST=Illinois/L=Chicago/O=Faulty Consulting/OU=IT/CN=myserver.com"

产生的 CSR 文件在发送给 CA 之前可以进行检查和验证。这个过程可以创建具有所需格式(如 X509)、签名、有效期等的数字证书。

openssl req -text -in myserver.csr -noout -verify

这是输出的一个片断:

verify OK
Certificate Request:
Data:
Version: 0 (0x0)
Subject: C=US, ST=Illinois, L=Chicago, O=Faulty Consulting, OU=IT, CN=myserver.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:ba:36:fb:57:17:65:bc:40:30:96:1b:6e:de:73:
…
Exponent: 65537 (0x10001)
Attributes:
a0:00
Signature Algorithm: sha256WithRSAEncryption
…

自签证书

在开发 HTTPS 网站的过程中,手头有一个不用经过 CA 流程的数字证书是很方便的。在 HTTPS 握手的认证阶段, 自签证书 self-signed certificate 就能满足要求,尽管任何现代浏览器都会警告说这样的证书毫无价值。继续这个例子,自签证书的 OpenSSL 命令(有效期为一年,使用 RSA 公钥)如下:

openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:4096 -keyout myserver.pem -out myserver.crt

下面的 OpenSSL 命令呈现了生成的证书的可读版本:

openssl x509 -in myserver.crt -text -noout

这是自签证书的部分输出:

Certificate:
Data:
Version: 3 (0x2)
Serial Number: 13951598013130016090 (0xc19e087965a9055a)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, ST=Illinois, L=Chicago, O=Faulty Consulting, OU=IT, CN=myserver.com
Validity
Not Before: Apr 11 17:22:18 2019 GMT
Not After : Apr 10 17:22:18 2020 GMT
Subject: C=US, ST=Illinois, L=Chicago, O=Faulty Consulting, OU=IT, CN=myserver.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (4096 bit)
Modulus:
00:ba:36:fb:57:17:65:bc:40:30:96:1b:6e:de:73:
...
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
3A:32:EF:3D:EB:DF:65:E5:A8:96:D7:D7:16:2C:1B:29:AF:46:C4:91
X509v3 Authority Key Identifier:
keyid:3A:32:EF:3D:EB:DF:65:E5:A8:96:D7:D7:16:2C:1B:29:AF:46:C4:91

        X509v3 Basic Constraints:
            CA:TRUE
Signature Algorithm: sha256WithRSAEncryption
     3a:eb:8d:09:53:3b:5c:2e:48:ed:14:ce:f9:20:01:4e:90:c9:
     ...

如前所述,RSA 私钥包含的值是用来生成公钥的。但是,给定的公钥不会泄露匹配的私钥。关于底层数学理论的介绍,见 https://simple.wikipedia.org/wiki/RSA_algorithm

数字证书与用于生成该证书的密钥对之间存在着重要的对应关系,即使证书只是自签的:

  • 数字证书包含构成公钥的指数和模数值。这些值是最初生成的 PEM 文件中密钥对的一部分,在本例中,是文件 myserver.pem
  • 指数 exponent 几乎总是 65,537(如本例中),所以可以忽略。
  • 密钥对的 模数 modulus 应该与数字证书的模数相匹配。

模数是一个很大的值,为了便于阅读,可以进行哈希处理。下面是两个 OpenSSL 命令,它们检查相同的模数,从而确认数字证书是基于 PEM 文件中的密钥对。

% openssl x509 -noout -modulus -in myserver.crt | openssl sha1 ## 证书中的模数
(stdin)= 364d21d5e53a59d482395b1885aa2c3a5d2e3769

% openssl rsa -noout -modulus -in myserver.pem | openssl sha1 ## 密钥中的模数
(stdin)= 364d21d5e53a59d482395b1885aa2c3a5d2e3769

所产生的哈希值匹配,从而确认数字证书是基于指定的密钥对。

回到密钥分发问题上

让我们回到第一部分末尾提出的一个问题:client 程序和 Google Web 服务器之间的 TLS 握手。握手协议有很多种,即使是用在 client 例子中的 Diffie-Hellman 版本也有不同的方式。尽管如此,client 例子遵循了一个共同的模式。

首先,在 TLS 握手过程中,client 程序和 Web 服务器就 加密套件 cipher suite 达成一致,其中包括要使用的算法。在本例中,该套件是 ECDHE-RSA-AES128-GCM-SHA256

现在值得关注的两个要素是 RSA 密钥对算法和 AES128 块密码,用于在握手成功的情况下对消息进行加密和解密。关于加密/解密,这个过程有两种流派: 对称 symmetric 非对称 asymmetric 。在对称流派中,加密和解密使用的是相同的密钥,这首先就引出了 密钥分发问题 key distribution problem 。如何将密钥安全地分发给双方?在非对称流派中,一个密钥用于加密(在这种情况下,是 RSA 公钥),但另一个密钥用于解密(在这种情况下,是来自同一对密钥的 RSA 私钥)。

client 程序拥有来认证证书的 Google Web 服务器的公钥,而 Web 服务器拥有来自同一对密钥的私钥。因此,client 程序可以向 Web 服务器发送加密信息,而 Web 服务器可以单独对该通信进行解密。

在 TLS 的情况下,对称方式有两个显著的优势:

  • client 程序与 Google Web 服务器之间的互动中,认证是单向的。Google Web 服务器向 client 程序发送三张证书,但 client 程序并没有向 Web 服务器发送证书,因此,Web 服务器没有来自客户端的公钥,无法加密发给客户端的消息。
  • 使用 AES128 的对称加密/解密比使用 RSA 密钥的非对称加密/解密快了近千倍

TLS 握手将两种加密/解密方式巧妙地结合在一起。在握手过程中,client 程序会生成随机位,即所谓的 预主密 pre-master secret (PMS)。然后,client 程序用服务器的公钥对 PMS 进行加密,并将加密后的 PMS 发送给服务器,服务器再用 RSA 密钥对的私钥对 PMS 信息进行解密:

              +-------------------+ encrypted PMS  +--------------------+
client PMS--->|server’s public key|--------------->|server’s private key|--->server PMS
              +-------------------+                +--------------------+

在这个过程结束时,client 程序和 Google Web 服务器现在拥有相同的 PMS 位。每一方都使用这些位生成一个 主密码 master secret ,并立即生成一个称为 会话密钥 session key 的对称加密/解密密钥。现在有两个不同但等价的会话密钥,连接的每一方都有一个。在 client 的例子中,会话密钥是 AES128 类的。一旦在 client 程序和 Google Web 服务器两边生成了会话密钥,每一边的会话密钥就会对双方的对话进行保密。如果任何一方(例如,client 程序)或另一方(在这种情况下,Google Web 服务器)要求重新开始握手,握手协议(如 Diffie-Hellman)允许整个 PMS 过程重复进行。

总结

在命令行上说明的 OpenSSL 操作也可以通过底层库的 API 完成。这两篇文章重点使用了这个实用程序,以保持例子的简短,并专注于加密主题。如果你对安全问题感兴趣,OpenSSL 是一个很好的开始地方,并值得深入研究。


via: https://opensource.com/article/19/6/cryptography-basics-openssl-part-2

作者:Marty Kalin 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

介绍

OpenSSL 是一个多功能的命令行工具,可以用于与 公钥基础设施 Public Key Infrastructure (PKI)和 HTTPS(HTTP over TLS)相关的大量任务。这本小抄风格的指南提供了 OpenSSL 命令的快速参考,这些命令在常见的日常场景中非常有用。这包括生成私钥、 证书签署请求 certificate signing request (CSR)和证书格式转换的 OpenSSL 示例,但它并没有涵盖 OpenSSL 的所有用途。

如何使用本指南

  • 如果你不熟悉证书签署请求(CSR),请阅读第一部分。
  • 除了第一部分,本指南采用了简单的小抄格式:自带了命令行代码片段。
  • 跳到与你准备完成的任务相关的任何部分。
  • 大多数命令都是单行的,为了清晰起见,已经扩展到多行(使用 \ 符号)。

关于证书签署请求(CSR)

如果你想从 证书颁发机构 certificate authority (CA)那里获得 SSL 证书,你必须生成一个 证书签署请求 certificate signing request (CSR)。一个 CSR 主要是由一个密钥对的公钥和一些附加信息组成。当证书被签署时,这两部分都会被插入到证书中。

每当你生成一个 CSR 时,你会被提示提供有关证书的信息。这些信息被称为 区分名称 Distinguised Name (DN)。DN 中的一个重要字段是 通用名称 Common Name (CN),它应该是你打算使用证书的主机的 完全合格域名 Fully Qualified Domain Name (FQDN)。当创建 CSR 时,也可以通过命令行或文件传递信息来跳过交互式提示。

DN 中的其他项目提供了有关你的业务或组织的附加信息。如果你是从证书机构购买 SSL 证书,通常要求这些附加字段(如“ 组织 Organization ”)准确地反映你的组织的详细信息。

下面是一个 CSR 信息提示的例子:

---
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:New York
Locality Name (eg, city) []:Brooklyn
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example Brooklyn Company
Organizational Unit Name (eg, section) []:Technology Division
Common Name (e.g. server FQDN or YOUR name) []:examplebrooklyn.com
Email Address []:

如果你想非交互式地回答 CSR 信息提示,你可以通过在任何请求 CSR 信息的 OpenSSL 命令中添加 -subj 选项来实现。这里是该选项的一个例子,使用上面代码块中显示的相同信息:

-subj "/C=US/ST=New York/L=Brooklyn/O=Example Brooklyn Company/CN=examplebrooklyn.com"

现在你已经了解了 CSR,可以自由跳转到本指南中涵盖你的 OpenSSL 需求的任何一节。

生成 CSR

本节介绍了与生成 CSR(以及私钥,如果它们还不存在的话)有关的 OpenSSL 命令。CSR 可以用来向证书颁发机构请求 SSL 证书。

请记住,你可以通过上一节中提到的 -subj 选项非交互式地添加 CSR 信息。

生成一个私钥和一个 CSR

如果你想使用 HTTPS(HTTP over TLS)来保护你的 Apache HTTP 或 Nginx Web 服务器的安全,并且你想使用一个证书颁发机构(CA)来颁发 SSL 证书,那么就使用这个方法。生成的 CSR 可以发送给 CA,请求签发由 CA 签名的 SSL 证书。如果你的 CA 支持 SHA-2,请添加 -sha256 选项,用 SHA-2 签署 CSR。

这条命令从头开始创建一个 2048 位的私钥(domain.key)和一个 CSR(domain.csr):

openssl req \
       -newkey rsa:2048 -nodes -keyout domain.key \
       -out domain.csr

回答 CSR 信息提问,完成该过程。

选项 -newkey rsa:2048 指定密钥应该是 2048 位,使用 RSA 算法生成。选项 -nodes 指定私钥没有用密码加密。这里没有包含 -new 选项,而是隐含在其中,表示正在生成一个 CSR。

从现有的私钥中生成一个 CSR

如果你已经有了私钥,并想用它向 CA 申请证书,请使用这个方法。

该命令基于现有的私钥(domain.key)创建一个新的 CSR(domain.csr):

openssl req \
       -key domain.key \
       -new -out domain.csr

回答 CSR 信息提问,完成该过程。

选项 -key 指定一个现有的私钥(domain.key),它将被用来生成一个新的 CSR。选项 -new 表示正在生成一个 CSR。

从现有的证书和私钥生成 CSR

如果你想更新现有的证书,但由于某些原因,你或你的 CA 没有原始的 CSR,请使用这个方法。基本上可以省去重新输入 CSR 信息的麻烦,因为它是从现有证书中提取信息的。

该命令基于现有的证书(domain.crt)和私钥(domain.key)创建一个新的 CSR(domain.csr):

openssl x509 \
       -in domain.crt \
       -signkey domain.key \
       -x509toreq -out domain.csr

选项 -x509toreq 指定你使用一个 X509 证书来制作 CSR。

生成 SSL 证书

如果你想使用 SSL 证书来确保服务的安全,但你不需要 CA 签名的证书,一个有效的(和免费的)解决方案是签署你自己的证书。

你可以自己签发的一种常见证书是 自签证书 self-signed certificate 。自签证书是用自己的私钥签署的证书。自签证书和 CA 签名证书一样可以用来加密数据,但是你的用户会显示一个警告,说这个证书不被他们的计算机或浏览器信任。因此,只有当你不需要向用户证明你的服务身份时,才可以使用自签名证书(例如非生产或非公开服务器)。

本节介绍与生成自签名证书相关的 OpenSSL 命令。

生成自签证书

如果你想使用 HTTPS(HTTP over TLS)来保护你的 Apache HTTP 或 Nginx Web 服务器,并且你不需要你的证书由 CA 签名,那么就使用这个方法。

这个命令可以从头开始创建一个 2048 位的私钥(domain.key)和一个自签证书(domain.crt):

openssl req \
       -newkey rsa:2048 -nodes -keyout domain.key \
       -x509 -days 365 -out domain.crt

回答 CSR 信息提问,完成该过程。

选项 -x509 告诉 req 子命令创建一个自签名的证书。-days 365 选项指定证书的有效期为 365 天。它会生成一个临时的 CSR,以收集与证书相关的信息。

从现有私钥生成自签名证书

如果你已经有了一个私钥,并且你想用它来生成一个自签证书,请使用这个方法。

这条命令可以从现有的私钥(domain.key)中创建一个自签证书(domain.crt):

openssl req \
       -key domain.key \
       -new \
       -x509 -days 365 -out domain.crt

回答 CSR 信息提问,完成该过程。

选项 -x509 告诉 req 子命令创建一个自签证书。-days 365 选项指定证书的有效期为 365 天。选项 -new 启用 CSR 信息提问。

从现有的私钥和 CSR 生成自签证书

如果你已经有了私钥和 CSR,并且你想用它们生成一个自签证书,请使用这个方法。

这条命令将从现有的私钥(domain.key)和(domain.csr)中创建一个自签证书(domain.crt)。

openssl x509 \
       -signkey domain.key \
       -in domain.csr \
       -req -days 365 -out domain.crt

选项 -days 365 指定证书的有效期为 365 天。

查看证书

证书和 CSR 文件是以 PEM 格式编码的,不适合被人读取。

本节介绍的 OpenSSL 命令将输出 PEM 编码文件的实际条目。

查看 CSR 条目

该命令允许你查看和验证纯文本的 CSR(domain.csr)的内容:

openssl req \  
       -text -noout -verify \  
       -in domain.csr

查看证书条目

该命令允许你查看纯文本证书(domain.crt)的内容:

openssl x509 \  
       -text -noout \  
       -in domain.crt

验证证书由 CA 签署

使用此命令验证证书(domain.crt)是否由特定的 CA 证书(ca.crt)签署:

openssl verify \  
       -verbose -CAFile ca.crt \  
       domain.crt

私钥

本节介绍了用于创建和验证私钥的 OpenSSL 命令。

创建私钥

使用该命令创建一个受密码保护的 2048 位私钥(domain.key):

openssl genrsa \  
       -des3 -out domain.key 2048

在提示时输入密码以完成该过程。

验证私钥

使用此命令检查私钥(domain.key)是否为有效密钥:

openssl rsa \  
       -check -in domain.key

如果你的私钥已经加密,系统会提示你输入它的密码,成功后,未加密的密钥会在终端上输出。

验证私钥是否与证书和 CSR 匹配

使用这些命令来验证私钥(domain.key)是否匹配证书(domain.crt)和 CSR(domain.csr):

openssl rsa  -noout -modulus -in domain.key | openssl md5
openssl x509 -noout -modulus -in domain.crt | openssl md5
openssl req  -noout -modulus -in domain.csr | openssl md5

如果每条命令的输出都是相同的,那么私钥、证书和 CSR 就极有可能是相关的。

加密私钥

这需要一个未加密的私钥(unencrypted.key),并输出它的加密版本(encrypted.key):

openssl rsa -des3 \
       -in unencrypted.key \
       -out encrypted.key

输入你所需的密码,以加密私钥。

解密私钥

这需要一个加密的私钥(encrypted.key),并输出一个解密的版本(decrypted.key):

openssl rsa \
       -in encrypted.key \
       -out decrypted.key

在提示时,输入加密密钥的密码。

转换证书格式

我们一直在使用的所有证书都是 ASCII 码 PEM 编码的 X.509 证书。还有很多其他的证书编码和容器类型;一些应用程序喜欢某些格式而不是其他格式。此外,这些格式中的许多格式可以在一个文件中包含多个项目,如私钥、证书和 CA 证书。

OpenSSL 可以用来将证书在则西格式间转换。本节将介绍一些可能的转换。

将 PEM 转换为 DER

如果要将 PEM 编码的证书(domain.crt)转换为 DER 编码的证书(domain.der),即二进制格式,请使用此命令:

openssl x509 \
       -in domain.crt \
       -outform der -out domain.der

DER 格式通常与 Java 一起使用。

将 DER 转换为 PEM

如果要将 DER 编码的证书(domain.der)转换为 PEM 编码的证书(domain.crt),请使用此命令:

openssl x509 \
       -inform der -in domain.der \
       -out domain.crt

将 PEM 转换为 PKCS7

如果你想把 PEM 证书(domain.crtca-chain.crt)添加到 PKCS7 文件(domain.p7b)中,请使用该命令:

openssl crl2pkcs7 -nocrl \
       -certfile domain.crt \
       -certfile ca-chain.crt \
       -out domain.p7b

请注意,你可以使用一个或多个 -certfile 选项来指定要添加到 PKCS7 文件中的证书。

PKCS7 文件,也被称为 P7B,通常用于 Java Keystores 和 Microsoft IIS(Windows)。它们是 ASCII 文件,可以包含证书和 CA 证书。

将 PKCS7 转换为 PEM

如果你想将 PKCS7 文件(domain.p7b)转换为 PEM 文件,请使用该命令:

openssl pkcs7 \
       -in domain.p7b \
       -print_certs -out domain.crt

请注意,如果你的 PKCS7 文件中有多个项目(如证书和 CA 中间证书),创建的 PEM 文件将包含其中的所有项目。

将 PEM 转换为 PKCS12

如果你想使用私钥(domain.key)和证书(domain.crt),并将它们组合成一个 PKCS12 文件(domain.pfx),请使用这个命令:

openssl pkcs12 \
       -inkey domain.key \
       -in domain.crt \
       -export -out domain.pfx

系统会提示你输入导出密码,你可以留空。请注意,在这种情况下,你可以通过将多个证书连接到一个 PEM 文件(domain.crt)中来添加一个证书链到 PKCS12 文件中。

PKCS12 文件,也被称为 PFX 文件,通常用于在 Micrsoft IIS(Windows)中导入和导出证书链。

将 PKCS12 转换为 PEM

如果你想转换 PKCS12 文件(domain.pfx)并将其转换为 PEM 格式(domain.combined.crt),请使用此命令:

openssl pkcs12 \
       -in domain.pfx \
       -nodes -out domain.combined.crt

请注意,如果你的 PKCS12 文件中有多个项目(如证书和私钥),创建的 PEM 文件将包含其中的所有项目。

OpenSSL 版本

openssl version 命令可以用来检查你正在运行的版本。你正在运行的 OpenSSL 版本,以及编译时使用的选项会影响到你可以使用的功能(有时也会影响到命令行选项)。

下面的命令显示了你正在运行的 OpenSSL 版本,以及它被编译时的所有选项:

openssl version -a

本指南是使用具有如下细节的 OpenSSL 二进制文件编写的(参见前面命令的输出):

OpenSSL 1.0.1f 6 Jan 2014
built on: Mon Apr  7 21:22:23 UTC 2014
platform: debian-amd64
options:  bn(64,64) rc4(16x,int) des(idx,cisc,16,int) blowfish(idx)
compiler: cc -fPIC -DOPENSSL_PIC -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -m64 -DL_ENDIAN -DTERMIO -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -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
OPENSSLDIR: "/usr/lib/ssl"

总结

这应该涵盖了大多数人如何使用 OpenSSL 来处理 SSL 证书的情况!它还有很多其他的用途,在这里没有介绍,所以请在评论中随时询问或建议其他用途。

如果你在使用这些命令时遇到了问题,请一定要评论(并附上你的 OpenSSL 版本输出)。


via: https://www.digitalocean.com/community/tutorials/openssl-essentials-working-with-ssl-certificates-private-keys-and-csrs

作者:Mitchell Anicas 选题:wxy 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

想要入门密码学的基础知识,尤其是有关 OpenSSL 的入门知识吗?继续阅读。

本文是使用 OpenSSL 的密码学基础知识的两篇文章中的第一篇,OpenSSL 是在 Linux 和其他系统上流行的生产级库和工具包。(要安装 OpenSSL 的最新版本,请参阅这里。)OpenSSL 实用程序可在命令行使用,程序也可以调用 OpenSSL 库中的函数。本文的示例程序使用的是 C 语言,即 OpenSSL 库的源语言。

本系列的两篇文章涵盖了加密哈希、数字签名、加密和解密以及数字证书。你可以从我的网站的 ZIP 文件中找到这些代码和命令行示例。

让我们首先回顾一下 OpenSSL 名称中的 SSL。

OpenSSL 简史

安全套接字层 Secure Socket Layer (SSL)是 Netscape 在 1995 年发布的一种加密协议。该协议层可以位于 HTTP 之上,从而为 HTTPS 提供了 S: 安全 secure 。SSL 协议提供了各种安全服务,其中包括两项在 HTTPS 中至关重要的服务:

  • 对等身份验证 Peer authentication (也称为相互质询):连接的每一边都对另一边的身份进行身份验证。如果 Alice 和 Bob 要通过 SSL 交换消息,则每个人首先验证彼此的身份。
  • 机密性 Confidentiality :发送者在通过通道发送消息之前先对其进行加密。然后,接收者解密每个接收到的消息。此过程可保护网络对话。即使窃听者 Eve 截获了从 Alice 到 Bob 的加密消息(即中间人攻击),Eve 会发现他无法在计算上解密此消息。

反过来,这两个关键 SSL 服务与其他不太受关注的服务相关联。例如,SSL 支持消息完整性,从而确保接收到的消息与发送的消息相同。此功能是通过哈希函数实现的,哈希函数也随 OpenSSL 工具箱一起提供。

SSL 有多个版本(例如 SSLv2 和 SSLv3),并且在 1999 年出现了一个基于 SSLv3 的类似协议 传输层安全性 Transport Layer Security (TLS)。TLSv1 和 SSLv3 相似,但不足以相互配合工作。不过,通常将 SSL/TLS 称为同一协议。例如,即使正在使用的是 TLS(而非 SSL),OpenSSL 函数也经常在名称中包含 SSL。此外,调用 OpenSSL 命令行实用程序以 openssl 开始。

除了 man 页面之外,OpenSSL 的文档是零零散散的,鉴于 OpenSSL 工具包很大,这些页面很难以查找使用。命令行和代码示例可以将主要主题集中起来。让我们从一个熟悉的示例开始(使用 HTTPS 访问网站),然后使用该示例来选出我们感兴趣的加密部分进行讲述。

一个 HTTPS 客户端

此处显示的 client 程序通过 HTTPS 连接到 Google:

/* compilation: gcc -o client client.c -lssl -lcrypto */
#include <stdio.h>
#include <stdlib.h>
#include <openssl/bio.h> /* BasicInput/Output streams */
#include <openssl/err.h> /* errors */
#include <openssl/ssl.h> /* core library */
#define BuffSize 1024

void report_and_exit(const char* msg) {
  perror(msg);
  ERR_print_errors_fp(stderr);
  exit(-1);
}

void init_ssl() {
  SSL_load_error_strings();
  SSL_library_init();
}

void cleanup(SSL_CTX* ctx, BIO* bio) {
  SSL_CTX_free(ctx);
  BIO_free_all(bio);
}

void secure_connect(const char* hostname) {
  char name[BuffSize];
  char request[BuffSize];
  char response[BuffSize];

  const SSL_METHOD* method = TLSv1_2_client_method();
  if (NULL == method) report_and_exit("TLSv1_2_client_method...");

  SSL_CTX* ctx = SSL_CTX_new(method);
  if (NULL == ctx) report_and_exit("SSL_CTX_new...");

  BIO* bio = BIO_new_ssl_connect(ctx);
  if (NULL == bio) report_and_exit("BIO_new_ssl_connect...");

  SSL* ssl = NULL;

  /* 链路 bio 通道,SSL 会话和服务器端点 */

  sprintf(name, "%s:%s", hostname, "https");
  BIO_get_ssl(bio, &ssl); /* 会话 */
  SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); /* 鲁棒性 */
  BIO_set_conn_hostname(bio, name); /* 准备连接 */

  /* 尝试连接 */
  if (BIO_do_connect(bio) <= 0) {
    cleanup(ctx, bio);
    report_and_exit("BIO_do_connect...");
  }

  /* 验证信任库,检查证书 */
  if (!SSL_CTX_load_verify_locations(ctx,
                                      "/etc/ssl/certs/ca-certificates.crt", /* 信任库 */
                                      "/etc/ssl/certs/")) /* 其它信任库 */
    report_and_exit("SSL_CTX_load_verify_locations...");

  long verify_flag = SSL_get_verify_result(ssl);
  if (verify_flag != X509_V_OK)
    fprintf(stderr,
            "##### Certificate verification error (%i) but continuing...\n",
            (int) verify_flag);

  /* 获取主页作为示例数据 */
  sprintf(request,
          "GET / HTTP/1.1\x0D\x0AHost: %s\x0D\x0A\x43onnection: Close\x0D\x0A\x0D\x0A",
          hostname);
  BIO_puts(bio, request);

  /* 从服务器读取 HTTP 响应并打印到输出 */
  while (1) {
    memset(response, '\0', sizeof(response));
    int n = BIO_read(bio, response, BuffSize);
    if (n <= 0) break; /* 0 代表流结束,< 0 代表有错误 */
  puts(response);
  }

  cleanup(ctx, bio);
}

int main() {
  init_ssl();

  const char* hostname = "www.google.com:443";
  fprintf(stderr, "Trying an HTTPS connection to %s...\n", hostname);
  secure_connect(hostname);

return 0;
}

可以从命令行编译和执行该程序(请注意 -lssl-lcrypto 中的小写字母 L):

gcc -o client client.c -lssl -lcrypto

该程序尝试打开与网站 www.google.com 的安全连接。在与 Google Web 服务器的 TLS 握手过程中,client 程序会收到一个或多个数字证书,该程序会尝试对其进行验证(但在我的系统上失败了)。尽管如此,client 程序仍继续通过安全通道获取 Google 主页。该程序取决于前面提到的安全工件,尽管在上述代码中只着重突出了数字证书。但其它工件仍在幕后发挥作用,稍后将对它们进行详细说明。

通常,打开 HTTP(非安全)通道的 C 或 C++ 的客户端程序将使用诸如文件描述符网络套接字之类的结构,它们是两个进程(例如,这个 client 程序和 Google Web 服务器)之间连接的端点。另一方面,文件描述符是一个非负整数值,用于在程序中标识该程序打开的任何文件类的结构。这样的程序还将使用一种结构来指定有关 Web 服务器地址的详细信息。

这些相对较低级别的结构不会出现在客户端程序中,因为 OpenSSL 库会将套接字基础设施和地址规范等封装在更高层面的安全结构中。其结果是一个简单的 API。下面首先看一下 client 程序示例中的安全性详细信息。

  • 该程序首先加载相关的 OpenSSL 库,我的函数 init_ssl 中对 OpenSSL 进行了两次调用:
SSL_load_error_strings();
SSL_library_init(); 
  • 下一个初始化步骤尝试获取安全上下文,这是建立和维护通往 Web 服务器的安全通道所需的信息框架。如对 OpenSSL 库函数的调用所示,在示例中使用了 TLS 1.2:
const SSL_METHOD* method = TLSv1_2_client_method(); /* TLS 1.2 */

如果调用成功,则将 method 指针被传递给库函数,该函数创建类型为 SSL_CTX 的上下文:

SSL_CTX* ctx = SSL_CTX_new(method);

client 程序会检查每个关键的库调用的错误,如果其中一个调用失败,则程序终止。

  • 现在还有另外两个 OpenSSL 工件也在发挥作用:SSL 类型的安全会话,从头到尾管理安全连接;以及类型为 BIO( 基本输入/输出 Basic Input/Output )的安全流,用于与 Web 服务器进行通信。BIO 流是通过以下调用生成的:
BIO* bio = BIO_new_ssl_connect(ctx);

请注意,这个最重要的上下文是其参数。BIO 类型是 C 语言中 FILE 类型的 OpenSSL 封装器。此封装器可保护 client 程序与 Google 的网络服务器之间的输入和输出流的安全。

  • 有了 SSL_CTXBIO,然后程序在 SSL 会话中将它们组合在一起。三个库调用可以完成工作:
BIO_get_ssl(bio, &ssl); /* 会话 */
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); /* 鲁棒性 */
BIO_set_conn_hostname(bio, name); /* 准备连接 */

安全连接本身是通过以下调用建立的:

BIO_do_connect(bio);

如果最后一个调用不成功,则 client 程序终止;否则,该连接已准备就绪,可以支持 client 程序与 Google Web 服务器之间的机密对话。

在与 Web 服务器握手期间,client 程序会接收一个或多个数字证书,以认证服务器的身份。但是,client 程序不会发送自己的证书,这意味着这个身份验证是单向的。(Web 服务器通常配置为需要客户端证书)尽管对 Web 服务器证书的验证失败,但 client 程序仍通过了连接到 Web 服务器的安全通道继续获取 Google 主页。

为什么验证 Google 证书的尝试会失败?典型的 OpenSSL 安装目录为 /etc/ssl/certs,其中包含 ca-certificates.crt 文件。该目录和文件包含着 OpenSSL 自带的数字证书,以此构成 信任库 truststore 。可以根据需要更新信任库,尤其是可以包括新信任的证书,并删除不再受信任的证书。

client 程序从 Google Web 服务器收到了三个证书,但是我的计算机上的 OpenSSL 信任库并不包含完全匹配的证书。如目前所写,client 程序不会通过例如验证 Google 证书上的数字签名(一个用来证明该证书的签名)来解决此问题。如果该签名是受信任的,则包含该签名的证书也应受信任。尽管如此,client 程序仍继续获取页面,然后打印出 Google 的主页。下一节将更详细地介绍这些。

客户端程序中隐藏的安全性

让我们从客户端示例中可见的安全工件(数字证书)开始,然后考虑其他安全工件如何与之相关。数字证书的主要格式标准是 X509,生产级的证书由诸如 Verisign 证书颁发机构 Certificate Authority (CA)颁发。

数字证书中包含各种信息(例如,激活日期和失效日期以及所有者的域名),也包括发行者的身份和数字签名(这是加密过的加密哈希值)。证书还具有未加密的哈希值,用作其标识指纹

哈希值来自将任意数量的二进制位映射到固定长度的摘要。这些位代表什么(会计报告、小说或数字电影)无关紧要。例如, 消息摘要版本 5 Message Digest version 5 (MD5)哈希算法将任意长度的输入位映射到 128 位哈希值,而 SHA1( 安全哈希算法版本 1 Secure Hash Algorithm version 1 )算法将输入位映射到 160 位哈希值。不同的输入位会导致不同的(实际上在统计学上是唯一的)哈希值。下一篇文章将会进行更详细的介绍,并着重介绍什么使哈希函数具有加密功能。

数字证书的类型有所不同(例如根证书、中间证书和最终实体证书),并形成了反映这些证书类型的层次结构。顾名思义,证书位于层次结构的顶部,其下的证书继承了根证书所具有的信任。OpenSSL 库和大多数现代编程语言都具有 X509 数据类型以及处理此类证书的函数。来自 Google 的证书具有 X509 格式,client 程序会检查该证书是否为 X509_V_OK

X509 证书基于 公共密钥基础结构 public-key infrastructure (PKI),其中包括的算法(RSA 是占主导地位的算法)用于生成密钥对:公共密钥及其配对的私有密钥。公钥是一种身份:Amazon 的公钥对其进行标识,而我的公钥对我进行标识。私钥应由其所有者负责保密。

成对出现的密钥具有标准用途。可以使用公钥对消息进行加密,然后可以使用同一个密钥对中的私钥对消息进行解密。私钥也可以用于对文档或其他电子工件(例如程序或电子邮件)进行签名,然后可以使用该对密钥中的公钥来验证签名。以下两个示例补充了一些细节。

在第一个示例中,Alice 将她的公钥分发给全世界,包括 Bob。然后,Bob 用 Alice 的公钥加密邮件,然后将加密的邮件发送给 Alice。用 Alice 的公钥加密的邮件将可以用她的私钥解密(假设是她自己的私钥),如下所示:

             +------------------+ encrypted msg  +-------------------+
Bob's msg--->|Alice's public key|--------------->|Alice's private key|---> Bob's msg
             +------------------+                +-------------------+

理论上可以在没有 Alice 的私钥的情况下解密消息,但在实际情况中,如果使用像 RSA 这样的加密密钥对系统,则在计算上做不到。

现在,第二个示例,请对文档签名以证明其真实性。签名算法使用密钥对中的私钥来处理要签名的文档的加密哈希:

                    +-------------------+
Hash of document--->|Alice's private key|--->Alice's digital signature of the document
                    +-------------------+

假设 Alice 以数字方式签署了发送给 Bob 的合同。然后,Bob 可以使用 Alice 密钥对中的公钥来验证签名:

                                             +------------------+
Alice's digital signature of the document--->|Alice's public key|--->verified or not
                                             +------------------+

假若没有 Alice 的私钥,就无法轻松伪造 Alice 的签名:因此,Alice 有必要保密她的私钥。

client 程序中,除了数字证书以外,这些安全性都没有明确展示。下一篇文章使用使用 OpenSSL 实用程序和库函数的示例填充更多详细的信息。

命令行的 OpenSSL

同时,让我们看一下 OpenSSL 命令行实用程序:特别是在 TLS 握手期间检查来自 Web 服务器的证书的实用程序。调用 OpenSSL 实用程序可以使用 openssl 命令,然后添加参数和标志的组合以指定所需的操作。

看看以下命令:

openssl list-cipher-algorithms

该输出是组成 加密算法套件 cipher suite 的相关算法的列表。下面是列表的开头,加了澄清首字母缩写词的注释:

AES-128-CBC ## Advanced Encryption Standard, Cipher Block Chaining
AES-128-CBC-HMAC-SHA1 ## Hash-based Message Authentication Code with SHA1 hashes
AES-128-CBC-HMAC-SHA256 ## ditto, but SHA256 rather than SHA1
...

下一条命令使用参数 s_client 将打开到 www.google.com 的安全连接,并在屏幕上显示有关此连接的所有信息:

openssl s_client -connect www.google.com:443 -showcerts

端口号 443 是 Web 服务器用于接收 HTTPS(而不是 HTTP 连接)的标准端口号。(对于 HTTP,标准端口为 80)Web 地址 www.google.com:443 也出现在 client 程序的代码中。如果尝试连接成功,则将显示来自 Google 的三个数字证书以及有关安全会话、正在使用的加密算法套件以及相关项目的信息。例如,这是开头的部分输出,它声明证书链即将到来。证书的编码为 base64:

Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google LLC/CN=www.google.com
 i:/C=US/O=Google Trust Services/CN=Google Internet Authority G3
-----BEGIN CERTIFICATE-----
MIIEijCCA3KgAwIBAgIQdCea9tmy/T6rK/dDD1isujANBgkqhkiG9w0BAQsFADBU
MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZpY2VzMSUw
...

诸如 Google 之类的主要网站通常会发送多个证书进行身份验证。

输出以有关 TLS 会话的摘要信息结尾,包括加密算法套件的详细信息:

SSL-Session:
    Protocol : TLSv1.2
    Cipher : ECDHE-RSA-AES128-GCM-SHA256
    Session-ID: A2BBF0E4991E6BBBC318774EEE37CFCB23095CC7640FFC752448D07C7F438573
...

client 程序中使用了协议 TLS 1.2,Session-ID 唯一地标识了 openssl 实用程序和 Google Web 服务器之间的连接。Cipher 条目可以按以下方式进行解析:

  • ECDHE 椭圆曲线 Diffie-Hellman(临时) Elliptic Curve Diffie Hellman Ephemeral )是一种用于管理 TLS 握手的高效的有效算法。尤其是,ECDHE 通过确保连接双方(例如,client 程序和 Google Web 服务器)使用相同的加密/解密密钥(称为会话密钥)来解决“密钥分发问题”。后续文章会深入探讨该细节。
  • RSA(Rivest Shamir Adleman)是主要的公共密钥密码系统,并以 1970 年代末首次描述了该系统的三位学者的名字命名。这个正在使用的密钥对是使用 RSA 算法生成的。
  • AES128 高级加密标准 Advanced Encryption Standard )是一种 块式加密算法 block cipher ,用于加密和解密 位块 blocks of bits 。(另一种算法是 流式加密算法 stream cipher ,它一次加密和解密一个位。)这个加密算法是对称加密算法,因为使用同一个密钥进行加密和解密,这首先引起了密钥分发问题。AES 支持 128(此处使用)、192 和 256 位的密钥大小:密钥越大,安全性越好。

通常,像 AES 这样的对称加密系统的密钥大小要小于像 RSA 这样的非对称(基于密钥对)系统的密钥大小。例如,1024 位 RSA 密钥相对较小,而 256 位密钥则当前是 AES 最大的密钥。

  • GCM 伽罗瓦计数器模式 Galois Counter Mode )处理在安全对话期间重复应用的加密算法(在这种情况下为 AES128)。AES128 块的大小仅为 128 位,安全对话很可能包含从一侧到另一侧的多个 AES128 块。GCM 非常有效,通常与 AES128 搭配使用。
  • SHA256 256 位安全哈希算法 Secure Hash Algorithm 256 bits )是我们正在使用的加密哈希算法。生成的哈希值的大小为 256 位,尽管使用 SHA 甚至可以更大。

加密算法套件正在不断发展中。例如,不久前,Google 使用 RC4 流加密算法(RSA 的 Ron Rivest 后来开发的 Ron’s Cipher 版本 4)。 RC4 现在有已知的漏洞,这大概部分导致了 Google 转换为 AES128。

总结

我们通过安全的 C Web 客户端和各种命令行示例对 OpenSSL 做了首次了解,使一些需要进一步阐明的主题脱颖而出。下一篇文章会详细介绍,从加密散列开始,到对数字证书如何应对密钥分发挑战为结束的更全面讨论。


via: https://opensource.com/article/19/6/cryptography-basics-openssl-part-1

作者:Marty Kalin 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

 title=

本篇中,Carla Schroder 会解释如何使用 OpenSSL 保护你的 Postfix/Dovecot 邮件服务器

上周,作为我们 OpenSSL 系列的一部分,我们学习了如何配置 Apache 以使用 OpenSSL 并强制所有会话使用 HTTPS。 今天,我们将使用 OpenSSL 保护我们的 Postfix/Dovecot 邮件服务器。这些示例基于前面的教程; 请参阅最后的参考资料部分,了解本系列中以前的所有教程的链接。

你需要配置 Postfix 以及 Dovecot 都使用 OpenSSL,我们将使用我们在OpenSSL 在 Apache 和 Dovecot 下的使用(一)中创建的密钥和证书。

Postfix 配置

你必须编辑 /etc/postfix/main.cf 以及 /etc/postfix/master.cf。实例的 main.cf 是完整的配置,基于我们先前的教程。替换成你自己的 OpenSSL 密钥和证书名以及本地网络地址。

compatibility_level=2
smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu/GNU)
biff = no
append_dot_mydomain = no

myhostname = localhost
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = $myhostname
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 192.168.0.0/24
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all

virtual_mailbox_domains = /etc/postfix/vhosts.txt
virtual_mailbox_base = /home/vmail
virtual_mailbox_maps = hash:/etc/postfix/vmaps.txt
virtual_minimum_uid = 1000
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_transport = lmtp:unix:private/dovecot-lmtp

smtpd_tls_cert_file=/etc/ssl/certs/test-com.pem
smtpd_tls_key_file=/etc/ssl/private/test-com.key
smtpd_use_tls=yes

smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_authenticated_header = yes

master.cf 取消 submission inet 部分的注释,并编辑 smtpd_recipient_restrictions

#submission inet n  -  y  -  - smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o milter_macro_daemon_name=ORIGINATING
  -o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
  -o smtpd_tls_wrappermode=no

完成后重新加载 Postfix:

$ sudo service postfix reload

Dovecot 配置

在我们以前的教程中,我们为 Dovecot 创建了一个单一配置文件 /etc/dovecot/dovecot.conf,而不是使用多个默认配置文件。这是一个基于我们以前的教程的完整配置。再说一次,使用你自己的 OpenSSL 密钥和证书,以及你自己的 userdb 的 home 文件:

protocols = imap pop3 lmtp
log_path = /var/log/dovecot.log
info_log_path = /var/log/dovecot-info.log
disable_plaintext_auth = no
mail_location = maildir:~/.Mail
pop3_uidl_format = %g
auth_mechanisms = plain

passdb {
  driver = passwd-file
  args = /etc/dovecot/passwd
}

userdb {
  driver = static
  args = uid=vmail gid=vmail home=/home/vmail/studio/%u
}

service lmtp {
 unix_listener /var/spool/postfix/private/dovecot-lmtp {
   group = postfix
   mode = 0600
   user = postfix
  }
}

protocol lmtp {
  postmaster_address = postmaster@studio
}

service lmtp {
  user = vmail
}

service auth {
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
        user=postfix
        group=postfix
  }
 }

ssl=required
ssl_cert = </etc/ssl/certs/test-com.pem
ssl_key = </etc/ssl/private/test-com.key

重启 Dovecot:

$ sudo service postfix reload

用 telnet 测试

就像我们以前一样,现在我们可以通过使用 telnet 发送消息来测试我们的设置。 但是等等,你说 telnet 不支持 TLS/SSL,那么这样怎么办呢?首先通过使用 openssl s_client 打开一个加密会话。openssl s_client 的输出将显示你的证书及其指纹和大量其它信息,以便你知道你的服务器正在使用正确的证书。会话建立后输入的命令都是不以数字开头的:

$ openssl s_client -starttls smtp -connect studio:25
CONNECTED(00000003)
[masses of output snipped]
    Verify return code: 0 (ok)
---
250 SMTPUTF8
EHLO studio
250-localhost
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-AUTH PLAIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250 SMTPUTF8
mail from: <[email protected]>
250 2.1.0 Ok
rcpt to: <alrac@studio>
250 2.1.5 Ok
data
354 End data with .subject: TLS/SSL test
Hello, we are testing TLS/SSL. Looking good so far.
.
250 2.0.0 Ok: queued as B9B529FE59
quit
221 2.0.0 Bye

你应该可以在邮件客户端中看到一条新邮件,并在打开时要求你验证 SSL 证书。你也可以使用 openssl s_client 来测试 Dovecot 的 POP3 和 IMAP 服务。此示例测试加密的 POP3,第 5 号消息是我们在 telnet(如上)中创建的:

$ openssl s_client -connect studio:995
CONNECTED(00000003)
[masses of output snipped]
    Verify return code: 0 (ok)
---
+OK Dovecot ready
user alrac@studio 
+OK
pass password
+OK Logged in.
list
+OK 5 messages:
1 499
2 504
3 514
4 513
5 565
.
retr 5
+OK 565 octets
Return-Path: <[email protected]>
Delivered-To: alrac@studio
Received: from localhost
        by studio.alrac.net (Dovecot) with LMTP id y8G5C8aablgKIQAAYelYQA
        for <alrac@studio>; Thu, 05 Jan 2017 11:13:10 -0800
Received: from studio (localhost [127.0.0.1])
        by localhost (Postfix) with ESMTPS id B9B529FE59
        for <alrac@studio>; Thu,  5 Jan 2017 11:12:13 -0800 (PST)
subject: TLS/SSL test
Message-Id: <20170105191240.B9B529FE59@localhost>
Date: Thu,  5 Jan 2017 11:12:13 -0800 (PST)
From: [email protected]

Hello, we are testing TLS/SSL. Looking good so far.
.
quit
+OK Logging out.
closed

现在做什么?

现在你有一个功能良好的,具有合适的 TLS/SSL 保护的邮件服务器了。我鼓励你深入学习 Postfix 以及 Dovecot; 这些教程中的示例尽可能地简单,不包括对安全性、防病毒扫描程序、垃圾邮件过滤器或任何其他高级功能的调整。我认为当你有一个基本工作系统时更容易学习高级功能。

下周回到 openSUSE 包管理备忘录上。

资源


via: https://www.linux.com/learn/intro-to-linux/openssl-apache-and-dovecot-part-2

作者:CARLA SCHRODER 译者:geekpi 校对:校对者ID

本文由 LCTT 原创编译,Linux中国 荣誉推出