目前,有几个库可供希望在其应用程序中添加加密或SSL/TLS功能支持的开发人员使用。本章将帮助您比较不同的库,并了解OpenSSL的优势。您还将了解OpenSSL的历史以及OpenSSL 3.0中的新功能。
在本章中,我们将介绍以下主题:
第一章 OpenSSL和其他SSL/TLS库什么是OpenSSL?OpenSSL的历史OpenSSL 3.0有什么新功能?OpenSSL与GnuTLS的比较OpenSSL与NSS的比较OpenSSL与Botan的比较OpenSSL与轻量级TLS库的比较OpenSSL与LibreSSL的比较OpenSSL与BoringSSL的比较总结
OpenSSL是一个开源软件工具包,其中包括密码学(cryptography)和SSL/TLS库,以及使用该库在命令行上提供一些有用功能的命令行实用程序,例如生成加密密钥和X.509证书(X.509 certificates)。OpenSSL的主要部分是它的库,这意味着OpenSSL主要对软件开发人员有用。然而,系统管理员和DevOps专家也会发现OpenSSL的命令行实用程序非常有用。
SSL代表安全套接字层(Secure Sockets Layer)。它是一种旨在通过不安全的计算机网络提供安全通信的协议。不安全的计算机网络是指恶意中间网络节点可以读取甚至更改传输数据的网络。互联网就是这种不安全网络的一个例子。安全通信是指无法读取或更改传输数据的地方。SSL通过使用对称(symmetric)和非对称(asymmetric)密码来实现通信安全。SSL协议由网景通信公司(Netscape Communications Corporation)于1995年发明,并于2015年被弃用,取而代之的是其继任者TLS协议。TLS代表传输层安全(Transport Layer Security)。
OpenSSL工具包是在SSL协议被弃用之前创建的,因此它的名称中包含“SSL”而不是“TLS”。
OpenSSL在历史上是按照BSD风格(BSD-style)的许可证授权的,但从3.0版本开始,它就按照Apache 2.0许可证(Apache 2.0 license)授权,这也是BSD风格的。此许可证允许OpenSSL在开源和闭源应用程序中使用。
OpenSSL支持许多加密算法(cryptographic algorithms),其中包括对称(symmetric)和非对称加密(asymmetric encryption)、数字签名(digital signatures)、消息摘要(message digests)和密钥交换(key exchange)的算法。OpenSSL支持X.509证书(X.509 certificates)、SSL、TLS和DTLS协议,以及其他不太流行的加密相关技术。
OpenSSL已经存在了一段时间,在其开发过程中,它获得了对许多操作系统的支持。OpenSSL最初是为类Unix操作系统开发的。到目前为止,OpenSSL支持Unix的不同变体,包括 GNU/Linux、BSD 以及新旧商业Unix,如 IBM AIX 和 macOS。OpenSSL还支持流行的非Unix操作系统,如 Microsoft Windows,移动操作系统,例如 Android 和 iOS,甚至旧的和奇特的操作系统,比如MS-DOS和VMS。
通过多年的OpenSSL开发,该库得到了许多优化,包括针对最流行的CPU架构(如 x86、x86_64 和 ARM)的配置优化(assembly optimizations)。OpenSSL目前是现有最快的加密和TLS库之一。
由于其通用性、对许多算法和操作系统的支持以及速度,OpenSSL已成为事实上的行业标准。OpenSSL非常受欢迎,以至于其他TLS库也制作了所谓的OpenSSL兼容层(compatibility layers),以便这些库可以通过OpenSSL应用程序编程接口(application programming interfaces,API)使用。
OpenSSL是一个非常受欢迎的库,但它被广泛采用的路径是什么?让我们通过浏览OpenSSL的历史来了解一下。
OpenSSL库基于Eric Andrew Young的SSLeay库(SSLeay library)。SSLeay中的 eay 代表 Eric Andrew Young(姓名首字母)。SSLeay的开发始于1995年,是SSL库的开源实现。当时,NSS 库还不存在。后来,Tim Hudson加入了开发团队。但在1998年,Eric和Tim都被RSA公司聘用,没有时间进一步开发SSLeay。
SSLeay在1998年被分叉为OpenSSL,这意味着OpenSSL已经成为SSLeay的继任者。最初的创始成员是马克·考克斯、拉尔夫·恩格尔沙尔、斯蒂芬·汉森、本·劳里和保罗·萨顿。OpenSSL的第一个版本,编号0.9.1,于1998年12月23日发布,就在Eric和Tim加入RSA公司并有效停止SSLeay工作一周后。
多年来,许多人和公司为OpenSSL贡献了大量代码和其他工作。贡献公司名单令人印象深刻:甲骨文、西门子、Akamai、红帽、IBM、VMware、英特尔和Arm等。
目前,OpenSSL开发由OpenSSL管理委员会管理,该委员会由七名成员组成。拥有提交权的核心开发团队由大约20人组成。只有两个人在OpenSSL上全职工作。其他贡献者要么在业余时间这样做,要么作为他们在贡献公司工作的一部分。
OpenSSL的历史很有趣,但它的未来会怎样?让我们了解一下工具包的最新变化。
OpenSSL 3.0 的一个主要变化是它的许可证。软件项目在其生命周期内不会经常更改其许可证。OpenSSL项目在3.0版本之前一直使用其 BSD风格 的开源许可证。从3.0版本开始,它使用 Apache License 2.0 。
OpenSSL 3.0是库内部架构发生重大变化的版本。架构更改尚未完成,将在OpenSSL 4.0中继续进行。介绍了OpenSSL操作实现提供者(OpenSSL operation implementation providers)的概念。提供者(provider)是提供加密算法实现的代码单元。现有的OpenSSL密码将主要通过 默认(Default) 和 传统(Legacy)提供程序提供。OpenSSL 3.0仍然支持引擎(engines),但已被弃用,取而代之的是提供程序。对 ENGINE API 的支持可能会在OpenSSL 4.0中删除。还支持第三方提供商,允许独立开发人员将其加密算法插入OpenSSL。
OpenSSL 3.0的另一个有趣特性是内核TLS(KernelTLS,KTLS)。使用KTLS时,应用程序可以创建一个特殊的TLS套接字(TLS socket),类似于TCP套接字。然后,OpenSSL执行TLS握手(TLS handshake),并以TLS套接字选项(TLS socket options)的形式将协商的加密密钥和其他数据传递给操作系统内核(operating system kernel)。然后,TLS协议中的实际数据传输由KTLS代码处理。将TLS卸载到内核可以加速高负载系统上的数据传输,在这些系统中,性能很重要,特别是当内核可以使用高级加密标准(Advanced Encryption Standard,AES)的硬件加速,从而卸载主CPU时。当然,TLS库和操作系统内核都需要KTLS支持。在撰写本文时,只有Linux和FreeBSD内核支持KTLS。
OpenSSL 3.0中的其他一些显著变化包括以下内容:
支持证书管理协议(Certificate Management Protocol)。
一个简单的HTTP/HTTPS客户端。
具有合成初始化向量的高级加密标准伽罗瓦/计数器模式(AES-GCM-SIV)(Advanced Encryption Standard Galois/Counter Mode with Synthetic Initialization Vector)加密。
AES——Advanced Encryption Standard,高级加密标准
GCM——Galois/Counter Mode,伽罗瓦/计数器模式
SIV——Synthetic Initialization Vector,合成初始化向量
新的消息认证码(Message Authentication Code,MAC)算法,如GMAC 和 KMAC 。
新的密钥推导函数(Key Derivation Function,KDF)算法,如SSKDF 和 SSHKDF 。
新的高级APIs,如 EVP_MAC、EVP_KDF 和 EVP_RAND。
低级APIs已被弃用,取而代之的是更新的高级APIs。
代码清理。
错误处理已返工。
旧的不安全算法在默认安全级别上不再可用。
已从 openssl
命令行工具中删除交互模式。
OpenSSL是一个成熟的软件工具包,因此最重要的功能已经在其中实现。因此,对于许多用户来说,最新的更改并不包含太多的新功能。最新版本侧重于库的架构改进。
虽然OpenSSL是最流行的加密/TLS库,但它并不是唯一的一个。我们将在以下部分将OpenSSL与其竞争对手进行比较。
GnuTLS 是一个自由软件TLS库,是为 GNU项目 的需要而创建的。当GnuTLS创建时,GNU项目的大多数应用程序都是在 GPL 2.0 license 下分发的,这与旧的OpenSSL许可证不兼容。GPL 2.0许可软件的作者如果希望与OpenSSL链接,则必须包含许可例外。GnuTLS最初是在 LGPL 2.0 下获得许可的,因此它不需要此类许可例外。
目前,GnuTLS在 LGPL 2.1 下获得许可。此许可证允许用户在自由和开源软件(free and open source software,FOSS)项目中使用该库。也允许在闭源代码项目中使用该库,但有某些条件,例如只有动态链接(dynamic linking)。
GnuTLS不包括密码学、大数算术功能和OpenSSL包含的一些其他功能。相反,GnuTLS使用 GNU生态系统(GNU ecosystem)中提供所需功能的其他库:
GnuTLS的一个有趣特性是,它不仅支持X.509证书,还支持OpenPGP证书。与X.509证书不同,后者在颁发时由其颁发者签名,OpenPGP证书支持所谓的信任网络(web of trust),可以有多个签名,并且可以在证书颁发后添加签名。遗憾的是,OpenPGP证书在TLS连接(TLS connections)中的使用尚未普及。
除了OpenPGP证书支持外,GnuTLS及其加密库Nettle支持的加密算法比OpenSSL少,而且在性能方面,它们比OpenSSL慢一点。然而,GnuTLS和Nettle支持所有流行的算法。
你应该选择OpenSSL还是GnuTLS?如果您正在开发GPL许可的软件,我建议您选择GnuTLS;否则,请选择OpenSSL。
OpenSSL的另一个竞争对手是NSS库,我们将在下一节中介绍。
网络安全服务(Network Security Serivces,NSS)是第一个SSL/TLS库。它最初是 Netscape Navigator 1.0 浏览器中的安全代码,由Netscape Communications Corporation于1994年发布。Netscape还发明了SSL协议,即TLS协议的前身。Netscape Navigator被Netscape Communicator取代,后者被Mozilla浏览器取代,最终被Firefox取代。1997年Netscape Communicator 4.0发布后不久,Netscape安全代码作为一个单独的库发布,名为硬核库(Hard Core Library,HCL)。HCL后来更名为NSS。
NSS库根据 Mozilla Public License 2.0 获得许可,允许应用程序开发人员在开源和闭源应用程序中使用该库。
使用NSS库的著名应用程序是Mozilla基金会的应用程序,如Firefox和Thunderbird,Oracle和Red Hat的一些应用程序,以及LibreOffice和Evolution等开源办公应用程序。虽然这是一个可靠和受人尊敬的公司和应用程序的列表,尽管NSS有着悠久的历史,但它并没有像OpenSSL那样受欢迎。我不确定为什么。有人说OpenSSL更容易使用,并且有更好的文档。
你应该选择NSS还是OpenSSL?我推荐OpenSSL,因为它有更好的文档和更大的开发人员和用户社区。
NSS和GnuTLS都在C中提供了它们的主要API。然而,Botan库是不同的,我们将在下一节中发现。
大多数TLS库都是用C编写的,并在C中提供它们的主要API。Botan是一个用C++11编写的TLS库,在版本3.0中采用了C++17。Botan在C++中提供了其主要的API,但也为C和Python提供了API绑定(API bindings)。第三方项目为Ruby、Rust和Haskell提供了API绑定。还有针对Java和Ocaml的实验性API绑定。
值得一提的是,Botan库有很好的文档。Botan是在一个简单的两条款BSD许可证(two-clause BSD license)下分发的,该许可证允许用户在开源和闭源应用程序中使用该库。
我推荐Botan给那些想要使用C++API并且愿意接受较小开发社区的不太受欢迎的库的开发人员。如果你想使用C API,或者想要一个更高性能的库和一个更大的开发社区,那么就坚持使用OpenSSL。
与轻量级TLS库不同,Botan库在您的存储上比OpenSSL占用的空间更大,我们将在下面讨论。
一些轻量级的TLS库(lightweight TLS libraries)可用。它们针对的是嵌入式市场,如物联网(Internet of Things,IoT)设备或许多人使用但不被视为计算机的其他小型设备。这包括您当地杂货店的支付终端、智能手表、智能灯泡和不同类型的工业传感器。此类设备通常具有较弱的CPU(weak CPUs)、较低的内存(low memory)和较小的存储空间(small storage space)。
轻量级TLS库通常通过 模块化 (modularity)变得轻量级,可以只编译所需的模块,支持更少的加密算法和协议,并且具有不太高级的API;也就是说,它们向使用该库的应用程序开发人员公开的功能和设置更少。
最著名的轻量级TLS库是wolfSSL(前身为yaSSL,也称为Yet Another SSL)、Mbed TLS(前身为PolarSSL)和MatrixSSL。
三个库中最先进的似乎是wolfSSL。它支持许多加密算法,包括 ChaCha20 和 Poly1305 等新算法。
wolfSSL的最新版本具有 程序集优化(assembly optimizations),性能非常高。根据wolfSSL网站上的 基准测试(benchmarks),woflSSL的原始加密性能通常与OpenSSL相当,在某些情况下甚至会明显快于OpenSSL,大约快50%。互联网上的其他信息表明,旧版本的wolfSSL明显比OpenSSL慢。如果您对性能感兴趣,那么我建议您在目标硬件和最新版本的库上运行基准测试。这是因为这两个库都在不断开发中,新版本可能包含更多优化。
Mbed TLS和MatrixSSL支持的加密算法明显较少。
WolfSSL和MatrixSSL在 GPL 2.0 和商业许可证下获得双重许可。GPL 2.0许可证只允许用户在GPL兼容的自由和开源软件应用程序中使用该库。商业许可证允许用户在 闭源(closed source)应用程序中使用该库。
Mbed TLS根据 Apache License 2.0 获得许可,允许用户在开源和闭源应用程序中使用该库。
虽然轻量级TLS库声称要小得多,大约是OpenSSL的20倍,但它们在默认配置中并没有那么小。以下是为 Ubuntu 22.04 x86_64 机器编译的库的大小:
为了减小库的大小,库的用户必须自己编译它,并禁用他们不需要的所有模块。
OpenSSL还具有模块化设计(modular design),允许您从编译中排除不需要的模块。然而,这比轻量级库更困难。一些OpenSSL模块很难排除,因为其他模块对它们有依赖关系,即使它们不应该依赖。一些OpenSSL模块非常大,特别是x509模块,因为它包含使用X.509证书的代码。因此,虽然可以减少编译的OpenSSL的大小,但不可能像轻量级TLS库那样减少那么多。
如果OpenSSL不适合您的设备,请使用轻量级TLS库。否则,请使用全尺寸(full-size)TLS库,如OpenSSL。
我们将审查的最后两个TLS库来自OpenSSL本身。让我们来看看为什么原始的OpenSSL对一些人来说不够好。
LibreSSL是OpenSSL的一个分支(派生代码),由OpenBSD项目于2014年创建,以应对OpenSSL中发现的臭名昭著的Heartbleed漏洞。LibreSSL的成立是为了通过删除旧的、不受欢迎的、不再安全的加密算法和其他功能来提高库的 安全性(security)和 可维护性(maintainability)。
OpenBSD是一个Unix操作系统,是旨在提高安全性的BSD系统家族之一。OpenBSD开发人员不仅开发操作系统内核和实用程序。另一个著名的软件项目是OpenSSH。其他软件项目最初是OpenBSD的应用程序,如OpenNTPD、OpenSMTPD等。现在包括LibreSSL。
分叉后,LibreSSL开发人员删除了许多他们认为过时或不安全的原始OpenSSL代码。他们声称在第一周内删除了大约一半的OpenSSL代码。他们还添加了一些新的加密算法,如伽罗瓦/计数器模式的高级加密标准(Advanced Encryption Standard in Galois/Counter Mode ,AES-GCM)和 ChaCha-Poly1305 。除了添加和删除代码外,一些现有的代码在某些地方进行了返工和强化。
尽管LibreSSL旨在提高安全性,但LibreSSL中存在一些不影响OpenSSL的漏洞,如CVE-2017-8301。
在过去的几年里,OpenSSL还做了一些工作来提高库的安全性和可维护性,并弃用/删除了一些代码——尽管删除的代码不如LibreSSL中删除的代码多。但是,添加了更多的代码和新功能。
OpenSSL的开发资源比LibreSSL多得多,这意味着它的发展速度要快得多。例如,从2018年底到2021年初,LibreSSL已经合并了来自36名开发人员的大约1500个补丁 。与此同时,OpenSSL已经合并了来自276名开发人员的5000多个补丁。除了核心的OpenSSL开发团队,OpenSSL还从Oracle、Red Hat、IBM等大公司获得代码贡献。
虽然LibreSSL的重点是为OpenBSD项目提供TLS库,但它也旨在支持其他平台,并保持与OpenSSL的API兼容。在撰写本文时,LibreSSL API与OpenSSL 1.0.1兼容,但不包括OpenSSL 1.0.2及更高版本的所有最新API。
自从从OpenSSL分叉以来,LibreSSL成为OpenBSD上的默认TLS库,但在大多数其他操作系统上,采用率一直很低。大多数Linux发行版继续使用OpenSSL,一些人决定尝试LibreSSL作为系统范围的选项,但后来决定放弃这种支持。大多数使用OpenSSL的商业应用程序供应商也决定坚持使用它。
在OpenSSL和LibreSSL之间的竞争中,OpenSSL正在获胜。我建议你选择OpenSSL,除非你是专门为OpenBSD社区开发软件,在这种情况下,你应该考虑LibreSSL。
OpenSSL的另一个分支是由强大的谷歌公司创建的,我们将在下一节中探讨。
BoringSSL是2014年公开的OpenSSL的另一个分支。BoringSSL是为满足谷歌公司的需求而设计的。多年来,谷歌一直为OpenSSL维护自己的补丁,用于各种谷歌产品,如Chrome、Android和服务器的基础设施。最终,他们决定对OpenSSL进行分叉,并将其作为一个独立的库进行维护。
与LibreSSL一样,在BoringSSL中,谷歌删除了许多原始的OpenSSL代码,这些代码负责支持旧的和不受欢迎的算法和功能。谷歌还添加了一些OpenSSL中不存在的功能。例如,CRYPTO_BUFFER功能允许您对内存中的X.509证书进行重复数据消除,从而减少内存使用。如果OpenSSL静态链接到应用程序,它还允许您从应用程序中删除OpenSSL的X.509和ASN.1代码。X.509代码是OpenSSL中相当大的一部分。
但这也意味着,如果谷歌以外的人想使用BoringSL,他们应该准备好打破API库中的更改,至少在合适的时候。这对使用该库的开发人员来说非常不便。谷歌理解这一点,并表示尽管BoringSSL是一个开源项目,但它不是通用的。
我的观点是,BoringSSL主要是为谷歌项目的第三方贡献者开源的,如Chrome和Android。
我不建议在您的应用程序中使用BoringSSL,因为它的API不稳定(API instability)。此外,OpenSSL具有更多的功能、更好的文档和更大的社区。
至此,我们已经审查了OpenSSL的几个竞争对手。现在,您应该了解流行的TLS库之间的主要区别,以及在哪种情况下应该使用哪个库。
让我们继续进行总结。
在本章中,我们了解了什么是OpenSSL以及为什么需要它。我们还浏览了OpenSSL的历史,并瞥见了它的未来。我们回顾了OpenSSL的其他TLS库和竞争对手,并强调了它们的优缺点。
现在,您应该更好地了解在任何给定情况下应该选择哪个TLS库。如果情况不是特别的话,我建议你选择OpenSSL,因为许多其他人也选择了OpenSSL,这意味着OpenSSL是最受欢迎的TLS库和事实上的行业标准。
现在你知道为什么要选择OpenSSL了,你需要学习如何使用它。接下来的几章将是实用的,因为我们将学习如何使用OpenSSL的强大功能——从对称加密到使用X.509证书创建TLS连接。