01.openssl基本介绍
本章介绍SSL和OpenSSL库。 我们给出一个概述涉及部署图书馆的最大安全风险,并讨论如何缓解他们在高层次。 我们也看看如何使用OpenSSL和Stunnel来保护第三方软件,例如没有内置SSL支持的POP服务器。
1.1.1 Goals of Cryptography
有许多不同的加密算法,每个加密算法可以为应用程序提供以下一项或多项服务:
Confidentiality (secrecy)
即使数据是通过不安全的介质传输的,数据也会被保密。 实际上,这意味着潜在的攻击者可能会看到实质上“锁定”的乱码数据,但是如果没有正确的信息,他们就不能解锁数据。 在传统的密码学中,加密(加扰)算法是秘密。 在现代密码学中,这是不可行的。 算法是公开的,加密和解密过程中使用**。 唯一需要保密的是关键。 另外,正如我们稍后将要演示的,常见的情况是不是所有的**都需要保密。
Integrity (anti-tampering)
数据完整性背后的基本思想是,一个数据的接收者应该有一种方法来确定是否在一段时间内进行了修改。 例如,可以使用完整性检查来确保通过线路发送的数据在传输过程中不被修改。 大量的着名校验和存在,可以检测甚至纠正简单的错误。 然而,这样的校验和在检测数据的熟练的有意修改方面很差。 如果正确使用,几个加密校验和不具有这些缺点。 请注意,加密不能确保数据的完整性。 整个类的加密算法都受到“翻转”攻击。 也就是说,攻击者可以改变通过改变相应的加密位数据来实现一位数据的实际值。
Authentication (认证)
密码学可以帮助建立身份认证的目的。
Non-repudiation
密码学可以使鲍勃证明他从爱丽丝收到的消息实际上来自爱丽丝。 当Alice向Bob发送这样一条消息时,Alice本质上可以被追究责任,因为她不能否认(否认)她发送的消息。 在现实世界中,你必须假设攻击者不会损害特定的加***。 SSL协议不支持不可否认性,但通过使用数字签名很容易添加。
Snooping (passive eavesdropping)
攻击者会在网络流量通过并记录有趣的数据时观察网络流量信用卡信息。
Tampering(篡改)
攻击者监视网络流量并恶意更改传输中的数据(例如,攻击者可能会修改电子邮件的内容)
Spoofing(欺骗)
攻击者伪造网络数据,似乎来自不同于实际来自的网络地址。 这种攻击可以用来阻止基于主机信息(例如,IP地址)进行认证的系统。
Hijacking(劫持)
一旦合法用户认证,欺骗攻击就可以用来“劫持”连接。
Capture-replay(重播)
在某些情况下,攻击者可以对网络交易进行记录和重放,从而产生不良影响。例如,假设您在出售单个股票的同时价格很高。 如果网络协议设计得不妥当,攻击者可能会记录该协议交易,然后在股票价格下跌的时候重播,直到你所有的股票都没有了
1.1.2 Cryptographic Algorithms
本书讨论了五种密码算法:对称**加密,公钥加密,加密散列函数,消息认证代码和数字签名。
1.1.2.1 Symmetric key encryption
对称**算法使用单个**加密和解密数据。 如图1-1所示,**和明文消息被传递给密码算法,产生密文。结果可以通过不安全的媒体发送,只允许有原始**的接收方解密消息,完成 通过将密文和**传递给解密算法。 显然,这项计划的关键必须保密。
对称**算法的主要缺点是**必须始终保密。 特别是,交换**可能很困难,因为通常您想要在您尝试使用加密保护的介质上交换**。 在发送**在使用之前清除,在攻击者甚至还没有记录**的情况下,可能会造成攻击者的可能性开始发送数据。
**分发问题的一个解决方案是使用密码**交换协议.OpenSSL为此提供了Diffie-Hellman协议,它允许**协商而不实际泄露网络上的**。 但是,Diffie-Hellman并不能保证与你交换**的一方的身份。 某种形式的身份验证机制对于确保您不会意外与攻击者交换**是必要的。
目前,Triple DES(通常是3DES,或者有时是DES3)是最保守的对称密码。 它被广泛使用,但是,新的高级加密标准AES将最终取代它作为最广泛使用的密码。 AES确实比3DES更快,但是3DES已经有了更长的时间,因此对于超偏执的人来说是更保守的选择。 值得一提的是,RC4得到了现有客户端和服务器的广泛支持。 它比3DES快,但难以正确设置(不用担心,SSL使用RC4)。 为了与既不支持AES也不支持3DES的现有软件兼容,RC4特别感兴趣。 我们不建议在没有充分理由的情况下支持其他算法。 对于感兴趣的,我们在第6章讨论密码选择。
安全性与**的长度有关。 更长的钥匙长度当然更好。 为确保安全性,您只能使用80位或更高的**长度。 虽然64位**可能是安全的,但它们可能不会很长,而80位**在至少几年内应该是安全的。 AES只支持128位和更高的**,而3DES则具有固定的112位有效安全性[1]。 在可预见的未来,这两种方法都应该是安全的,以满足所有的密码需求。大型**可能是不必要的。 56位(常规DES)或更少(40位**常见)的**长度太弱; 他们已经证明是可以通过适量的时间和精力来解决的。
1.1.2.2 Public key encryption
公钥密码学提出了解决对称密码术的关键分布问题的解决方案。 在最流行的公钥密码体制中,每一方都有两个**,一个必须保密(私钥)和一个可以自由分配的**(公钥)。 这两个键有一个特殊的数学关系。 对于Alice使用公钥加密发送消息给Bob(见图1-2),Alice必须先拥有Bob的公钥。 然后,她使用Bob的公钥加密她的消息,并将其传递。 一旦加密,只有拥有Bob私钥的人才能成功解密邮件(希望这只是Bob)
公钥加密解决了**分发的问题,假设有一些方法可以找到Bob的公钥并确保**真的属于Bob。 在实践中,公钥通过一系列称为证书的支持信息传递,这些证书由可信任的第三方验证。 通常情况下,一个可信的第三方是一个对那些希望验证其证书的人进行研究(如信用检查)的组织。 SSL使用可信的第三方来解决**分发问题.
公钥密码学有一个显着的缺点,但是对于大消息来说,速度慢得令人难以忍受。 对称**加密通常可以快速完成,以加密和解密机器可以管理的所有网络流量。 公钥加密一般受加密速度的限制,而不是进入计算机的带宽,特别是在需要同时处理多个连接的服务器上。
因此,大多数使用公钥密码系统(包括SSL)的系统尽可能少地使用它。 通常情况下,公钥加密用于协商对称算法的加***,然后所有进一步的加密都使用对称算法完成。 因此,公钥加密算法主要用于**交换协议以及需要不可否认的情况。
RSA是最流行的公钥加密算法。 Diffie-Hellman**交换协议基于公钥技术,可以通过交换对称**实现相同的目的,用于执行实际的数据加密和解密。 为了使公钥方案有效,通常需要有一个涉及与加密本身分离的可信第三方的认证机制。 大多数情况下,我们在下面讨论的数字签名方案提供了必要的认证。
公钥算法中的**本质上是具有特定属性的大数字。 因此,公钥密码中**的比特长度不能直接与对称算法相比较。 对于公钥加密算法,应该使用1024位以上的**来保证合理的安全性。 512位**可能太弱了。 大于2048位的任何内容都可能太慢,并且很可能不会购买更实用的安全性。 最近有人担心1,024位**太弱,但在撰写本文时还没有确切的证据.如果您的**可能需要保护多年,那么您可能需要继续使用2,048位键。
在为公钥算法选择**长度时,通常还需要选择对称**长度。 建议有所不同,但是我们建议您在使用长度小于100位的对称**时使用1,024位**。 如果您使用的是3DES或128位**,我们推荐使用2,048位公钥。 如果您偏执到使用192位**或更高,我们推荐使用4096位公钥。
如果您使用的是椭圆曲线加密(ECC),那么对**长度的要求就会发生变化。这是对公钥加密技术的一种修改,可以使用更快的操作和更小的**来提供相同的安全性。 OpenSSL目前不支持ECC,对于那些希望使用它的人来说,可能会有一些悬而未决的专利问题。 对于对此主题感兴趣的开发人员,我们推荐Michael Rosing(Manning)撰写的“实现椭圆曲线加密”一书。
1.1.2.3 Cryptographic hash functions and Message Authentication Codes
加密哈希函数本质上是具有特殊属性的校验和算法。 您将数据传递给哈希函数,并输出固定大小的校验和(通常称为消息摘要),或者简称为摘要。 将相同的数据传递给哈希函数两次将总是产生相同的结果。 但是,结果没有提供有关输入到该功能的数据的信息。 另外,找到两个产生相同消息摘要的输入实际上是不可能的。 一般来说,当我们讨论这样的功能时,我们谈论的是单向功能。 也就是说,在任何情况下,输出和算法都不可能重构输入。 当然有可逆的哈希函数,但是我们在本书的范围内并不考虑这种情况。
对于通用的用法,一个最小安全的密码哈希算法应该有一个摘要是最小安全对称**算法的两倍。 MD5和SHA1是最流行的单向加密散列函数。 MD5的摘要长度只有128位,而SHA1是160位。 对于某些用途,MD5的**长度是适合的,对于其他用户来说,这是危险的。 为了安全起见,我们建议只使用产生160位摘要或更大的加密散列算法,除非您需要支持传统算法。 另外,由于部分算法存在一些密码上的弱点,MD5被广泛认为是“接近破碎”。 所以,我们建议您避免在任何新的应用程序中使用MD5。
密码散列函数已被用于许多用途。 它们经常用作密码存储解决方案的一部分。 在这种情况下,通过在密码和一些额外的数据上运行散列函数来检查登录,并根据存储的值检查登录。 这样,服务器不必存储实际的密码,因此即使攻击者设法获取密码数据库,选择的密码也是安全的。
人们喜欢用加密哈希来做的另一件事就是在发布软件的同时发布它们。 例如,OpenSSL可能会与归档的MD5校验和一起发布。当您下载归档时,还可以下载校验和。 然后,您可以计算归档上的校验和,并查看计算出的校验和是否与下载的校验和相匹配。您可能希望如果两个校验和匹配,那么您已经安全地下载了实际发布的文件,并且没有得到一些特洛伊木马的修改版本 在里面。 不幸的是,情况并非如此,因为没有涉及的秘密。 攻击者可以用修改后的版本替换存档,并用有效值替换校验和。 这是可能的,因为消息摘要算法是公开的,没有秘密信息输入给它。
如果您与软件分销商共享**,则分销商可以将存档与**结合起来,以产生一个攻击者不应该伪造的消息摘要,因为他不会有这个秘密。 用于使用**散列的方案,即涉及**的散列被称为消息认证码(MAC)。MAC通常用于为通用数据传输提供消息完整性,无论是否加密。 事实上,SSL使用MAC来达到这个目的。
1.1.2.4 Digital signatures
对于许多应用来说,MAC并不是非常有用,因为它们需要就共享**达成一致。 能够认证消息而不需要共享秘密将是很好的。 公钥密码学使这成为可能。 如果Alice用她的秘密签名**签署消息,则任何人都可以使用她的公钥来验证她是否签署了该消息。 RSA提供数字签名。 基本上,公钥和私钥是可以互换的。 如果Alice用她的私钥加密一条消息,任何人都可以解密它。 如果Alice没有对消息进行加密,则使用她的公钥解密消息将导致垃圾。
很像公钥加密,数字签名非常缓慢。 为了加快速度,算法一般不会对整个要签名的消息进行操作。 相反,消息被加密散列,然后消息的散列被签名。 尽管如此,签名计划仍然很昂贵。 为此,如果发生任何类型的安全**交换,则MAC是优选的。
由于数字签名是公钥加密的一种形式,因此您应该确保使用1024位或更高的**长度来确保安全
1.2 Overview of SSL
SSL是目前应用最广泛的安全协议。 它是安全HTTP(HTTPS)背后的安全协议,因此负责网络浏览器角落的小锁定。 SSL能够保护通过TCP工作的任何协议。
SSL事务(见图1-3)从客户端向服务器发送握手开始。 在服务器的响应中,它发送它的证书。 如前所述,证书是包含与服务器关联的公钥和其他感兴趣信息的数据片段,例如证书所有者,其到期日期以及与服务器关联的完全限定的域名[2]
在连接过程中,服务器将使用其私钥证明其身份,以成功解密客户端使用服务器公钥加密的挑战。 客户端需要接收正确的未加密数据才能继续。 因此,服务器的证书可以保持公开 - 攻击者需要证书副本以及相关的私钥,以伪装成已知的服务器
但是,攻击者总是可以拦截服务器消息并呈现攻击者的证书。伪造的证书的数据字段可以看起来是合法的(例如与服务器关联的域名和与证书关联的实体的名称)。在这种情况下,攻击者可能建立到目标服务器的代理连接,然后窃听所有的数据。这样的攻击被称为“中间人”攻击,如图1-4所示。为了完全阻止中间人攻击,客户端不仅要对服务器证书进行彻底的验证,而且还要有一些确定证书本身是否可信的方法。确定可信度的一种方法是将有效证书列表硬编码到客户端中。这个解决方案的问题是它不可扩展。想象一下,在开始浏览网页之前,需要为每个安全的HTTP服务器提供证书,这些服务器可能希望在存储在网络浏览器中的网络上使用。
这个问题的实际解决方案是涉及一个可信的第三方,负责保存有效证书的数据库。 可信的第三方(称为认证中心)使用其私钥对有效的服务器证书进行签名。 签名表示认证机构已经对拥有证书的实体进行了背景检查,
客户端可以验证当局的签名,假设它在本地拥有认证中心的公钥。 如果检查成功,则客户可以合理确信证书由可信第三方已知的实体拥有,然后可以检查存储在证书中的其他信息的有效性,例如证书是否过期。
虽然很少,服务器也可以从客户端请求证书。 在证书验证完成之前,客户端和服务器就要使用哪些加密算法达成一致。 在证书验证之后,客户端和服务器使用安全**协商协议(使用对称**加密算法传输数据)就对称**达成一致。 一旦所有的谈判都完成,客户端和服务器可以随意交换数据。
SSL协议的细节稍微复杂一些。 消息认证码广泛用于确保数据完整性。 另外,在证书验证期间,一方可以去证书吊销列表(CRL)的证书颁发机构,以确保看起来有效的证书实际上没有被盗取
我们不会深入到SSL协议(或其后继者,TLS)的细节。 就我们的目的而言,我们可以把所有其他事情当作黑箱。 再一次,如果您对这些细节感兴趣,我们推荐Eric Rescorla的书籍SSL和TLS。
1.3 Problems with SSL
SSL是一个很好的协议。 像许多工具一样,它是有效的在谁知道如何使用它的人的手中,但容易被误用。 人们在部署SSL时会遇到许多陷阱,其中大部分可以通过一些工作来避免。
1.3.1 Efficiency
SSL比传统的不安全的TCP / IP连接要慢很多。 这个问题是提供足够安全性的直接结果。 当一个新的SSL会话正在建立时,服务器和客户端交换了相当数量的信息,这些信息是他们相互验证和同意用于会话的**所必需的。 最初的握手包括大量使用公钥加密,正如我们已经提到的那样,这种加密很慢。 这也是使用SSL时最大的放缓。 在当前的高端个人电脑硬件上,OpenSSL在实际工作负载下努力实现每秒100个连接。
一旦初始握手完成并建立会话,开销就会大大降低,但仍然有一部分与不安全的TCP / IP连接相比。 具体来说,更多的数据传输比正常。 数据以包的形式传输,包含SSL协议所需的信息以及正在使用的对称密码所需的任何填充。 当然,也有加密和解密数据的开销,但好消息是对称密码正在使用,所以通常不是瓶颈。 对称密码的效率可以根据所使用的算法和**的强度而有很大的变化。 然而,即使是最慢的算法也是有效的,所以它们几乎不是瓶颈。
由于公钥密码学效率低下,许多人在意识到无法处理足够大的负载时决定不使用SSL。 有些人根本就没有安全感,这显然不是一个好主意。 其他人试图设计自己的协议来弥补。 这是一个糟糕的主意,因为有很多不明显的缺陷可以让你感到困惑。 不熟练的密码员设计的协议不可避免地会有问题。 SSL的设计确实考虑了效率; 它只是不愿意牺牲安全来提高速度。 你应该怀疑使用更高效的协议。
有办法在不放弃协议的情况下改善这个问题。 SSL确实支持连接恢复机制,这样在断开连接之后不久就可以重新连接的客户端可以这样做,而不会产生建立连接的全部开销。 虽然这对于HTTP很有用,但对于其他协议通常不起作用。
1.3.1.1 Cryptographic acceleration hardware
加速SSL的一种常见方法是使用硬件加速。 许多供应商提供PCI卡,可以从您的处理器卸载加密操作的负担,OpenSSL支持其中大部分。 我们讨论使用硬件加速的具体细节
1.3.1.2 Load balancing
用于管理SSL效率问题的另一个受欢迎的选择是负载均衡,即简单地在多个机器之间透明地分配连接,使得该机器群体出于所有意图和目的而作为单个机器出现在外部世界。 这可能比加速卡更具成本效益的解决方案,特别是如果您已经有硬件躺在附近。 然而,负载均衡通常需要更多的工作来确保持久数据随时可用于后端的所有服务器。 负载平衡的另一个问题是许多解决方案将新的连接路由到任意的机器,这可以消除连接恢复的大部分好处,因为在重新连接期间很少的客户机实际上将连接到原始机器。
一种简单的负载均衡机制是循环DNS,其中多个IP地址被分配给单个DNS名称。 为了响应DNS查找,DNS服务器在发送相同地址两次之前,遍历该DNS名称的所有地址。 这是一个流行的解决方案,因为它是低成本的,不需要特殊的硬件。 连接恢复一般适用于这个解决方案,因为机器往往会保留DNS结果的短期记忆.
硬件负载均衡器的价格和功能各不相同。 那些能够记住外部机器并通过多个连接将它们映射到同一台内部机器的人往往会更昂贵,而且对于SSL更有效
1.3.2 Keys in the Clear
在典型的SSL安装中,服务器维护凭据,以便客户端可以验证服务器。 除了在连接时提供的证书之外,服务器还维护一个私钥,这对于证实提供证书的服务器实际上呈现自己的证书是必需的。
该私钥需要住在服务器上的某个地方。 最安全的解决方案是使用加密加速硬件。 这些设备中的大多数可以生成和存储**资料,并且另外防止私钥被入侵到机器的攻击者访问。 为此,私钥仅在卡上使用,除特殊情况外不允许关闭。
在硬件解决方案不可行的情况下,没有绝对的办法来保护获得root访问权限的攻击者的私钥,因为在处理新的连接时,**必须至少在内存中不加密。[4] 如果攻击者拥有root权限,她通常可以将一个调试器附加到服务器进程中,并提取未加密的**。
在这些情况下有两种选择。 首先,您可以简单地将**保存在磁盘上。 这是最简单的解决方案,但是如果他具有物理访问权限,攻击者的工作也会变得简单,因为他可以关闭计算机并拔出磁盘,或者直接重启到单用户模式。 或者,您可以使用密码在磁盘上保存**,管理员在SSL服务器启动时必须键入该密码。 在这种情况下,**只能在服务器进程的地址空间中未加密,因此对于可以关闭机器并直接访问磁盘的用户是不可用的。
此外,许多袭击者正在寻找低洼的水果,即使他们有这样的技能,他们也不可能追随他们。 这个解决方案的不利之处在于无人参与重启是不可能的,因为无论何时机器重启(或者SSL服务器进程崩溃),都必须输入密码,这通常不太实际,特别是在无人环境中。 明显存放钥匙显然不存在这个问题。
无论哪种情况,最好的防御措施是使用最好的锁定技术(包括物理锁定技术)来保护主机和网络。 这样的解决方案超出了本书的范围。
如果服务器的私钥被泄露,究竟意味着什么? 最明显的结果是攻击者可以伪装成服务器,我们将在下一节讨论这个问题。 另一个结果(可能不那么明显)是所有使用**的通信都可能被解密。 如果攻击者能够泄露私钥,攻击者也可能记录了以前的通信。 解决这个问题的方法是使用临时**。 这意味着在创建新的SSL会话时会生成临时**对。 然后这被用于**交换,并随后被销毁。 通过使用临时**,可以实现前向保密,这意味着如果一个**受到攻击,用以前的**加密的消息将不会受到攻击[5]。 我们将在第5章更详细地讨论短暂的**和前向保密。
1.3.3 Bad Server Credentials
服务器的私钥可能被盗。 在这种情况下,攻击者通常可以伪装成服务器而不受惩罚。 此外,认证机构有时也会为欺骗性地代表自己的人签署证书,尽管CA做出了努力来验证所有关于请求证书签名的一方的重要信息[6]。 例如,在2001年年初,VeriSign签署了声称属于微软的证书,但实际上并没有。 但是,由于他们已经由一个知名的认证机构签名,所以他们对于验证这些证书签名的任何人都是真实的。
SSL有一个阻止这些问题的机制:证书吊销列表。 一旦证书颁发机构得知证书被盗或签名不当,证书颁发机构会将证书的***添加到CRL中。 客户端可以访问CRL并使用CA的证书验证它们,因为服务器使用其私钥签署CRL。
CRL的一个问题是漏洞的窗口可能很大。 一个组织可能需要一定的时间才能意识到私钥可能已经被盗,并通知CA. 即使发生这种情况,CA也必须更新其CRL,这通常不会实时发生(所需时间取决于CA)。 然后,一旦CRL被更新,客户端必须下载它们,以便检测出现的证书已被撤销。 在大多数情况下,客户端永远不会下载或更新CRL。 在这种情况下,被破坏的证书往往会一直受到损害,直至到期。
这种现象有几个原因。 首先,CRL往往足够大,以致需要花费大量时间进行下载,并且本地可能需要相当大的存储空间,特别是当SSL客户端是具有有限存储容量的嵌入式设备时。 RFC 2560中指定的在线证书状态协议(OCSP)解决了这些问题。 不幸的是,这还不是一个被广泛接受的标准协议,也不会很快成为现实。 此外,广泛部署的唯一版本存在严重的安全问题(请参阅第3章了解更多信息)。 OpenSSL仅在0.9.7版本中增加了OCSP支持,甚至很少有CA甚至提供它作为服务。 其他权威机构可以增量更新CRL,只需最少的下载时间,但该解决方案仍然需要客户端或某种缓存服务器上的空间。
这些解决方案都需要CA的服务器高度可用,如果客户要有最新的信息。 有些客户端将部署在不可能连接到CA的环境中。 另外,查询CA的需求会增加连接时间的显着延迟,这对最终用户是不能容忍的。
由于围绕CRL的许多问题,采取一切可行的措施来确保SSL私钥不被盗用就显得尤为重要。 您至少应该设置入侵检测系统来检测您的私钥的泄露情况,以便您可以快速向CA报告泄密情况。
虽然SSL协议和TLS的第3版被认为是相当安全的(如果正确使用的话),[8] SSLv2(第2版)有基本的设计问题,导致后续版本的广泛变化(版本1从未公开部署)。 因此,您不应该支持该协议的版本2,只是为了确保攻击者不会启动导致客户端和服务器解决协议不安全版本的网络攻击。 您只需要拦截连接请求并发送响应,使其看起来像v3服务器不存在。 然后客户端将尝试使用协议的版本2进行连接。
请注意,服务器通常会根据客户端提供的受支持密码列表挑选密码。 我们建议在可行的情况下只支持服务器中的强密码。 在其他情况下,确保选择客户提供的最强密码。 我们将在第5章详细讨论密码选择
1.4 What SSL Doesn't Do Well
1.4.1 Other Transport Layer Protocols
SSL在TCP / IP上运行良好。 但是,对于不是面向连接的传输层协议(如UDP和IPX),它根本不起作用。 也没有真正的方法来使这种协议工作,无论是。 对不能保证顺序和可靠性的协议的安全加密是一个挑战,并且超出了SSL的范围。 我们在第6章中概述了加密UDP流量的解决方案。
在第10章中,我们将讨论如何使用S / MIME签名加密的消息。 通过在发送数据之前签署数据,可以使用相同的技术通过SSL发送消息。 或者,可以简单地通过SSL连接发送S / MIME消息以实现相同的结果。
1.5 Securing Third-Party Software
虽然本书的大部分内容都着重于如何使用OpenSSL API来为您的应用程序添加安全性,但您通常会希望使用OpenSSL来保护其他人的应用程序。 已经构建了许多应用程序来支持OpenSSL。 例如,OpenSSH广泛地使用OpenSSL密码学基础,并且要求在编译之前该库存在。 在这种特殊情况下,安装软件的正常过程将会处理所有的细节,只要你在系统上的一个熟知的地方安装了一个OpenSSL版本即可。 否则,可以在配置软件时明确指定OpenSSL的位置。