可证明安全的远程内存证明用于堆溢出保护
亚历山德拉·博尔迪列娃1(B),金泰秀1,理查德·利普顿1,和博格丹·瓦林斯基2
1佐治亚理工学院,亚特兰大,美国 sasha@gatech.edu
2布里斯托大学,布里斯托,英国
1 引言
内存破坏攻击是用于控制任意程序的最常见技术之一。这些攻击允许对手通过注入自己的代码或转移程序执行流程来利用正在运行的程序,通常使对手完全控制被攻破的程序。尽管这类漏洞的经典体现是缓冲区溢出攻击,但仍存在许多其他形式,包括释放后使用漏洞和堆溢出。后者正是我们工作的重点。毫无疑问,这一问题极为重要,并已受到安全社区的广泛研究。
现有的解决方案(例如栈和堆金丝雀[14,17,19,31]或地址空间布局随机化(ASLR)[27,37],等)在安全保证、性能、所使用的资源(基于软件或硬件)等方面差异很大。尽管这些技术已在许多系统中实现并已部署,以在实际中防止多种攻击,但它们的构造仅适用于本地系统的场景:例如,检查堆金丝雀完整性的权威机构必须监控程序执行的每一步。然而,这一要求使得现有的基于堆的保护方案很难适用于远程内存证明,其中权威可能位于本地机器之外。例如,一种直接的构造方法来跟踪所有堆金丝雀的位置并在请求时验证其完整性,不仅会带来明显的性能开销,还需要程序与远程验证者之间建立可信通信通道。
更重要的是,以往针对堆溢出攻击的研究均未提供可证明的安全保证。由于缺乏明确的对抗模型,难以判断保护机制的适用范围,而攻击者正变得越来越复杂,往往仍能够绕过许多此类缓解技术。
证明一个给定协议能够在某个明确定义的攻击范围内抵御所有可能的攻击,是现代密码学中的黄金标准。然而,可证明安全的协议在实际系统中却很少被使用,通常是因为这些协议针对的是极其强大的安全定义,导致其运行速度过慢而无法实际应用,或者因为它们依赖于对攻击者不切实际的假设。我们的工作旨在通过设计具有可证明安全保证、能够抵御现实威胁并满足实际系统要求的实用协议,来弥合这一差距。我们的方法结合了现代密码学的形式化可证明安全方法与应用系统专业知识。
在本文中,我们将理论成果实现为一个可运行的原型系统,该系统能够缓解在用户本地计算机外部远程运行的应用程序中的(仍然有限的)堆溢出攻击。
尽管当前的实现主要关注保护在云环境或主CPU外部运行的固件上执行的用户程序,但所提出的安模型具有足够的通用性,可为未来针对其他对手类别的研究工作提供参考。接下来,我们将更详细地讨论我们的重点和贡献。
Our Focus
我们的重点是远程验证场景,其动机来自于云计算的广泛使用。在我们的场景中,协议涉及两个实体:一个可能是易受攻击的程序,以及一个远程验证者,后者证明该程序内存(例如堆)的状态。此场景特别适用于验证部署在本地机器之外并运行的软件的完整性:云上的已部署程序是一个例子,运行在主CPU之外的固件是另一个例子。需要注意的是,如果云是完全不可信的,则不依赖安全硬件就无法保证安全性(而我们的重点仅在于基于软件的解决方案)。因此,我们需要在一定程度上信任云,但同时希望避免更改其上的操作系统。由于我们不信任可能具有恶意的程序,因此我们创建了另一个实体——包装器,该包装器不会直接受到程序的影响,除非对手绕过了操作系统提供的保护边界。
在实践中,系统软件(例如浏览器或操作系统)容易受到内存破坏的影响,因为它严重依赖于C语言等不安全的低级编程语言,出于性能或兼容性原因。
正如我们所提到的,我们并不试图防止所有类型的内存破坏攻击(例如释放后使用或错误类型转换)以及利用技术(例如面向返回编程(ROP)),而是仅考虑一种特定类型的内存破坏攻击,即通过覆写连续内存区域(例如缓冲区)来破坏控制敏感数据结构(例如函数指针或虚函数表)。然而,我们认为此类内存损坏仍然非常普遍(例如glibc中的近期GHOST漏洞 [4]),并且在我们必须依赖云服务提供商的云环境中变得愈发重要。
在此范围内,我们的目标是找到(1)提供可证明安全性保证且(2)实际高效的解决方案。
在没有明确定义的安全模型的情况下,无法提供安全性保证。我们首先定义一个远程内存证明(RMA)协议,其目标是保护程序数据内存(例如堆)的完整性。该协议本质上是证明者与验证者之间的一种交互式挑战‐响应协议,由初始化算法启动,该算法将验证者已知的一个密钥嵌入到程序的内存中。验证者的目标是检测内存破坏。
接下来,我们提出了首个针对RMA协议的安全模型。该定义是我们的主要贡献之一。我们的模型涵盖了各种对抗能力(攻击者所知晓和能够做到的事情),反映了实际的安全威胁。我们假设攻击者可能对内存内容具有一些先验知识(例如二进制文件本身),并且能够随着时间的推移自适应地获取其中的部分信息。
由于我们针对的是证明者与验证者之间的通信通过不可信信道进行的场景,我们允许对手观察证明者与验证者之间的合法通信。此外,我们允许对手冒充任意一方,并假设其可以修改或替换他们发送的消息为任意选择的消息。为了模拟对内存的恶意写入,我们允许攻击者篡改内存。攻击者的目标是在内存已被破坏的情况下,使验证者仍然接受。
我们注意到,一方面,如果攻击者的查询是无限制的,则可能无法实现任何安全性;另一方面,我们希望避免在模型中硬性规定对这些查询的特定限制。因此,我们针对抽象函数类来表述安全性,以模拟攻击者的读写能力。这使得我们的定义保持高度通用性。具体协议的安全性由定理陈述来说明,其中指定了这些函数类,从而定义了该协议所防御的攻击范围。
为了防止上述 GHOST 攻击 [4],即对同一位置先进行读取(例如信息泄露)后进行写入并保持密钥不变,在我们的设置中,任何解决方案都需要执行周期性密钥更新。我们的协议定义和安全模型已考虑到这一点。但当然,如果攻击发生在刷新时间窗口内,则无法保证安全性。这是防止时序攻击时的一个常见注意事项。
一个被证明满足我们针对特定读取和写入能力类别的安全定义的RMA协议,将保证在合理的计算假设下,这种方案能够有效抵御具有此类实际限制的高效攻击者。这与之前的方案形成对比,因为之前的方案仅被非正式地论证为能够防御某些特定攻击。
我们解决方案背后的思想很简单,类似于栈或堆金丝雀的机制。我们在内存中嵌入密钥,并通过认证来验证这些密钥是否完好无损。这与金丝雀的使用方式类似,但在验证者为远程的情况下,需要对这些思想进行调整。一个简单但具有说明性的例子是:证明者直接向验证者发送所有(连接后的)金丝雀的哈希值。在这种协议中,攻击者可以在修改内存后重放该值。接下来的讨论进一步揭示了在尝试推导可证明的安全保证时发现的该协议潜在弱点。
为了清晰起见,我们不再将这些密钥称为金丝雀,而是将嵌入内存中的密钥称为份额,即:我们将一个密钥分割成多个份额,并将其分散在内存空间中。目前,为简化起见,假设这些份额以相等间隔嵌入。那么,即使对手知道份额的位置,只要其注入恶意代码并写入至少一个块长度的字符串,就必然会覆盖至少一个份额。验证过程只需检查原始密钥是否能够被重构,并可用于防止重放的简单挑战‐响应协议中。例如,验证者可以发送一个随机挑战,证明者则回复由重构的密钥与挑战计算得到的哈希值。需要注意的是,证明者将在完全独立的内存空间中运行,因此在验证时重构密钥的保密性不会成为问题。
我们注意到,我们的解决方案不能直接应用于栈,因为栈没有明确的单元或边界来静态放置秘密共享,而堆具有分配单元(页),使得密钥放置更加高效和容易。
n选n秘密共享方案的标准安全性确保了除非攻击者读取全部内存(而在此情况下无论如何也无法保证安全性),否则密钥是信息论意义上的隐藏。然而,对手可能在读取后篡改内存,同时保持份额不变。为了缓解这一问题,周期性更新可以对所有份额进行重新随机化,同时保持密钥不变。块的大小和更新频率是特定应用程序可根据所需的安全性与效率权衡自行选择的参数。在理想环境中,我们会在发生份额泄露时立即刷新份额。但由于此类事件的发生并不总是明确可知,因此频繁“足够”刷新的替代方案可能导致不合理的开销。在当前实现中,我们将更新频率设为一个参数,开发者可简单地在其实现中引入反映对手现实假设的时间安排。
尽管该解决方案的方法看似简单且合理,但从系统和密码学的角度来看,评估其安全性和实用性却引发了诸多细微之处和复杂性。例如,我们的系统无法固定内存对象的大小,这自然会导致内存空间利用率不足(例如去碎片化)。在我们的系统中,我们支持各种用于分配的内存槽,从小至8字节对象逐步递增到超过100兆字节,具体取决于用户配置。
为内存中嵌入的密钥生成,显而易见的选择是使用n选n秘密共享方案作为我们构造的基本构建模块。然而,事实证明,秘密共享方案的标准安全性不足以保证协议的安全性。首先,我们必须扩展安全定义以考虑密钥更新。只要攻击者不在连续更新之间访问全部内存,就允许其访问全部内存。这种扩展的概念称为主动秘密共享[20]。此外,为了证明,我们需要额外的性质:修改至少一个份额意味着改变密钥,并且还有一个我们稍后讨论的额外性质。幸运的是,这些性质均可由一种简单的基于异或的秘密共享方案满足。
我们证明,将简单的基于异或的秘密共享方案(或任何满足我们定义的某些额外属性的通用秘密共享方案)与基于哈希的挑战‐响应协议结合,可以为具有受限但相当合理的读取和篡改内存能力的攻击者提供安全高效的RMA协议。
我们提供的证明依赖于随机预言机(RO)模型[8]。由于随机预言机在高安全性应用中并不稳妥[12],因此可能更希望拥有在标准(无RO)模型下可证明提供安全保障的协议。
一种直观的解决方案是采用某种对称密钥身份验证协议,例如使用基于重构密钥生成的随机挑战的消息认证码(MAC)进行响应。然而,考虑到我们所假设的现实攻击者的能力,形式化证明需要一种在密钥存在泄露和篡改情况下仍保持安全的MAC。后一特性也被称为抗相关密钥攻击(RKA)[6]。遗憾的是,目前尚无适用于广泛类别泄露和篡改函数的合适抗泄露和抗篡改的MAC,因为现有方案(例如[5,10],)仅针对特定的代数类篡改函数,并且效率较低。
或许出乎意料的是,我们考虑一种基于公钥加密方案的挑战‐响应协议——验证者发送一个随机挑战,并期望收到该挑战与(重建的)密钥一起的加密结果。该解决方案要求验证者的公钥被存储,以便证明者可以访问,并且不能被Tamper(否则我们需要一个针对相关公钥攻击安全的公钥方案;类似于对称设置,目前尚无对此属性可证明安全的方案,除非少数研究针对一类狭窄的Tamper函数[7,38])。
为了确保公钥的不可篡改性,我们的系统将潜在的恶意程序与其证明者(例如,不同的进程)的内存空间分离,并将其公钥存储在证明者的内存空间中。由于验证过程是单向的(例如,证明者访问程序的内存),我们的系统能够在实践中保证公钥的不可篡改性。
(例如,除非没有远程内存覆写或权限提升)。这种安全性由已部署的计算平台(例如,MMU商品处理器)提供。
期望加密方案具备某种形式的不可延展性是很自然的。否则,攻击者可能会将针对某个挑战的合法响应修改为同一密钥下另一新挑战的有效响应。一个 IND‐CCA安全的加密方案(如克拉默‐肖普)[15]可能适用于我们。但我们注意到,对我们的应用而言,IND‐CCA安全过于强了,因为我们并不需要防范对密文的任意篡改;相反,攻击者只需为验证者已知的特定消息生成一个有效的密文即可。我们表明,对我们而言,一种在较弱的明文检查攻击下安全的加密方案[32]已足够。因此,我们采用阿卜达拉等人SCS最近提出并分析的“短”克拉默‐肖普(SCS)方案[1]。这使得我们在通信中比标准克拉默‐肖普方案节省了一个群元素。我们还讨论了如何通过略微增加计算量,进一步优化并再节省一个群元素的通信开销。
2 符号说明
X ←$ S表示 X从 S中均匀随机选取。如果 A是一个随机算法,则记号 X ←$ A表示将运行 A的实验结果(可能基于某些输入)赋值给 X。如果 A是确定性的,则在箭头上方省略美元符号。如果 X, Y是字符串,则 X‖Y表示 X和 Y的连接。我们用 L:: a表示将 a追加到列表 L所得到的列表,用 L[i,…, j]表示 L在索引 i和 j之间的子列表。我们用id表示恒等函数(其定义域通常由上下文明确),用 US表示集合 S上的均匀分布。如果 n是一个整数,我们用[n]表示集合1,2,…, n。对于整数 k和比特 b, bk表示由 k个连续的“b”比特组成的字符串。
3 远程内存认证
Syntax
我们首先定义远程内存证明(RMA)协议的抽象功能。
定义1(RMA协议) 。远程内存证明协议由一个算法元组(SS,初始化,(内存证明者, 内存验证者),更新,提取)定义,其中:
- 初始化算法SS以安全参数 1κ作为输入,输出一对公钥/密钥(pk, sk)。(SS由验证者运行。)该输出是可选的。
- 初始化算法Init以比特串 M(表示待保护的内存)、公钥 pk和私钥 sk作为输入,输出一个比特串 Ms(表示受保护内存),以及一个比特串 s(用于认证内存状态的秘密信息)。
- 由证明者和验证者分别运行的一对交互式算法(MA,MV)构成了证明协议。算法MA以公钥 pk和比特串 Ms作为输入,验证者以私钥 sk和秘密值 s作为输入。验证者输出一个比特,其中 1表示接受,0表示拒绝。
- 更新算法Update以比特串 Ms作为输入,输出比特串 Ms ′(即“刷新后”的受保护内存)。该算法可在执行过程中的任意时刻由证明者运行。
- 提取算法Extract以比特串 Ms(表示受保护内存)作为输入,输出比特串 M(表示在 Ms中保护的真实内存)和秘密值 s。该算法主要用于分析,同时也模拟了操作系统读取内存的方式。
正确性条件要求,对于由SS输出的每一对(pk, sk)、每一个M ∈{0, 1}∗,以及由Init(M, pk, sk)输出的每一对(Ms, s),协议(MA(pk, Ms), MV(sk s))中的第二方以概率1返回1。同时,Extract(Ms)=(M, s′)对某个 s′以概率1成立。即使进行了任意多次Update协议的运行,这些条件也应保持成立。
在实践中,远程验证者在将包装器发送到云之前,使用密钥对其进行初始化。随后,包装器作为本地证明者与远程验证者进行交互。在实践中,包装器是一个独立的进程,通过ptrace机制获得内存访问权限。
我们现在正式定义RMA协议的安全模型,这是我们的主要贡献之一。
我们考虑一个能够读取公钥(如果存在)并观察证明者与验证者之间交互的攻击者。该攻击者分为两个阶段进行攻击。在其攻击的第一阶段,它可以读取内存的任意部分,并通过注入其选择的数据来覆盖内存的一部分。在此阶段,对手可以观察并干扰证明者与验证者之间的交互。这一点通过赋予对手访问执行交互式RMA协议的预言机的能力来体现;具体而言,对手可以通过简单地将一个预言机的回答转发给另一个预言机,从而选择观察协议的一次合法执行。当然,对手也可以选择操纵对话,甚至提供其自行选择的输入。我们仅对协议的单一会话进行模
型,因为我们不期望在实际中运行并行会话。此外,在任何时刻,攻击者都可以请求更新密钥份额。在第二阶段,对手指定其希望如何修改内存(要覆盖的位置以及要写入的数据)。随后,内存被修改,执行一次额外更新,之后攻击者可以继续执行第一阶段允许的操作,但不再具备读取内存的能力,这正是我们将攻击者划分为两个阶段的原因。这一点体现了引言中指出的事实:只有在读取和写入之间执行了内存更新过程,安全性才可能实现,因为读取和覆盖操作可能是任意的,从而可能保持密钥完整。
如果对手使得验证者在第二阶段接受,尽管内存已被攻击者修改,则称该对手获胜。这体现了验证者未能察觉内存已被破坏的概念。
我们注意到,出于几个原因,有必要限制对手的能力。首先,正如我们在引言中提到的,如果攻击者的查询是无限制的,则可能无法实现任何安全性。例如,对手可以在密钥更新之间读取全部内存,或者它可以读取一个块并立即覆盖它,同时保持相关的秘密份额不变。此外,请注意,能够逐位覆盖内存的对手可以通过为每个比特依次固定两种可能的值,并逐一观察证明者与验证者之间交互的结果,最终获取整个密钥。简而言之,如果我们不对对手施加(合理的)限制,则无法实现任何安全性。
其次,似乎不太可能有一种唯一解足以防御广泛的攻击类型,而不同的解决方案可能适用于不同的应用程序和攻击类别。然而,我们希望避免为每个单独场景提供不同的安全定义。
因此,我们针对抽象函数类来阐述安全性,这些抽象函数类对建模合法读取和攻击者可进行的篡改请求的读写查询进行参数化。这使得我们的定义具有相当的通用性;具体协议和应用的定理陈述将负责明确这些类,从而界定协议能够防范的攻击范围。
Exp rma-(L,T) A ,Π :
(pk, sk) ←签名方案
M ← A(pk)
(Ms, s) ←初始化(M, pk, sk)
g ← ARead(·),Tamper(·),MA(pk,Ms),内存验证者(sk,s), 更新
I g返回 ⊥
Ms ←更新(Ms) Ms ← g(Ms)
ATamper(·),MA(pk,Ms),内存验证者(sk,s)
当且仅当内存验证者在第二阶段接受时输出1
并且在该点,Extract(Ms) 的第一部分不是 M。
Oracle 读取(f):
f返回 ⊥
否则返回 f(Ms)
Oracle Tamper(g):
g返回 ⊥
Ms ← g(Ms)
图1. 定义内存认证方案安全性的游戏 Π=(SS,Init,(MA, MV), Update, Extract)。
定义2 (RMA方案安全性) . 设 L和 T为两类泄露 和篡改 函数。考虑一个RMA协议 Π=(SS,Init,(MA,MV),Update,Extract)。我们通过实验Exp rma-(L,T) A , Π涉及对手 A,我们在图1中给出该实验。
我们称Π关于 L和 T是安全的,如果对于每个(可能受限的)高效对手A,实验Exp rma(L,T) A Π -,输出1的概率在安全参数下是可忽略的。
上述模型的设计直接受到对实际威胁研究的影响。特别是,读取内存以泄露信息在过去十年几乎成为所有攻击的先决条件。考虑到中间人攻击,是因为即使我们信任云服务提供商,我们也不一定信任提供商与客户端之间的路径,例如在使用咖啡馆的WiFi时。我们要求在不使用安全信道的情况下完成安全认证。
事实证明,实际的读写函数类别本身可能无法描述必要的限制。因此,可以进一步限制攻击者,但这同样体现在安全声明中。例如,我们的构造的安全性能够容忍任何可以读取除一个“块”以外的所有内存,并且可以覆盖内存任意部分的攻击者,只要该部分的长度超过某个最小比特数即可。
4 构建模块
Refreshable Secret Sharing Scheme
我们的方案依赖于一种 n选n的秘密共享方案,其中需要所有份额才能重构秘密;任何 n−1个份额的子集都与秘密独立。除了标准属性外,我们还要求能够以如下方式刷新份额:在更新之间获得的每个 n −1个份额的子集均与秘密独立。该属性被称为主动秘密共享 [20]。此外,我们还需要另外两个安全属性,我们将在本节后面描述。
语法
我们首先提供所考虑的秘密共享方案的语法。
定义3 . 一种可刷新的 n选n秘密共享方案由算法(KS,KR,SU)定义,用于秘密的共享与重构以及份额的刷新1。为简便起见,我们假设密钥域为{0, 1}κ(其中κ是安全参数)。共享算法KS接受一个秘密{s}作为输入,并输出一个份额集合( s1, s2,…, sn) 2。重构算法KR以份额集合 s1, s2,…, sn作为输入,并返回一个秘密 s。更新算法SU以份额集合(s1, s2,…, sn)作为输入,并返回更新后的集合(s′ 1, s ′ n),即同一秘密的新一轮共享结果。
对于正确性,我们要求对于任意s ∈{0, 1}κ以及通过(s1, s2, . . . , sn)由(s1, s2, . . . , sn) ←$ KS(s)得到的(s1, s2, . . . , sn),在任意整数 i ≥1的情况下,KR((s1, s2, . . . , sn)) = s且 KR(SUi((s1, s2, . . . , sn)) = s以概率1成立,其中 SUi((s1, s2, . . . , sn))表示 SU的 i次连续调用,即 SU(SU(… SU((s1, s2, . . . , sn))…))。
安全性
我们要求所使用的秘密共享方案满足三个安全属性。
最基本的是,可刷新秘密共享方案(又称主动秘密共享)的密钥隐私性保证份额不会向对手泄露关于秘密值s的任何信息,且这一性质即使在对每个份额集合进行任意次数的更新。正式定义见完整版本[11]。
Oblivious Reconstruction
我们还要求该方案具有oblivious重建的性质。直观上,这意味着:给定一个能够读取和替换部分份额的对手,可以在任意时刻判断出份额中编码的值是否与原始值相同。这一性质与可验证秘密共享相关但不同:能够判断份额是否与某个秘密一致,并不一定意味着能够判断将一组份额转换为另一组(有效)份额时,底层的秘密是否发生了改变。
更正式地,固定一个密钥 s ∈{0, 1}κ,并令 (s1, s2,…, sn) ←$ KS(s)。考虑一个能够间歇性发出两种类型查询的对手。对于查询i ∈{1,…, n},该对手收到 si;对于查询 (i, v) ∈({1, 2,…, n}×{0, 1}κ, si 的值被设置为 v。我们需要存在一个“密钥是否已更改?”算法 SC,形式化定义见图2,该算法在给定 A所发出的查询及其收到的响应的情况下,能够高效地判断(以压倒性概率)被编码的密钥值是否等于原始密钥的值。
Exp rec A ,Π:
s←$ A; L ←[]
{s1, s2,…, sn}←密钥生成算法(s)
AShareInfo(·)
b ← SC(L)
s ←秘密重构算法(s1 , s2 ,…, sn)
当且仅当返回 1
(b= 1 且 s= s) 或 (b= 0 且 s= s)
ShareInfo(·):
输入 i ∈{1,…, n}
L ← L:: (i, si)
返回 si
输入(i, v) ∈{1, 2,…, n}×{0, 1}κ
L ← L:: (i, v)
si ← v
图2 .定义秘密共享的无意识重构性质的实验。
Share unpredictability
此性质要求对于任意由对手选择的秘密值以及对该秘密值的任意一种份额分配,在执行更新 操作后,对手无法以任何有意义的方式篡改所生成的新份额中的任何一个,且不改变原始秘密值。这一直观概念通过图Exp unpred A Π中图3所示的游戏进行形式化。首先,实验随机选取一个秘密值。在对手获知部分(但并非全部)份额后,这些份额将被刷新,随后对手需尝试篡改至少一个新生成的份额。若在整个过程中共享的秘密值保持不变,则对手获胜。
我们称Π满足份额不可预测性,当且仅当对于任意调用读取 预言机至多 n − 1次,并至少调用一次Tamper预言机的对手,该实验返回1的概率可忽略不计。
Expunpred A,Π:
s ←{0, 1}κ
ARead(·)
(s1, s2,…, sn) ←份额更新算法(s1, s2,…, sn)
ATamper(·)
s=?密钥生成算法(s1, s2,…, sn)
Oracle 读取(i)
返回 si
Oracle Tamper(i, v)
si ← v
图3. 定义秘密共享中份额不可预测性的游戏。我们要求A至少对Tamper查询一次。
安全构造
在此,我们提出一种非常简单的具有无意识可重构性的n选n可刷新秘密共享方案,并论证其安全性。
构造41(可刷新的秘密共享) 。我们定义方案(KS,KR,SU)如下。
- 密钥生成算法接收密钥s ∈{0, 1}κ,为 1 ≤ i ≤ n − 1选取 si ←${0, 1}κ,计算 sn← s⊕ s1 ⊕… ⊕ sn−1
- 秘密重构算法在输入(s1,…, sn)时返回 s1 ⊕… ⊕ sn
- 份额更新算法接收(s1,…, sn)并针对 1 ≤ i ≤ n−1计算 ri ←${0, 1}κ, si ←$ si⊕ri。最后, sn← sn ⊕ r1 ⊕… ⊕ rn−1,且份额更新算法返回(s1,…, sn)。
显然,上述方案是正确的。以下定理说明了其(信息论意义上的)安全性。证明见完整版本[11]。
定理1 。构造41的方案是一种具有秘密隐私、无意识可重构性和份额不可预测性的可刷新秘密共享方案。
我们的第二种构造使用了一种(带标签的)加密方案,该方案满足在明文检查攻击下的不可区分性(IND‐PCA)[32]。一种满足IND‐PCA安全性的具体方案是阿卜达拉等人提出的“短”Cramer‐Shoup(SCS)方案[1]。我们在完整版本中回顾了该原语及该方案[11]。关于SCS方案的IND‐PCA安全性的以下结果由阿卜达拉等人得出[1]。
定理2 . 在 G上的DDH假设下,并假设 H是一个抗目标碰撞的哈希函数,阿卜达拉等人[1]提出的SCS方案是IND-PCA。
5 RMA构造
我们现在准备提出针对一类受限但非常实用的攻击的RMA协议的两种构造。第一种构造结合了秘密共享方案和哈希函数,且不依赖于公钥密码学。该方案在随机预言模型下是安全的,并且效率很高;第二种构造使用了一种在明文检查攻击下安全的公钥加密方案。
两种构造共享相同的基本思想。一个密钥被分割成份额并存储在内存中。在我们的构造中,我们假设这些份额位于等距位置——只要这种布局能够确保对内存的篡改(使用提供给RMA攻击者的篡改函数)会影响这些保护性份额,其他布置方式也是可行的。认证协议采用挑战‐响应形式:验证者选择一个随机临时值并将其发送给证明者。证明者收到临时值后,收集各个份额,重建密钥,并将其用于密码操作;随后验证者确认所使用的密钥与自己持有的密钥一致。
在第一种方案中(如下所述),证明者将密钥与临时值一起进行哈希运算,并将结果发送给验证者,验证者通过其本地存储的密钥以及他所发送的临时值来检查一致性。
5.1 基于哈希的远程内存认证
构造51(基于哈希的RMA) 。固定一个可刷新的 n‐选‐n秘密共享方案 SSh= (KS,KR,SU)。令Divide为任意函数,当输入长度大于 n的比特串时,将 M划分为 n个连续的子字符串(M1,…, Mn)。令 H: {0, 1}∗ →{0, 1}h为一个哈希函数。该方案不使用参与方的非对称密钥,因此在下文中我们将其从算法描述中省略。我们通过以下算法(SS,初始化,(内存证明者,内存验证者),更新,提取)定义RMA协议 hash2rma(H):
- SS(1k) 返回 ε。
- 输入 M 的初始化执行
- s$←{0, 1}κ
- (s1,…, sn)←密钥生成算法 (n, s)
- (M1,…, Mn)← Divide(M)
- 返回(M1‖s1‖… ‖Mn‖sn, s)。
- 输入 Ms时的Extract将 Ms解析为 M1‖s1‖… ‖Mn‖sn,执行 s← KR(s1,…,sn)并返回(M, s)。
- 输入 s时的MV选择 l$←{0, 1}l(κ)并将 l发送给MA。
- MA在输入Ms时从MV获取 l,计算(M, s) ← Extract(Ms),然后将 t= H(s||l)返回。
- MV从MA收到 t,返回比较结果 t= H(s||l)。
- 输入Ms Ms时的Update将其视为 M1‖s1‖… ‖Mn‖sn并返回SU(s1,…, sn)。
以下定理陈述了上述构造所提供的安全性保证——证明的详细信息见论文的完整版本[11]。
定理3 。设 SSh=(KS,KR,SU)为一个 n-选-n可刷新的秘密共享方案。设Divide为任意函数,该函数以比特串 M作为输入,为简便起见,我们假设其长度为 nm位,将 M划分为 n个连续的子字符串(M1,…, M n)。令hash2rma(H)= (SS,Init,(MA,MV), Update, Extract)为基于哈希的RMA协议,如构造51所述。
令 L为一类函数,该类函数在输入整数 a、 b且满足 1 ≤ a<b ≤ m时,返回消息Ms[a… b]。令 T为一类函数,该类函数在输入索引1 ≤ i ≤ n和长度为m+ k的比特串 c时,返回将第 i个块更改为 c后的{s} Ms。
如果对手在两次Update查询之间的所有对Read和Tamper预言机的查询中,存在一个长度至少为n的 Ms子串未被读取(即未被Read返回),则称该对手为受限的。
那么,如果 SSh具有秘密隐私、无意识可重构性以及共享不可预测性,则hash2rma(H)在随机预言模型中关于 L和 T是安全的,且针对上述受限的攻击者也是安全的。
我们注意到,尽管我们的协议描述和处理为了简化起见假设份额以相等间隔嵌入内存中,但我们的实现在出于系统功能考虑时使用了递增大小的块。不过,我们的安全分析仍然适用。这是因为读取和篡改查询如何对应于对份额的读取和篡改是明确的,此外,对尚未读取的内存部分的任何篡改查询都必须改变密钥。
我们从系统的角度论证了安全性声明中限制的合理性。我们要求攻击者无法读取全部内存。这是合理的,因为读取错误的内存地址会导致段错误(例如,进程终止)。鉴于现代处理器使用64位地址,攻击者推断出整个内存空间的可能性极低。
由于我们的威胁模型并非任意内存写入,而更像是缓冲区溢出这类连续内存溢出,因此在此威胁模型下,可以合理假设攻击者需要覆盖块之间的边界。鉴于内存随机化是一种常见的防御手段(尽管不在我们的模型内),攻击者必须正确识别份额位置才能进行覆盖(该位置是随机化的),因此我们不考虑完全任意的写入操作。
5.2 基于加密的RMA
该构造基于与上述基于哈希的RMA协议相似的思想。不同之处在于认证和验证算法。证明者不是计算哈希值,而是使用验证者发送的临时值作为标签,对当前内存中编码的密钥进行加密,并发送该加密结果。
构造52(基于加密的RMA) 。设 SSh=(密钥生成算法,秘密重构算法,份额更新算法)和Divide如构造51中所述。令Π=(KeyGen, Enc,Dec)为一个带标签的非对称加密方案。RMA方案enc2rma(Π)定义如下:
- SS(1κ) 运行 (pk , sk) ←$KeyGen(1κ) 并返回 (pk , sk )
- 初始化与构造51相同。
- 提取在输入Ms上将 Ms解析为 M1‖s1‖… ‖Mn‖sn,运行 s ← KR(s1, . . . , sn) 并返回 (M, s)。
- 内存验证者在输入 s上选择 l ←${0, 1} l(κ)并将 l发送给内存证明者
- 内存证明者在输入 Ms上从内存验证者获取 l并执行
- (M, s1,…, sn)←提取(Ms),
- C$←Encl(s) 和
- 将秘密值 C发送给验证者。
- MV在输入 C上计算 s′← Decl(C) 并返回 s=? s′ 的结果。
- 更新 算法如构造51中所述。
该构造安全性的直观解释如下。证明者将加密后的密钥(针对验证者选择的某个标签)发送给验证者;对手的目标是最终为验证者提供的新标签创建同一密钥的新密文。如果这是可行的,则明文检查预言机将能够区分该加密与另一个不同密钥的加密。以下命题确立了上述构造的安全性。证明见[11]。
定理4 。如果 SSh是具有秘密隐私、无意识可重构性和份额不可预测性的可刷新秘密共享方案,并且 Π=(KeyGen, Enc,Dec)是IND‐PCA安全的,则由构造方法52定义的enc2rma(Π)是关于 L、 T以及定理3中定义的任何高效但受限对手的安全RMA方案。
Optimization
上述定理表明,我们可以使用第4节中提出的SCS方案来实例化一个RMA方案。事实上,我们可以通过观察发现,验证者已经拥有其所接收密文应包含的明文,从而进一步优化该协议的通信复杂度(在原始协议中,每次交互需要证明者发送三个群元素)。在这种情况下,证明者无需发送密文的第二个组件(因为验证者可以使用其密钥重新计算出该组件)。为完整性起见,我们在下方给出该优化方案的相关算法。
构造53(基于SCS的RMA) 。
- SS(1κ) 通过运行 KeyGenSCS(1 κ) 获得 G 和 (h, c, d),以及 (x, a, b, a′, b′)。
- MV 在输入 s 下选择 l ←${0, 1}l(κ),并将 l 发送给 MA。
- MA 在输入 Ms和 (h, c, d) 后,从 MV 获取 l,通过 (M, s1,…, sn) ← Extract(Ms) 获得密钥份额,并采样随机比特 r ∈[|G|],计算 (u= g r, e= hr · m, v=(c · dα)r),其中 α= H(l, u, d)。然后将 (u, v) 发送给服务器。
- MV 在输入其密钥 (x, a, b, a′, b′)、挑战 l 和密钥 s 的情况下,对接收自证明者的输入 (u, v) 执行如下操作,并返回比较结果 v= ua+αa ′ ·(ux)b+αb ′ ,,其中 α= H(l, u, ux · s)。
以下安全性声明直接来自定理4和 2 .
定理5 。 如果 SSh是一个具有秘密隐私、无意识可重构性和份额不可预测性的可刷新秘密共享方案,且 Π= (KeyGen, Enc,Dec)如构造52所述,则由构造53定义的RMA协议是关于 L, T 的安全的RMA方案,并且针对定理3中定义的任何高效但受限的对手均安全,假设DDH问题在底层群中是困难的,并且哈希具有目标抗碰撞性。
6 实现与评估
我们的原型可以无缝地在使用标准库的任何应用程序中启用远程内存证明。在运行时,该原型通过在应用程序开始执行时引入malloc()和free()来拦截所有的内存分配与内存释放。在应用程序运行之前,我们的自定义运行时会预分配不同大小的内存区域,并在内存对象之间仔细插入密钥分片。
具体而言,我们提供了一个简单的包装程序(称为prover),供最终用户执行所有这些操作。根据请求,证明者启动程序,并插入我们的自定义库以用于目标应用程序的内存分配。在程序开始之前,证明者预先分配一个分块内存列表,从8字节对象开始,逐步增加至数兆字节(默认为128兆字节)。在当前原型中,每个大小预先分配 N个块(可配置,默认为10个),例如 N 8字节的块,直至128兆字节。
在认证过程中,证明者使用提供的公钥初始化密钥,对其启动的程序执行内存认证,并与远程验证者进行通信。为了访问远程程序的内存,它通过类 UNIX操作系统中的ptrace接口附加到该程序,并运行协议。
我们从三个方面评估了RMA原型:(1)计算密集型任务(如SPEC基准测试)的运行时开销;(2)最终用户在使用RMA时可能面临的最坏情况开销 (例如启动应用程序);(3)通过我们的原型对远程证明过程中性能开销和传输的数据进行分解分析。我们使用基于加密的RMA的原型实现进行了所有实验。
正如我们在引言中提到的,该协议在加密操作方面不如基于哈希的协议高效,但它提供了更强的安全性(不依赖于随机预言模型),并且在存在系统相关开销的情况下同样表现出色。
Micro-Benchmark
我们通过运行标准的SPEC CPU2006整数基准测试套件来评估RMA的原型。所有基准测试均在配备Intel Xeon CPU E7‐4820 @2.00 GHz和128 GB内存的机器上运行,基线基准测试使用Ubuntu 15.04与Linux 3.19.0‐16提供的标准库运行。如图5所示,由于实现简单,RMA对SPEC基准测试程序造成的性能开销极小:平均为3.1%,根据不同的SEPC基准测试程序,在0.0%到4.8%之间波动。实验过程中,我们发现性能开销的主要部分来自自定义内存分配器的实现以及内存碎片带来的副作用,从而掩盖了与加密操作相关的开销。我们认为,对于需要频繁验证或更新共享密钥的不同类型应用程序,可能需要对加密相关软件栈进行更好的优化。值得注意的是,我们的原型从未在任何方面进行过优化(例如,使用粗粒度全局锁来支持多线程),如有必要,整体性能可以得到显著提升。
| 程序 | 基线 (s) | RMA (s) | 开销 (%) |
|---|---|---|---|
| 400.perlbench | 545 | 566 | 3.9% |
| 401.bzip2 | 749 | 770 | 2.8% |
| 403.gcc | 521 | 537 | 3.1% |
| 429.mcf | 385 | 395 | 2.6% |
| 445.gobmk | 691 | 691 | 0.0% |
| 456.hmmer | 638 | 665 | 4.2% |
| 458.sjeng | 779 | 805 | 3.3% |
| 462.libquantu | 1,453 | 1,514 | 4.2% |
| 464.h264ref | 917 | 950 | 3.6% |
| 471.omnetpp | 540 | 547 | 1.3% |
| 473.astar | 606 | 635 | 4.8% |
| 483.xalancbmk | 361 | 373 | 3.3% |
图5. SPEC基准测试程序在RMA下的运行时开销。
Macro-Benchmark
为了测量最终用户在使用RMA时可能遇到的性能开销,我们构建了一个宏基准测试,包含三个应用程序执行四项不同任务:启动网页浏览器 (Firefox)、邮件客户端(Thunderbird)以及文件压缩与解压缩(Tar)。所有实验均在运行Ubuntu 12.04并配备标准glibc的笔记本电脑上进行。
库(Ubuntu/Linaro 4.6.3‐1ubuntu5),我们对每个基准测试测量了十次,总结如下 [11]。注意,启动应用程序对RMA而言是最坏的情况,因为它必须在程序启动时分配内存空间,并在执行程序之前初始化所有密钥分片。根据我们的基准测试,即使在最坏情况下构建,其性能开销也是可以接受的,但我们认为用户实际感受到的延迟极小:Firefox 中为 0.023 秒,Thunderbird 中为 0.199 秒。
我们还测量了使用原型实现执行RMA协议每个阶段所需的时间,并测量了需要传输的数据量。总之,实际实现所提出的RMA协议是可行的:我们未经优化的系统带来的性能开销可以忽略不计(详细信息见[11]),且证明者与验证者之间的消息量极小(例如,从12字节到396字节)。根据我们的评估,我们认为 RMA协议在实践中能够以高效的方式被利用。
1108

被折叠的 条评论
为什么被折叠?



