我最近看到一种说法,即BearSSL具有RSA的无限制实​​现。这是什么意思?我不知道没有bignum算法怎么能实现RSA。

评论

您可能需要提供该声明的来源。

在他们的主页上:“尚未实现:...用于RSA的更好的大整数代码...当前的实现方式...相当慢”

@MCCCS好点;我应该删除该项目,因为同时已添加了更好的代码。

#1 楼

这仅表示BearSSL是在不使用任何第三方bignum库的情况下实现的。根据BearSSL网站:


BearSSL的当前实现在性能方面并不是最优的。它们是纯C语言,只有32位乘法。在后续版本中应添加更好的实现。


避免使用外部代码库是减小软件包大小和减小攻击面的一种方法。例如,gmp(流行的bignum库)包括RSA不需要的各种函数,例如有符号算术和浮点算术,并且针对速度(而非安全性)进行了优化。因此,它很可能受到定时攻击。

BearSSL开发人员似乎决定改用自己的代码,而不是从其他地方导入bignum库并对其进行详尽的审核。 />

评论


$ \ begingroup $
我认为Bear专门指的是OpenSSL BigNum(BN)实现。我们让他确认。 PS:我会等一会儿,看看熊本人是否不想写答案。我毫不怀疑这种解释是正确的。
$ \ endgroup $
–马腾·博德威斯♦
18年6月7日在11:19

$ \ begingroup $
@MaartenBodewes哦,我不知道他在使用crypto.se。
$ \ endgroup $
–r3mainer
18年6月7日在15:06

$ \ begingroup $
不仅在crypto.SE上;他是该网站上的顶级用户之一(截至撰写时,该排名接近三分之一),他的声誉是BearSSL受到重视的原因之一。
$ \ endgroup $
–R .. GitHub停止帮助ICE
18年6月7日在17:51



$ \ begingroup $
有关GMP的参考,请访问:gmplib.org/manual/…。
$ \ endgroup $
– Marc Glisse
18年6月8日在19:29

#2 楼

首先,我不会将BearSSL描述为“无大数位数”。但是,确实没有大整数的通用实现;它包含的是大模块化整数的通用实现(实际上是几个)。这很重要。

关于低级乘法

软件库在某些硬件上运行,除硬件提供的功能外不能使用其他任何功能。关于乘法,通用CPU将提供32位乘法,结果为64位。例如,CPU的x86行有一个名为mul的汇编操作码,它将两个32位无符号值相乘(一个在eax寄存器中,另一个在作为参数传递的寄存器中),并产生64位结果,分为两个32 eaxedx中的半位。编写C代码时,通常会得到与操作数相同大小的结果,即,如果将两个uint32_t值相乘,则会得到一个uint32_t结果;要获得完整的64位结果,您需要对uint64_t使用一些强制转换。在BearSSL首次发布时,这种32×32→64的乘法是该实现使用的最大乘数。

某些体系结构不提供32×32→64的操作码。特别是,ARM Cortex M0和M0 +具有高效的32×32→32操作码,但是32×32→64乘法必须使用相当慢的软件例程(在这里我们谈论的是1个周期对40个周期),并且通常是非恒定时间。其他一些具有32×32→64的操作码,但是它不是固定时间的(例如ARM Cortex M3)。这就是BearSSL还提供仅使用16×16→32乘法(在BearSSL API中代号为“ i15”)的实现的原因。
最近,我添加了一些名为“ i62”的代码,该代码利用了某些大型体系结构(尤其是64位模式下的x86)上可用的64×64→128操作码。这要求使用某些编译器特定的扩展,因为(通常)没有可用的uint128_t类型(有关源代码,请参见此处;这仅适用于RSA中使用的模块化幂运算)。

关于通用的bignum代码

许多密码库都包含通用的“大整数”实现:这是一组内存结构和函数,可以表示并对不受先验限制的整数执行算术运算在长度上。在OpenSSL中,这称为BIGNUM(或“ BN”)。在内部,每个这样的大整数都是一个结构,该结构引用一个包含整数内容的数组,并分成基本的“四边形”(就像您用十进制写一个整数时,将其表示为数字序列一样);其他结构元素包含实际的整数长度和相关的内存管理信息。

编写通用的大整数库是一种很自然的做法:优秀的软件工程师要自上而下并自下而上地编写代码。因此,由于许多非对称密码算法是用大整数表示的(例如RSA,DSA,ECC ...),因此该工程师将首先编写一个可靠的大整数库,然后使用它来实现相关算法。第二阶段,出于纯粹的性能原因,将使用专用代码重新实现上述算法中一些最昂贵的操作(这就是OpenSSL现在具有AVX2操作码的专用汇编代码的方式,该操作码专门处理RSA中用于RSA的RSA的模幂运算长度恰好为2048位的密钥)。另外,当以某些语言实现加密时,已经有一个大的整数库可供使用(例如Java的java.math.BigInteger)。

现在,BearSSL没有走这条路,这是有原因的。 BearSSL不包含通用的“大整数”库。它具有某种外观,但实际上是对模块化整数(即,以给定(奇数)整数为模的整数)实现运算。这些功能不是公共API的一部分(仅供内部使用),但在此处进行了说明。实现是在src/int/目录中。

根本原因是对恒定时间代码的追求,以免通过基于定时的边通道攻击(尤其是缓存攻击)泄漏信息。为了真正克服此类攻击,实现必须使用不依赖于秘密信息的内存访问模式。但是,通用的大整数实现不能是恒定时间的,因为值是根据表示的整数动态分配给缓冲区的大小而分配的。因此,可以观察某些代码的内存访问模式的攻击者将能够注意到整数值是“ short”还是“ long”。

在BearSSL中遵循严格的恒定时间准则,则整数是在数组中处理的,数组的长度与模数的长度匹配,而不是值本身的长度,并且即使在某些数组插槽仅包含零的情况下,也始终访问所有数组插槽。在内部,该概念被描述为“宣布的比特长度”:一个大的整数结构在其标头中声明了一个比特长度,该比特长度即为模数的长度,并且所有操作循环都在该比特长度上工作,而不是从该长度推断出的任何长度值(大整数“结构”实际上是一个简单的单词数组,而“标头”是该数组中的第一个单词)。

应该注意的是,像OpenSSL这样的普通密码库历史悠久,始于发明缓存攻击之前。此外,他们的“大整数”库通常是公共API的一部分,因此,他们不能简单地删除它而不破坏与现有应用程序的兼容性。 BearSSL是相对较新的(我于2015年开始使用),因此我可以在充分了解缓存攻击的情况下设计其结构和API,因此缺乏通用的大整数代码,而且模块化整数的代码不属于这一事实公共API的名称(以便以后可以根据需要更改)。

评论


$ \ begingroup $
我很好奇您是否(以及如何)处理硬件乘法持续时间取决于操作数的体系结构,例如一些ARM,包括ARM9TDMI和香草Cortex M3;以及其他一些文档不足的架构。
$ \ endgroup $
–fgrieu♦
18年6月7日在16:35



$ \ begingroup $
@fgrieu:ARM7TDMI的一种方法可能是将乘法视为16x16运算,但计算(x + 65536)y-65536y。这样就消除了对x值的任何时序依赖性。我不知道这种RSA实现是否可以选择这样做,但是它将消除定时攻击。
$ \ endgroup $
–超级猫
18年6月7日在16:43



$ \ begingroup $
@fgrieu通过使用较短的操作数并将顶位强制为“ 10”模式,可以在某种程度上强制执行恒定时间乘法。在此处查看BearSSL。但是,这取决于乘法操作码的确切行为,很少有详细记录。另外,请参见BearSSL网站上的专用页面:bearssl.org/ctmul.html
$ \ endgroup $
–托马斯·波宁(Thomas Pornin)
18年6月7日在17:41

$ \ begingroup $
@fgrieu另外,Cortex M3具有快速的恒定时间32×32→32操作码(与M0 +相同),因此您可以使用针对M0 +情况的实现(“ i15”和“ m15”用BearSSL术语)。在实践中,最有问题的体系结构是从G3 / G4线派生的PowerPC内核(它们仍然很普遍,尤其是在某些可编程HSM中)。
$ \ endgroup $
–托马斯·波宁(Thomas Pornin)
18年6月7日在17:43

$ \ begingroup $
@supercat进行加法时,会产生进位传播的额外费用,更重要的是,该例程使用许多寄存器,迫使代码围绕乘法进行昂贵的保存/恢复操作(基本保存到RAM中)。一个32位寄存器是M0 +上的两个周期,另外两个周期用于将其加载回去。
$ \ endgroup $
–托马斯·波宁(Thomas Pornin)
18年6月7日在17:49

#3 楼

当今最大且尚未开发的最大安全问题是所谓的边信道攻击,其中算法本身是“正确的”,但有关其操作的信息会泄漏到不同的进程:具有不同输入的操作会导致采用不同的分支,并且会访问不同的内存位置。使用精心设计的代码运行在据说独立的任务中,可以观察到CPU全局内部状态的变化,形式包括可能受影响的缓存命中或分支预测,温度变化或其他可衡量的影响的后续性能。

最近,Intel CPU的Spectre和Meltdown漏洞是“推测执行”的产物,它出于效率原因而绕过所有内存保护层,并且当确定推测执行的代码实际上不是运行目标时,其“结果”将被丢弃。然而,它的旁通道效应仍然存在。和行为取决于要处理的实际值。通过使用高效的多精度,这将使库的操作可以通过边信道攻击来观察,并且由于通用多精度库的目标和针对其自身用例不希望受到边信道攻击的应用程序的算法不同,并非专门为要执行的加密任务而设计的库,很有可能导致破坏其封装的方式使软件可观察。 br />