椭圆曲线密码学

作者: Joe Hendrix

当谈到公钥密码学时,当今大多数系统仍然停留在 20 世纪 70 年代。1977 年 12 月 14 日,发生了两件将改变世界的事件:派拉蒙影业发行了《周末夜狂热》,麻省理工学院为 RSA 申请了专利。正如《周末夜狂热》通过其舞蹈编排和配乐帮助普及了迪斯科一样,RSA 通过允许双方在没有共享密钥的情况下安全通信,帮助普及了密码学。

公钥技术,如 RSA,彻底改变了密码学,并构成了通过 SSL/TLS 进行网站加密、通过 SSH 进行服务器管理、安全电子邮件和 IP 加密 (IPsec) 的基础。它们通过将传统密码学中使用的共享密钥分成两部分来实现这一点:用于识别身份的公钥和用于以电子方式证明身份的私钥。尽管迪斯科的流行度已经下降,但如今大多数使用加密技术的网站仍然在使用 RSA。

自 20 世纪 70 年代以来,已经开发出更新的技术,与 RSA 相比,它们以更小的密钥尺寸提供更好的安全性。一项重大突破是基于椭圆曲线数学理论开发的密码学,称为 ECC(椭圆曲线密码学)。尽管 ECC 以非常复杂而闻名,但它已被集成到流行的开源密码学软件中,包括 OpenSSH 和 OpenSSL,并且它本质上并不比 RSA 更难使用。在本文中,我将介绍 ECC,并展示如何在最新版本的 OpenSSH 和 OpenSSL 中使用它。

并非所有加密算法都是相同的。对于固定的密钥或输出长度,一种算法可能比另一种算法提供更高的安全性。在比较不同类型的算法时,例如比较公钥和对称密钥算法时,尤其如此。为了帮助理解这一点,美国国家标准与技术研究院 (NIST) 审查了有关攻击密码算法的学术文献,并就不同算法提供的实际安全性提出了建议(参见 2011 年表 1)。

表 1. NIST 推荐的密钥长度
安全位数 对称密钥算法 相应的哈希函数 相应的 RSA 密钥长度 相应的 ECC 密钥长度
80 三重 DES(2 个密钥) SHA-1 1024 160
112 三重 DES(3 个密钥) SHA-224 2048 224
128 AES-128 SHA-256 3072 256
192 AES-192 SHA-384 7680 384
256 AES-256 SHA-512 15360 512

注意:对于新应用,即使不需要 128 位安全性,我也认为应该使用 AES-128 而不是三重 DES。SHA-1 已被发现存在攻击,NIST 现在估计 SHA-1 在数字签名应用中仅提供 69 位安全性。

如果您的系统预计仅保护信息到 2030 年,NIST 建议您使用提供至少 112 位安全性的密码学。对于需要长期保护的应用,NIST 建议至少 128 位安全性。

国防部要求

尽管 NIST 指南备受尊敬,但国防部对机密信息有更严格的要求。对于国防部而言,128 位仅足以保护机密信息。RSA 的使用未获批准,绝密信息需要使用 AES-256、SHA-384 和 ECC,密钥长度为 384 位。此外,系统必须使用两个单独的加密实现进行保护。例如,同时使用 IPsec 和 TLS,以便如果在一个层中发现缺陷,信息仍然受到另一层的保护。尽管这对于大多数互联网应用来说可能不是很实用,但了解安全性至关重要时的要求是很有趣的。

仅仅因为 NIST 提出了这些建议,并不意味着应用程序会遵循它们。许多网站,包括在线银行,仍然会使用 SHA-1 并将其与 AES 128 和 1024 位或 2048 位 RSA 密钥配对。根据 NIST 的说法,实现真正的 128 位安全性意味着 RSA 密钥应至少为 3072 位——大多数互联网证书颁发机构甚至不提供这种大小。目前,Verisign 将向您出售 SSL 证书,声称它可以提供“256 位安全性”,因为您可以将其与 AES-256 一起使用。签名本身使用 SHA-1 和 2048 位 RSA 密钥。

目前,互联网上的安全性仍然足够薄弱,几乎总是更容易找到允许攻击者绕过安全性的漏洞,而不是直接攻击加密。但是,仍然值得了解整体加密实现提供了多少安全性。在密码学中,位数越多通常越好,但实现强度仅取决于其最弱的长度。ECC 和 SHA-2 都代表获得真正 128 位或 256 位安全性的基本算法。

椭圆曲线密码学的数学原理

椭圆曲线密码学以复杂且高度技术性而闻名。当维基百科文章将椭圆曲线定义为“亏格为 1 的平滑射影代数曲线”时,这并不奇怪。椭圆曲线也出现在费马大定理和 Birch 和 Swinnerton-Dyer 猜想的证明中。如果您解决了这个问题,您可以赢得一百万美元。

要基本了解 ECC,您需要了解四件事

  1. 椭圆曲线的定义。

  2. 椭圆曲线群。

  3. 椭圆曲线群上的标量乘法。

  4. 有限域算术。

本质上,椭圆曲线是满足以下形式方程的点

y2 = x3 + ax + b

图 1 显示了实数上的椭圆曲线的图片,其中 a 为 -1,b 为 1。椭圆曲线满足一些有趣的数学性质。曲线围绕 x 轴对称,因此如果 (x,y) 是曲线上的点,则 (x,–y) 也是曲线上的点。如果您在曲线上任意两个具有不同 x 坐标的点之间画一条线,它们将在唯一的第三个点与线相交。最后,对于曲线上的每个点,如果您从该点画一条与曲线相切的直线,它将再次在另一个点与曲线相交。

图 1. 实数上的椭圆曲线

数学家使用这些性质从椭圆曲线上的点形成一个称为群的结构。群由一组元素组成,这些元素包含一个特殊点(表示为 0)、一个用于否定元素的操作(表示为 –x)和一个用于添加两个元素的操作(表示为 x + y)。由椭圆曲线定义的群中的元素由曲线上的点加上一个附加点 0 组成,该点不在曲线上,但正如您将在下面看到的,最容易将其可视化为 x 轴上的一条线。要否定一个点,您只需否定该点的 y 坐标,并且将一个点添加到其否定的定义是返回 0(图 2)。要添加两个具有不同 x 坐标的点 P 和 Q,请画一条连接这两个点并超出它们的线。这条线应该在第三个点与曲线相交。和 R = P + Q 是第三个点的否定。最后,要将点 P 添加到自身,请画一条与 P 相切的线(图 3)。和 R = 2P 是该线相交的点的否定(图 4)。

图 2. 否定一个点

图 3. 添加两个点

图 4. 倍增一个点

一旦定义了群,我们就可以讨论标量乘法——使椭圆曲线在密码学中有用的基本运算。P 的第 k 个标量倍数是通过将 P 自身相加 k 次获得的点。这可以通过将 k 表示为二进制数并使用双倍和加法乘法方法有效地完成。如果您熟悉 RSA,则标量乘法在 ECC 中起着与模幂运算在 RSA 中类似的作用。

用于解释 ECC 的图表中的实数在实际实现中不实用。实数可以有任意位数的数字,而计算机只有有限的内存量。大多数应用程序,包括 OpenSSL,都使用坐标上的椭圆曲线,这些坐标使用模算术,其中模数是一个大的素数。图 5 显示了与图 1 中方程相同的椭圆曲线,但算术运算以 19 为模执行。

图 5. 素数域上的椭圆曲线(mod 19)

对于表 1 中的不同密钥长度,NIST 建议使用具有该密钥长度的素数模数的特定椭圆曲线(参见二进制域侧边栏)。对于每个密钥长度,NIST 指定了三件事

  1. 椭圆曲线方程中的系数。

  2. 用于表示 x 和 y 的底层域的大小。

  3. 一个基点,它是调用标量乘法时要使用的曲线上的一个点。

二进制域

对于每个位大小,NIST 还建议使用另外两个在称为二进制域的字段上的椭圆曲线。尽管素数域在软件中更常见,但二进制域在低功耗硬件中实现 ECC 时很常见。我在本文中重点介绍素数曲线,因为这是 OpenSSL 使用的,并且二进制曲线实现比素数曲线有更多的专利。除非您有一些特定的硬件需求,并且还有钱请律师处理专利问题,否则我建议坚持使用素数曲线。

要了解 256 位曲线的数字有多大,NIST P-256 曲线方程的系数 a=–3 和 b = 41058363725152142129326129780047268409114441015993725554835256314039467401291。

坐标在素数域模 p_256 中,其中

p_256 = 2256 – 2224 +2192 +296 – 1

基点是 G=(xG,yG),定义为

xG = 48439561293906451759052585252797914202762949526041747995844080717082404635286

yG = 36134250956749795798585127919587881956611106672985015071877198253568414405109

如果这些数字对您来说很大,请想想 256 位椭圆曲线相当于 3072 位数字的 RSA。RSA 公钥包含的位数是其 12 倍以上。

如果您想了解有关椭圆曲线密码学的更多信息,可以找到许多参考资料。Certicom 是一家由 ECC 的一些发明者创立的公司,在 http://www.certicom.com/ecc-tutorial 上托管了一个在线教程。为了更全面地了解密码学,Christof Paar、Jan Pelzl 和 Bart Preneel 合著的《Understanding Cryptography》一书有一个关于 ECC 的章节,并且还涵盖了 AES 和 SHA。我在这里只介绍了基本定义,并且没有讨论用于实现像 OpenSSL 中的高性能实现的优化。有关快速 ECC 算法的相当全面的参考资料,《椭圆和超椭圆曲线密码学手册》( http://www.hyperelliptic.org/HEHCC ) 至今没有让我失望。

在 OpenSSH 中使用椭圆曲线密码学

一年多前,OpenSSH 5.7 添加了对基于 ECC 的密码学的支持。尽管它仍然没有在每个 Linux 发行版中都出现,但对 ECC 的支持最终变得足够广泛,以至于开始值得考虑迁移。对 ECC 的支持需要 OpenSSH 版本 5.7 或更高版本和 OpenSSL 版本 0.9.8g 或更高版本。OpenSSH 可以使用 ECC 来帮助您验证您确实在与您想要的服务器通信,并帮助服务器执行基于密钥的用户身份验证。

主机身份验证由客户端用于验证服务器。它用于检测中间人攻击,通常由 OpenSSH 自动设置和使用。安装 OpenSSH 时,它应该创建一个或多个主机密钥,这些密钥通常存储在 /etc/ssh 中。ECC 私钥通常命名为 ssh_host_ecdsa_key,相应的公钥通常命名为 ssh_host_ecdsa_key.pub。如果您想更改此路径,请参阅 sshd_config 的手册页。只需确保私钥只能由授权管理员读取;任何有权访问主机私钥的人都可能冒充服务器。

客户端身份验证用于针对服务器验证客户端身份。使用密钥而不是密码进行身份验证既更方便(因为您可以使用 ssh-agent 或其他程序来缓存密钥),也更安全(因为密码永远不会以纯文本形式发送到服务器)。如果您过去在 SSH 中进行了大量工作,您可能已经使用 RSA 密钥进行了设置,并且使用 ssh-keygen 的完全相同的过程用于创建 ECC 密钥。唯一的区别是传递 -tecdsa 来创建密钥。ssh-keygen 的手册页将有更多详细信息,如果您需要演练,网上有很多关于设置 SSH 密钥的教程。

对于大多数人来说,一旦支持 ECC 的加密软件得到更广泛的部署,转换为 ECC 应该是快速且轻松的。RSA 可能仍然“足够好”用于大多数应用程序,但 ECC 的安全性明显更高,并且对于在越来越普及的微型、低功耗、联网设备上获得强大的安全性至关重要。将其引入 OpenSSL 和 OpenSSH 等开源工具绝对是朝着更广泛使用迈出的重要一步。

加载 Disqus 评论