在加密算法中使用机密数据时保护机密数据的方法

文档序号:10663628阅读:337来源:国知局
在加密算法中使用机密数据时保护机密数据的方法
【专利摘要】本公开涉及一种生成算法的受保护实现的方法,所述方法包括:将实现所述算法的原始源代码扩展成单个真实操作集;将使用真实数据的每个真实操作与每个真实操作所使用的真实数据相组合,以获得以这样的方式表示的组合:该方式以不同于原始形式的形式使用实际真实数据片段;产生应用于引诱数据的表示所述算法的备选实现的重复和变异引诱操作集;将所述引诱操作集与包括所述组合的所述真实操作集相组合,以便获得其中所述引诱操作与所述真实操作和由所述真实操作处理的所述真实数据交互的实现,以使得难以分析所述实现中的真实数据流;以及将所述实现变换成能够被执行的结果代码。
【专利说明】在加密算法中使用机密数据时保护机密数据的方法
【背景技术】
[0001]近年来,加密在计算机软件中的作用已变得越发重要。在过去,加密的使用限于特 定类型的应用,但最近对隐私性以及安全性的关注已迫使应用开发人员响应以显著增加加 密在各种应用中的使用。
[0002] 遗憾的是,加密使用的这种增加(以及其他安全性领域的增加)在实践中并未显著 提高隐私性或安全性。其中一个原因是标准加密算法基于现实世界中并非始终存在的前 提。
[0003] 作为所有标准加密基础的基本前提是用于执行加密操作的机密(例如密钥)保密。 如果机密暴露,则使用这些机密保护的任何信息也暴露。在加密文献中,参与信息交换的实 体被建模为不透明端点,使得如果实体使用机密,则假设该机密对该实体保持私有,除非该 实体传输允许另一个实体导出机密的信息。
[0004] 但是,在现实世界中,这些实体通常是在设备上运行的应用,这些设备可能受到恶 意软件攻击或者甚至由恶意个人直接访问。如果攻击者直接访问在设备上运行的软件,则 对于他们而言窃取这些应用中由加密操作使用的任何机密通常轻而易举。当发生这种情况 时,上述前提不再成立并且受影响的应用将不再从加密的使用中获得任何好处。
[0005] 该问题近年来已导致称为白盒加密的新领域,白盒加密旨在通过以防止直接从应 用提取这些机密的形式重新实现加密操作来解决该问题。在最低限度上,加密操作的白盒 版本应该甚至在非常短的一段时间内防止在存储器中暴露机密数据。但是,在实践中,还需 要抵抗旨在通过检查实现的内部细节而导出机密数据的攻击。
[0006] 早期产生白盒实现的尝试是高度算法特定的,即,专家必须使用专业算法知识谨 慎地设计用于每个算法的方法。这些白盒实现在防止在存储器中暴露机密数据方面非常有 效,但在防止通过检查实现的内部细节而导出实现方面收效甚微。其中主要原因是大多数 加密算法依赖于整体操作的复杂性-当从更细粒度级别观看时,这种复杂性不再存在,并且 通常可以通过相对小的整体算法部分来观察数据流而导出机密。
[0007] 例如,高级加密标准(AES)算法多次执行相同的步骤序列(每次称为一轮),并且其 强度依赖于使用1〇、12或14轮(取决于密钥大小)。如果攻击者能够观察个体轮的输入和输 出,则他们将能够恢复密钥,并且远比在他们将所有轮作为单个不透明单元进行观察的情 况容易。
[0008] 最新解决方案已尝试通过以下操作解决该问题:通过人工或自动化过程,使用其 中极其难以遵循和理解程序和数据流的重度混淆的形式来实现算法的白盒版本。这些解决 方案中的一些解决方案已在实践中被证明至少在防止密钥窃取方面非常有效。
[0009]但是,它们并未明显减轻的一个问题是支持新算法需要的工作量。这仍是一个需 要大量专业知识的相对手动过程。在常见使用中的有限数量算法的情况下,这可能看似不 是严重问题,并且实际上,对于仅需要静态密钥的用例而言并不是问题,但对于需要动态密 钥的用例而言确实造成问题。
[0010]静态密钥是当生成白盒实现时知道的密钥,并且是白盒解决方案的基本元素-产 生白盒的过程基本上涉及以难以导出密钥值的形式,将静态密钥嵌入到加密算法的某一版 本中。动态密钥是仅在运行时才知道的密钥,这意味着动态密钥被传递到白盒而不是已经 被嵌入白盒中,这违反了白盒的固有静态性质。
[0011] 为了适应动态密钥,一个简单解决方案是使用另一个密钥(并且可能使用不同算 法)对密钥加密,其中该另一个密钥变成嵌入白盒中的静态密钥。然后使用白盒对真实密钥 解密,该真实密钥然后与标准算法一起使用以便执行最初预期的操作。
[0012] 该简单解决方案的问题是当对真实密钥被解密时将在存储器中暴露真实密钥,这 部分地违背了起初使用白盒的目的。现有解决方案已尝试通过以下操作减轻该问题:组合 操作序列并且通过通用混淆机制使结果混淆,以便更难隔离暴露真实密钥的点。这表示当 应用于动态密钥时,对此类解决方案的效用的显著妥协。
[0013] 现有解决方案的另一个主要问题是它们并未解决针对白盒实现的特定类别攻击, 这些攻击通常称为提升攻击(lifting attack),然而更准确的名称将是上下文外(out-of-context) 攻击 。上下文外攻击是这样的攻击:其 中攻击者使用 白盒实现以便代表他们执行 加密操作,而不必曾经知道密钥的值。在实践中,如果没有针对该类攻击的特定防御,则白 盒实现可能不比标准实现提供更多的安全性。
[0014] 为了在现实世界中提供足够的加密操作保护,因此需要具有这样的白盒实现:它 们在没有明显削弱保护的情况下支持动态密钥,并且防止提升攻击。

【发明内容】

[0015] 本公开描述一种直接从标准(非白盒)实现的源代码自动生成任意加密算法的白 盒实现的方法。
[0016] 由该方法生成的白盒实现被设计为防止机密数据(例如密钥)被暴露或者由对包 含所述实现的程序具有完全访问和控制权的攻击者以其它方式导出。
[0017] 本公开还描述一种生成白盒实现的方法,其中所述机密数据是动态的,即仅在运 行时已知。这实现为所述第一种方法转换任意算法的能力的逻辑扩展,由此以支持使用动 态机密而不在所述白盒外部暴露它们的形式,将两个加密算法组合成单个白盒实现。
[0018] 最后,本公开描述一种防止在上下文外使用白盒实现,即防止白盒实现直接由攻 击者调用以便用于恶意目的而不是由应用调用以便用于其预期目的的方法。
[0019] 尽管本公开的方法的主要目的是生成加密算法的白盒实现,但所述方法本身并不 限于针对加密算法操作,尽管它们针对其它算法的效用将依赖于这些算法与加密算法共享 多少个属性。具体地说,针对运行时输入数据具有高度确定性的算法通常将产生最有效的 结果。
[0020] 各实施例涉及一种生成以存储在存储器中的代码形式表达的算法的受保护实现 的计算机实现的方法,所述方法包括:将实现所述算法的原始源代码扩展成单个真实操作 集;将使用真实数据的每个真实操作与每个真实操作所使用的真实数据相组合,以获得以 这样的方式表示的组合:该方式以不同于原始形式的形式使用实际真实数据片段;产生应 用于引诱数据的表示所述算法的备选实现的重复和变异引诱操作集;将所述引诱操作集与 包括所述组合的所述真实操作集相组合,以便获得其中所述引诱操作与所述真实操作和由 所述真实操作处理的所述真实数据交互的实现,以使得难以分析所述实现中的真实数据 流;以及将所述实现变换成被存储在所述存储器中并且能够被执行的结果代码。
[0021 ]根据一个实施例,所述算法是加密算法并且所述真实数据包括机密数据。
[0022]根据一个实施例,扩展所述算法包括:由仿真器执行所述原始源代码,并且记录正 在被执行的操作、发生的控制流改变以及发生的对存储器的改变;通过由所述仿真器使用 不同运行时输入多次执行所述原始源代码并且将这些执行的结果组合成所述真实操作集 来恢复在执行期间未被执行的代码;以及由所述仿真器通过将在所述执行期间未被执行的 缺失代码注入所述真实操作集中来协调所述缺失代码。
[0023]根据一个实施例,扩展所述算法包括产生对所述真实操作集中的操作与在所述真 实操作间流动的数据值之间的数据依赖性建模的数据依赖性图。
[0024]根据一个实施例,扩展所述算法包括消除所述真实操作集中产生静态已知值的操 作,所述产生静态已知值的操作包括针对所述真实数据的操作,以使得所述真实数据的每 个部分仅以最终导出形式存在并尽可能深入地被传播到结果真实操作集中。
[0025] 根据一个实施例,扩展所述算法包括减小所述真实操作集的大小,方式为:消除通 过所述仿真器的执行生成的所述真实操作集的一部分内联函数代码和展开循环,使用来自 所述原始源代码的函数调用和循环替换这些内联函数代码和展开循环,使用为函数和基本 块分配得分的决策模型,所述得分表示与通过这种消除发生的真实数据传播损失的成本相 对的通过消除内联和/或展开获得的收益水平。
[0026] 根据一个实施例,扩展所述算法包括:将涉及导出的真实数据的所述源代码的原 始操作拆分成多个新操作,以使得每个新操作使用一段所述导出的真实数据;将各段所述 导出的真实数据变换成产生各段所述导出的真实数据块的唯一操作子集,其中这些操作子 集使用在运行时生成的序列敏感数据值;以及将所述操作子集插入到所述真实操作集中。
[0027] 根据一个实施例,产生重复和变异引诱操作集包括多次重复扩展步骤以便产生多 个引诱操作集,其中为每个引诱操作集供应随机生成的数据而不是所述真实数据,以便产 生表示所述算法的备选虚假实现的多个引诱操作集。
[0028] 根据一个实施例,将所述引诱操作集与所述真实操作集相组合包括:使来自每个 集合的操作与来自所有其它操作集的操作相交错以获得组合集,使得当所述组合集被执行 时,同时有效地执行所有操作集;以及通过逐渐选择多组操作并且通过将每个输出转发到 正确接收操作的新生成的路由操作路由所述多组操作的输出,将来自所述组合集中不同集 合的操作的数据流彼此合并,由此使用唯一生成的不透明表达式来构造路由操作,所述唯 一生成的不透明表达式使用在运行时生成的序列敏感数据值。
[0029] 根据一个实施例,根据小型统一指令集表达所述实现的操作,变换所述实现包括: 使用公知的混淆变换将所述实现的操作序列变换成语义等同的备选形式;组合变换后的操 作序列的操作以便定义包括新指令的新的大得多的非统一指令集,每个新指令被定义为与 所述操作序列对应的个体函数,组合所述个体函数以产生所述新指令;以及使用新指令集 变换所述实现,以便获得包括操作的变换后实现,每个操作对应于所述新指令集的指令。
[0030] 根据一个实施例,变换所述实现包括生成执行控制代码,所述执行控制代码导致 以正确序列并使用正确数据执行所述操作以便执行所述算法,其中由解码器功能集控制执 行,每个所述解码器功能被与一个操作关联,对于该操作,每个解码器功能知道执行该操作 需要的数据的位置、对应指令功能的位置,以及如何对针对每个解码器功能唯一编码的该 数据解码。
[0031 ]根据一个实施例,所述解码器功能使用在运行时生成的序列敏感数据值。
[0032] 根据一个实施例,变换所述实现包括根据复杂程度启用混淆,当将所述复杂程度 设置为最大值时,启用在变换步骤可用的所有混淆。
[0033] 根据一个实施例,所述方法包括生成所述算法的新白盒实现,其中仅在运行时才 知晓机密数据,所述生成包括将所述实现与使用静态密钥的解密算法组合成使用动态机密 数据的所述新白盒实现,所述动态机密数据被使用所述静态密钥预加密,所述解密算法解 密传输到所述实现的所述动态机密数据。
[0034] 根据一个实施例,所述方法包括生成新白盒实现,所述新白盒实现针对已加密数 据执行数据处理操作而不泄露所述已加密数据的内容,所述生成包括将解密算法、所述实 现以及加密算法组合成所述新白盒实现,其中所述解密和加密算法是彼此的逆算法并且使 用相同静态密钥,由此所述解密算法对要处理的数据解密,所述实现针对所述已解密数据 操作并且所述加密算法重新加密所述数据。
[0035] 根据一个实施例,所述方法包括防止在除包含所述实现的程序所指定的上下文之 外的上下文中使用所述实现,所述防止包括:通过将随机生成的数据或真实数据与现有合 并数据相混合,将合并产生器注入到所述程序中,其中当所述实现执行时所述合并产生器 生成合并数据;以及将合并目标注入到所述实现中,其中所述合并目标读取合并数据并将 这些数据与由所述实现内部的操作使用的静态数据相组合,并且其中修改由所述操作使用 的所述静态数据以使得它们不正确并且仅当将它们与所述合并数据组合时才产生所述正 确数据,从而使得所述操作依赖于通过所述程序的执行被正确地生成的所述合并数据,其 中每段合并数据具有不同位置,该位置仅对需要修改该段合并数据的所述合并产生器已知 并且仅对所述实现中的所述合并目标已知。
[0036]根据一个实施例,所述方法包括混淆每个中间数据元素,并且将每个中间数据元 素与对于该数据元素唯一并指定如何混淆该数据元素的混淆上下文相关联。
[0037] 根据一个实施例,所述方法包括在所述实现中注入额外随机化的存储器访问操作 以便掩藏由所述真实操作展示的存储器访问模式。
[0038] 根据一个实施例,所述方法包括随机化由所述真实操作在存储器中访问的所述真 实数据的数据片段的位置。
[0039] 各实施例还可以涉及一种存储应用的非瞬时性计算机可读介质,所述应用适于在 设备上运行并且通过上面定义的方法生成。
[0040] 各实施例还可以涉及一种用于保护以代码形式表达的算法的设备,所述设备被配 置为实现上面定义的方法以便生成所述算法的受保护实现。
【附图说明】
[0041] 图1示出适合于实现本发明的一个示例性实施例的环境,
[0042] 图2是根据一个实施例的生成白盒实现的方法的流程图,
[0043] 图3和4是根据各实施例的生成白盒实现的方法的各阶段的流程图,
[0044]图5是示出根据一个实施例的部分评估步骤的调用图的一个简化实例,
[0045]图6是示出根据一个实施例的操作交错步骤的一个简化实例,
[0046] 图7A和7B示出根据一个实施例的在数据流合并步骤之前和之后的单独操作集的 一个简化实例。
【具体实施方式】
[0047] 将相对于示例性实施例描述本发明。所属技术领域的技术人员将认识到,本发明 可以在许多不同应用和实施例中实现,并且其应用不具体限于在此示出的特定实施例。
[0048] 本发明的一个示例性实施例涉及一种生成白盒实现的方法,其用于直接从标准 (非白盒)实现的源代码自动生成任意加密算法的白盒实现。
[0049] 另一个示例性实施例涉及一种生成白盒实现的方法,其中机密数据是动态的,即 仅在运行时已知。
[0050] 另一个示例性实施例涉及一种防止在上下文外使用白盒实现,即防止白盒实现直 接由攻击者调用以便用于恶意目的而不是由应用调用以便用于其预期目的的方法。下面将 依次描述这些方法的每一种。
[0051] 图1示出适合于实现本发明的一个示例性实施例的环境。电子设备CMP包括:存储 器MEM,在其上存储根据本发明的一个实施例的软件;处理器(CPU)PRC,其用于执行存储在 存储器MEM中的软件;以及其它程序,它们用于控制系统硬件。通常,个人用户与电子设备 CMP的交互通过诸如用户接口之类的输入/输出(I/O)设备发生。I/O设备可以包括显示设备 DSP(例如显示器)和诸如鼠标MS和键盘KEYB之类的一个或多个输入设备和/或诸如触摸屏 之类的其它合适的常规I/O外围设备,以及网络接口。
[0052] 存储器MEM保存应用WBGN,其能够直接从算法的实现的标准源代码PGSC自动生成 算法的白盒实现。
[0053]电子设备可以是计算机或任何其它计算设备,例如智能电话、数字平板计算机或 已连接对象。
[0054]在一个示例性实施例中,电子设备CMP还与诸如因特网之类的网络对接。所属技术 领域的技术人员将认识到,程序源代码PGSC可以在本地存储在电子设备CMP上,或者通过网 络存储在与电子设备对接的远程位置处。同样,白盒生成应用WBGN可以存储在网络服务器 或远程对等服务器上。
[0055] 1.生成白盒实现
[0056] 根据一个实施例的生成白盒实现的方法包括两个主要过程P1、P2,每个过程分为 多个阶段,如图2中所示。过程P1、P2是实现核心生成P1和执行机器生成P2。实现核心生成过 程P1生成低级操作集,这些操作实现输入算法(其可以是加密算法)的初始白盒版本。该操 作集比输入算法复杂得多,并且可以采用多种技术以便抵抗密钥提取攻击。
[0057] 执行机器生成过程P2将上面产生的操作集(这些操作尚未采用可容易执行形式) 变换成可执行形式,可执行形式可以提供防止密钥提取攻击的额外保护。该过程的输出是 独立源代码,其可以被编译成现有项目并且直接执行。这通常是C源代码但可以使用其它实 现语言,例如Java。
[0058] 所述方法的过程P1、P2接收输入算法作为中间表示(IR),其通过解析算法源代码 产生。加密算法最常以C实现,但所述方法适用于编译式和解释式编程语言。由所述方法产 生的代码可以适于由任何计算设备(例如计算机、智能电话或数字平板计算机)或任何已连 接对象执行。当旨在执行要保护的算法的设备围绕开放平台设计和/或连接到公共网络时, 所述方法更加有用。
[0059] 下面更详细地描述过程P1、P2。实现核心生成过程P1负责生成低级操作集,这些操 作实现输入算法的初始白盒版本。根据一个实施例,过程P1包括两个阶段S11、S12-机密激 增和合并以及引诱生成:第一阶段S11-机密激增和合并一将算法扩展成大的低级操作集, 并且将每个操作与它使用的任何机密数据相组合。以不使用原始形式的实际机密数据片段 的方式来表示操作和机密数据的组合。
[0060] 第二阶段S12-引诱生成一产生大的重复和变异引诱操作集,这些引诱操作将并 存并且与由过程P1提供的真实操作同时执行。这些引诱与真实操作和要以这样的方式处理 的数据交互:该方式使得通过实现建立可靠数据流极其困难。
[0061] 根据一个实施例,如图3中表示,阶段S11包括以下四个步骤:
[0062]-算法扩展(步骤S31),
[0063]-部分评估(步骤S32),
[0064]-机密激增(步骤S33),以及 [0065]-机密合并(步骤S34)。
[0066]在算法扩展步骤S31中,将算法扩展成完整的操作集,如果给出可用的静态输入数 据(例如机密数据),则这些操作用于实现算法。这些操作表示最内联、展开形式的算法。该 步骤还产生数据依赖性图,其对操作与在它们之间流动的数据值之间的所有可知数据依赖 性建模。
[0067]在部分评估步骤32中,对操作进行部分评估,这消除产生静态已知值的操作。该步 骤的主要目的是消除针对机密数据的中间操作,使得机密数据仅以最终导出形式存在并且 在它开始与非静态数据(例如要加密/解密的数据块)的点存在。
[0068] 在机密激增步骤33中,将涉及导出机密数据的任何剩余操作拆分成多个操作,使 得与原始操作相比,每个新操作使用更小的导出机密数据部分。重复应用该过程直到没有 操作使用多于某一数量的导出机密数据位(这可以低至单个位)。
[0069] 在机密合并步骤34中,将所有导出机密数据段变换成唯一操作集,这些操作产生 数据而不是存储数据。这些唯一操作集是序列敏感的(如下所述),这意味着它们产生的数 据依赖于由实现直到该点之前执行的几乎所有先前操作。然后将这些数据产生操作与使用 数据的操作相组合,使得几乎不能区分数据的产生和数据的使用。
[0070] 在算法扩展步骤S31中,将算法扩展成完整的操作集,如果给出可用的静态输入数 据(例如静态密钥数据),则这些操作用于实现算法。这些操作表示最内联、展开形式的算 法。作为一个简单实例,将扩展过程应用于以下伪代码:
[0072] 该伪代码包括简单循环并且针对该循环输入"a"和"I"。该伪代码的扩展最初产生 以下操作:
[0073] 1 a = 0
[0074] 2 i = 0
[0075] 3 a = a+10
[0076] 4 i = i+l
[0077] 5 a = a+10
[0078] 6 i = i+l
[0079] 7 a = a+10
[0080] 8 i = i+l
[0081] 9 a = a+10
[0082] 10 i = i+l
[0083] 11 a = a+10
[0084] 12 i = i+l
[0085] 在该扩展伪代码中,已展开循环并且已消除条件("if")语句。
[0086] 包括函数调用和更多程序流控制的更复杂实例还将示出消除作为内联和未达 (unreached)代码的函数,但是当完成过程的其余部分时,该简单实例将有助于清晰可见。 该扩展步骤还产生数据依赖性图,其对操作与在它们之间流动的数据值之间的所有可知数 据依赖性建模。用于上面简单实例的该图的表示如下:
[0087] 1 a = 0
[0088] 2 i = 0
[0089] 3 a = a{0:#1:c}+10
[0090] 4 i = i{0:#2:c}+l
[0091] 5 a = a{10:#3:c}+10
[0092] 6 i = i{l :#4:c}+l
[0093] 7 a = a{20:#5:c}+10
[0094] 8 i = i{2:#6:c}+l
[0095] 9 a = a{30:#7:c}+10
[0096] 10 i = i{3:#8:c}+l
[0097] 11 a = a{40: #9: c}+10
[0098] 12 i = i{4:#10:c}+l
[0099] 在上面的表示中,具有对另一个操作的依赖性的每个值被使用大括号中的依赖性 信息修饰,具有以下格式:
[0100] {value:#source:state}
[0101] 其中"value"是该值的运行时内容(在该时间点),"source"是产生该值的操作,并 且"state"指示是单独从常量输入(由"c"指示)还是从至少一个变量输入(由V'指示)导出 值。例如,在第7行,修饰的存储器位置"a"具有由第5行的操作产生的运行时值20,并且单独 从常量输入数据导出值。值得注意的是,在此示出的实例仅是过程的表示,并且可能未直接 对应于用于实现过程的物理表示。例如,在本发明的当前实施例中,操作在低于在此示出的 伪代码的级别存在,并且没有诸如"for"循环之类的结构。当前实施例还将本身限于没有多 个输出的操作,这简化了依赖模型。但是所述过程适用于广泛的物理表示。
[0102] 通过生成仿真器实现算法扩展步骤S31,该仿真器执行算法并且记录在执行期间 发生的操作,包括:
[0103] -记录每个被执行的操作,以及每个操作的参数的实际值和这些实际值的常量/变 量状态;
[0104] -记录所有控制流改变,包括函数调用、函数出口、条件分支和无条件分支,但这些 控制流改变被标记为不同于正常操作,因为它们的影响已经存在于已记录的正常操作中; 例如,如果调用函数,则记录将包含以下序列:1)调用操作;2)被调函数中的操作;3)函数出 口;以及4)调用方函数中的剩余操作;以及
[0105] -在图中记录由操作写入的所有存储器位置的状态,该图存储要写入该位置的(每 个)最后操作和作为该操作的结果的该位置的常量/变量状态。如果操作的输入值全部是常 量,则写入的存储器位置将被记录为常量;否则它将被记录为变量。
[0106] 在下面表1中示出用于针对实例代码更新存储器状态图的方式:
[0107] 表1
[0109]表1中的每个表行表示正在被执行的每个操作和已执行该操作之后每个存储器位 置的状态。每个存储器位置"a"和"i"由3个列表示,这3个列示出该位置的值、要写入该位置 的最后操作以及位置的常量/变量(c/V)状态。位置"a"和"i"从操作1到12交替变化。当再次 查看操作7(在第7行)时,可以看到在执行操作之前(从第6行读取),"a"的位置具有值20并 且最后由操作5写入,这对应于记录在上面的数据依赖性图中的依赖性信息。在执行操作7 之后(在第7行之后),如可以看到的,位置"a"已改变并且现在具有值30,其最后操作现在被 设置为7。
[0110]使用该简单实例代码,可能显得使用存储器状态映射是过分之举;状态数据可简 单地与每个变量(a和i)关联并且获得相同结果。但是,真实程序具有复杂得多的存储器访 问模式,包括阵列、结构、已分配内存和指针别名使用;存储器状态映射允许使用单个机制 支持所有存储器访问模式。
[0111]当仿真器执行算法时,某些代码可能未被实际执行。在某些情况下,这是希望的; 算法可以包含将从未执行的不可达代码或条件代码,并且这自然由仿真过程丢弃。但是,取 决于算法,可以具有以下情况:其中代码在仿真期间不执行但可以处于不同条件下。当发生 这种情况时,仅基于已知静态数据,确定是否由于决策而未执行代码。如果是这种情况,则 简单地将代码分类为未使用代码;如果不是这种情况,则将代码分类为输入相关代码。如果 给出将导致进行备选决策的输入集,则可以通过将缺失原始代码与允许执行代码的决策逻 辑(而不是在仿真期间实际执行的操作)一起注入到扩展操作集中来处理输入相关代码。这 允许结果实现在面对未见过的输入时工作,但重新注入的代码将不会具有完整的依赖性信 息,这限制在后续步骤中推导依赖性信息的能力。
[0112] 在许多情况下,输入相关代码将不存在或者仅表示小部分代码,并且因此将不会 构成重大问题。在其中更普遍的情况下,上面的解决方案远不够理想,因为它将限制充分执 行后续处理步骤的能力,这又可能限制由白盒过程作为整体提供的保护。为了缓解这种情 况,允许使用不同运行时输入多次执行仿真,并且使用某种运行时决策逻辑将这些仿真的 结果组合成单个扩展操作集。如果选择输入以使得仿真器能够看到所有可能执行路径,则 能够构造完整的扩展操作集。如果检测到每个输入相关代码路径的至少一个执行而不是代 码路径的所有实例,则仍能够构造没有运行时值信息的依赖性图。
[0113] 在部分评估步骤S32中,对操作进行部分评估,其消除产生静态已知值的操作。该 步骤的主要目的是消除针对机密数据的中间操作,以使得机密数据仅以最终导出形式存在 并且在它开始与非静态数据(例如要加密/解密的数据块)的点存在。因为该步骤针对算法 的内联和展开模型操作,并且因为机密数据被视为静态输入数据,所以这导致消除大部分 操作。为了例示这种情况,可以将该步骤应用于简单实例程序时的结果减少到以下行:
[0114] 1 a = 50
[0115] 2 i = 5〇
[0116] 出现该结果,因为针对存储器位置"a"和"i"的所有操作产生静态已知值。这两个 位置使用常量值初始化,并且然后相继通过将它们的当前值与另一个常量值组合而被修 改,这意味着它们的输出始终静态已知。实际上,甚至这两行代码将不会实际存在。如果通 过使用变量"a"和"i"的其它代码扩展程序,则这些操作将直接使用值50和5作为常量,并且 变量" a"和"i"将不存在。如果随后代码不使用变量"a"和"i",则它们将完全不存在。完整的 部分评估过程相对复杂,但可以使用简单实例程序示出基本过程。从使用来自数据依赖性 图的依赖性信息的扩展形式开始,可以从操作1开始并且消除它,因为它明显产生静态已知 数据,与操作2-样。操作3也产生静态已知数据,因为它将依赖性信息指示是常量的值"a" 与文字值(10)组合,因此也能够消除该操作。对于剩余操作同样如此,这意味着能够消除所 有剩余操作。这遗留下具有值50的变量"a"和具有值5的变量"i",但不需要产生这些值的任 何操作;逻辑上,存在上面示出的两个分配,但它们将从不作为实际分配存在。
[0117] 当考虑变量(非静态已知)值和操作的完全内联和展开性质时,过程变得更复杂。 在许多情况下,使用完全内联和展开操作生成白盒实现不切实际;结果实现将太大而没有 实际用途。为了产生实际实现,需要消除某些内联和/或展开。消除这些事物的问题是它们 对操作中的静态已知数据量做出很大贡献。可以通过查看简单实例程序能够得知原因。如 果展开代码要再次进入循环,则"a"和"i"都将变成变量(尽管单独从常量输入导出),并且 将依次"污染"使用它们的任何后续代码,从而使它们的输出可变。当消除内联时,发生类似 效果。这种情况的问题是主要目标是将机密数据以其最终导出形式尽可能远地传播到实现 中,并且当机密数据遇到任何变量数据时该传播终止。
[0118] 部分评估步骤S32的一个目标因此是尽可能多地消除内联和展开,同时最小化该 操作对通过实现传播导出机密数据的影响。为此,建立决策模型,其中为函数和基本块分配 得分,该得分表示与机密数据传播的损失成本相对的通过消除内联/展开获得的收益水平。 得分的收益分量与消除将提供的代码减少量成比例。通过对受消除影响的所有机密数据段 的传播损失求和,计算成本分量。通过测量机密数据段在到达其最终导出形式之前参与的 其它操作的数量,计算个体传播损失。成本分量的自然结果是靠近调用图顶部的代码将往 往比在调用图的叶处的代码具有更高的成本。为此,决策过程自下而上操作,并且当已实现 足够的代码减少时终止。在图5中示出这种情况的一个简化实例。
[0119] 图5顶部的列编号指图的各部分,调用图在下面示出,每个框表示函数块(函数名 称在框内部示出);更宽的框表示其中具有更多操作的函数块。执行的开始在左上角;调用 由向下箭头示出,并且函数出口由向上箭头示出。在父函数中的循环内执行所有调用,并且 在向下箭头上指示调用计数。
[0120] 在调用图下面,示出两行信息"H"和"CTS",其中每列与在它正上方的调用图元素 关联。"H"行示出对应列中的每个元素的执行总次数。调用图底部的函数"e"和"f"被执行很 多次,这是由于数个级别的循环调用所致。"CTS"行示出对应列中的多少个操作产生常量导 出机密数据。
[0121]因为这是简化实例,所以消除内联/展开的成本将被建模为与受影响区域中产生 常量导出机密数据的操作数量成比例。如前所述,通过测量机密数据的传播损失来计算真 实成本。相比之下,该实例假设传播损失始终是1;这是用于示例性目的的合理近似。
[0122] 在下面表Π 中示出从图5的实例获得的得分计算:
[0123] 表Π
[0126] 列"收益"中的结果被计算为"大小*H",并且列"自身成本"中的结果被计算为 "CTS*H"。通过将函数的子函数(它调用的函数)的"自身成本"数值相加,计算列"子成本"中 的结果。列"成本"中的结果简单地被计算为"自身成本+子成本"。用于包括子成本的原因是 如果消除代码区域上的内联/展开,则这将影响依赖于它的几乎每一事物。在函数的情况 下,这意味着它调用的函数。最后,列"得分"中的结果被计算为"收益/(成本+1)"。如可从表 Π 看到的,函数"b"将是第一候选者,因为具有最高得分。尽管它具有相当小的收益,但它具 有零成本,从而使它成为很好的选择。下一个候选者将是函数" e",其具有相当高的成本,但 也具有非常大的收益。在此之后可以使用函数"f";函数"f"的收益和成本非常大,但收益仍 然胜出。函数"a"、"c"和"d"将是特别差的候选者;在调用图顶部意味着它们具有非常大的 成本,并且它们都没有多少的收益。
[0127] 值得注意的是,在实践中,得分计算实际上随着做出每个选择而变化。具体地说, 与选择关联的成本将仅发生一次,并且因此也包括该成本的任何其它选择将使它们的成本 相应地减少。
[0128] 在步骤S33中,将涉及导出机密数据的任何剩余操作拆分成多个操作,以使得与原 始操作相比,每个新操作使用更小的导出机密数据部分。可以以许多不同方式拆分每种类 型的操作。例如,考虑32位乘法操作"s*t",其中"s"是机密数据并且"t"是另一段(可能是变 量)数据。可以将该操作拆分成一系列移位和加法操作,其中每个移位操作表示来自"s"的 单个位。备选地,可以将乘法操作拆分成乘法和加法序列,其中每个乘法仅使用"s"的少量 位。对于更简单的实例,考虑以下X0R(异或)操作:
[0129] 1 s = 0xl234abcd
[0130] 2 t = 0xl0203040
[0131] 3 u = s XOR t
[0132] 与先前实例一样,"s"是机密数据并且"t"是另一段(可能是变量)数据。为了清晰 起见,变量"s"和"t"被示为为它们分配值;在实践中,"s"的值将直接在X0R操作中用作文字 值,并且"t"将已经存在并具有某个变量值。可以将该操作拆分成包括两个X0R操作和一个 0R操作的序列,如下所示:
[0133] 1 si =0x12340000
[0134] 2 tl =0x10200000
[0135] 3 s2 = 0x0000abcd
[0136] 4 t2 = 0x00003040
[0137] 5 ul = slX0R tl
[0138] 6 u2 = s2X0R t2
[0139] 7 u = ulOR u2
[0140] 在这种情况下,通过以下操作实现拆分:针对"s"和"t"的顶部16位执行XOR并且针 对底部16位执行X0R,然后将结果与0R操作组合。将分量拆分成甚至更小的段是该方案的简 单扩展;例如,可以使用4个X0R和3个0R将它们拆分成四个8位段。
[0141] 在此示出的实例仅涉及针对单个操作拆分机密数据。但是,在实践中,它使用操作 序列完成,方法是将涉及机密数据的操作与依赖于第一操作的结果(并且因此依赖于机密 数据)的后续操作组合。
[0142] 下面示出该情况的一个实例:
[0143] 1 s = 0xl234abcd
[0144] 2 u = s XOR t
[0145] 3 v = a+b
[0146] 4 w = u*v
[0147] 在该实例中,机密数据"s"与"t"进行XOR以便产生"u",随后在第4行使用"u"以便 产生V'。第3行(其不以任何方式依赖于"s")的存在用于指示"s"的相关操作可能不连续; 实际上,它们可以通过许多不相干操作被分离。为了针对多个操作拆分机密数据,可以重写 该实例,如下所示:
[0148] 1 s = 0xl234abcd
[0149] 2 v = a+b
[0150] 3 w=(s XOR t)*v
[0151] 其中第3行是这样的表达式:将原始代码中的"u"替换为产生其值的操作("s XOR t,,)。
[0152] 不是针对"s XOR t"产生拆分操作,而是针对表达式"(s XOR t)*v"产生拆分操 作,这表示针对"s"的包含两个相关操作的序列。这可以从导出机密数据扩展成任意深度的 相关操作。在整个操作集中重复应用该激增过程直到没有操作使用多于某一数量的导出机 密数据位。将每个导出数据段拆分成的位数还将依赖于导出数据如何与原始机密数据相 关;如果它们密切相关,则它们将往往拆分成更少量的位。
[0153] 在机密合并步骤S34中,将所有导出机密数据段(许多数据段可能小到单个位)变 换成唯一操作集,这些操作产生数据而不是存储数据。这些唯一操作集是序列敏感的(如下 解释),这意味着它们产生的数据依赖于由实现直到该点之前执行的几乎所有先前操作。然 后将这些数据产生操作与使用该数据的操作组合,以使得几乎不能区分数据的产生和数据 的使用。
[0154] 根据一个实施例,如图4中所示,引诱生成阶段S12包括以下步骤:
[0155] -重复和变异步骤S41;
[0156] -操作交错步骤S42;以及
[0157] -数据流合并步骤S43。
[0158] 在重复和变异步骤S41中,使用随机数据替换机密数据而多次重复机密激增和合 并阶段,以便产生表示选定算法的备选引诱实现的操作集。
[0159] 在操作交错步骤S42中,将所有生成的操作(真实和引诱)组合成单个大操作集,其 中使来自每个集合的操作与来自所有其它集合的操作交错,以使得当执行组合集时,有效 地执行所有操作集。
[0160]在交错之后执行数据流合并步骤S43。在执行该步骤之前,组合操作集仍然包括不 相关操作集一它们简单地位于彼此之间。在该最后步骤中,将这些不相关操作彼此合并,使 得难以确定通过整个组合操作集的数据流。
[0161] 在重复和变异步骤S41中,使用随机机密数据多次重复机密激增和合并阶段,以便 产生表示选定算法的备选引诱实现的操作集。因为生成过程依赖于机密数据的值,所以每 个生成的操作集将是唯一的。我们将此称为变异,因为使结果有效地变异,但实际过程是使 用不同的开始种子生成它们。默认情况下,简单地使用随机生成的数据取代真实机密数据。 当不能将机密数据与随机数据区分开时,这非常好,但如果任何机密数据没有该属性,则需 要使用与机密数据性质更好地匹配的引诱数据。这通过允许算法提供算法特定过滤器加以 解决,这些过滤器调整随机生成的数据以使它适合作为引诱机密数据。
[0162] 在操作交错步骤S42中,将所有生成的操作(真实和引诱)组合成单个大操作集,如 图6中所示。图6示出引诱操作集011、012、013、014和真实操作集1?1,它们交错以便获得单个 大型组合操作集CI。在操作集CI中,使来自每个操作集DI1到DI4和RI的操作与来自所有其 它集合的操作交错(根据集合上面和下面的箭头),以使得当执行组合集CI时,有效地执行 所有操作集DI 1到DI4和RI。交错被具体设计为部分重叠,以使得来自碰巧彼此靠近的不同 集合的操作之间没有直接对应性。具体地说,真实操作集RI始终远离组合集CI的最开始和 最末尾。
[0163] 在步骤S42进行交错之后,组合操作集仍然包括不相关操作集,它们简单地位于彼 此之间。在最后步骤S43-数据流合并中,将这些不相关操作彼此合并,以使得难以确定流 经整个组合操作集的数据。这通过以下操作实现:通过出站数据流逐渐选择操作组,并且通 过新生成的操作推送所述操作组的所有输出数据,新生成的操作将所述操作组的输出数据 路由到正确接收操作。使用唯一生成的不透明表达式构造该路由操作,唯一生成的不透明 表达式也使用序列敏感合并(如下解释)。为了查看这如何工作,图7A中的实例示出使用数 据流合并组合的两个单独操作集。图7A在左侧示出操作"al"、"a2",并且在右侧示出操作 吒1"、%2"。操作" &1"具有两个输入"11&1"和"12&1"。操作%1"具有两个输入"11131"和 "12131"。操作" &2"接收变量"11&2"和操作"&1"的输出。操作吒2"接收变量"11&2"和操作 "bl"的输出。为了使用数据流合并组合操作"al"、"a2"与操作"bl"、"b2",这些操作被布置 为使得在执行操作"a2"或"b2"之前执行操作"al"和"bl",因为在操作"al"与"a2"之间并且 还在操作"bl"与"b2"之间添加额外操作。在图7B中示出针对这些操作执行数据流合并的结 果。在图7B中,插入路由操作R0P以使得它将在已执行操作"al"和"bl"之后但在执行操作 "a2"或"b2"之前执行。如可以看到的,操作"al"和"bl"不是将其输出分别传递到"a2"和 "b2",而是将它们传递到路由操作R0P,路由操作R0P然后将它们继续传递到正确接收者,即 操作"a2"和"b2"。由路由操作R0P使用的不透明表达式使得非常难以确定哪个输出将转到 哪个接收者;具体地说,经由静态分析几乎不可能对此进行确定。数据流合并过程继续直到 已充分合并组合操作集中的所有数据流。
[0164] 通过实现核心生成过程产生的操作集不能以该形式被执行,因此将它们变换成可 执行形式以便产生能够实际被使用的实现。执行机器生成过程P2执行该变换并且产生源代 码,该源代码可以被包括到软件项目中并被直接调用以便执行所需加密操作。但是,根据一 个实施例,不是执行操作到代码的简单直接转换,而是过程P2生成专用机器以便执行提供 防止密钥提取攻击的显著额外保护的操作。
[0165] 在概念级别,从存在执行引擎(其在虚拟机模型的上下文中处理虚拟程序并且执 行由该程序指定的操作)的意义上说,生成的机器大致类似于虚拟机(VM)。但是,在实现级 另IJ,存在许多显著区别:
[0166] 每个生成的机器是唯一的:对于每个机器而言,它能够执行的操作、它如何执行这 些操作、表达这些操作的方式以及执行这些操作的机制是唯一的。
[0167] 机器没有指令集:给定机器能够执行的操作集可以被视为指令集,但它们没有将 允许它们被提供名称并以这种方式被使用的可辨别的概念意义;
[0168] 机器不执行程序:给定机器仅能够执行一个特定程序并且该程序是机器本身的组 成部分,并且在许多情况下,在机器的执行侧与程序侧之间没有边界;
[0169] 机器中没有执行引擎:每个机器包括大量执行元素,这些执行元素负责执行操作 并且每个执行元素还负责确定要执行的下一个操作,并且没有参与所有执行步骤的"中央 引擎";
[0170] 机器没有虚拟机模型:任何给定操作的实现不与特定虚拟CPU或对如何实现操作 加以任何限制的任何其它结构相关联,并且仅有的例外是存在用于实现函数调用的程序堆 栈,但没有用于机器内部调用的规定调用惯例;以及
[0171]机器不能被静态地分析:除了静态分析没有指令集的唯一机器的固有困难之外, 没有可辨别的程序并且没有机器模型,执行机器的过程完全依赖于序列敏感合并操作(如 下解释),并且在执行已到达该部分之前不能理解机器的任何部分(甚至不能由机器自身理 解)。
[0172] 根据一个实施例,如图2中所示,生成机器的过程包括以下步骤:
[0173] 操作重新表达步骤S21,其将由实现核心生成过程P1产生、根据小型统一指令集表 达的操作集变换成根据大得多的非统一指令集表达的操作;
[0174] 操作实现步骤S22,其产生从步骤S21获得的重新表达后的操作的实现;
[0175] 序列合并步骤S23,其变换操作实现以便利用序列敏感合并抵抗静态分析;以及
[0176] 代码生成步骤S24,其应用于由序列合并步骤S23产生的实现的所有分量,并且准 备以可执行形式被输出。
[0177] 尽管操作重新表达步骤S21的输出被称为具有指令集,但严格地说它没有资格作 为指令集,因为包含在每个指令中的子操作彼此没有有意义的概念关系(这种关系将允许 它们被提供统一名称以便在传统意义上如同指令那样被使用)。例如,"function call"指 令通常将包括子操作序列,这些子操作具有单独意义(例如将值推送到堆栈上,跳转到另一 个程序位置等),但还具有组合意义,该组合意义允许它们被共同表达为具有名称 "function call"的单个指令。现在考虑与指令(该指令将1234加到寄存器rO以形成新指 令)相组合的该函数调用序列。该新指令将必须被称为"ca 11 f unct ion&add 1234,r0"(或 类似事物)以便表示它执行的操作。如果说以这种方式组合十个或更多指令,则得到的新指 令名称将太复杂并且太具体而没有概念意义。
[0178] 为了实现所需变换,以两个步骤执行步骤S21;即,第一步骤一操作重写和第二步 骤一操作组合。第一步骤-操作重写-使用诸如不透明表达式、算术/逻辑重写和蛮力等效代 码生成之类的公知混淆变换,将操作序列变换成语义等同的备选形式。使用随机选择的混 淆变换,随机选择和变换操作序列。重复该过程直到已发生足够级别的变换。在该过程期 间,可以多次变换每个个体操作。该步骤的主要目的是降低代码的一致性以便进行第二步 骤。混淆变换的使用还有助于使结果代码更难以理解,但这不是整体过程的关键要素。
[0179] 第二步骤-操作组合-组合操作序列以便产生新指令集,其中每个指令表示被组合 以便产生指令的操作序列。组合过程的工作方式(根据每个函数)是:从第一操作开始,并且 选择随机数量的后续操作以便与第一操作相组合。这些操作被组合并且与新指令索引关 联。该过程然后移到下一个可用(非组合)操作并且将该操作与随机数量的后续操作相组 合,以此类推直到已处理所有操作。该步骤的目的是产生新指令集,其中在组成每个指令的 操作之间没有概念关系。这可以单独通过组合过程实现,但将组合过程应用于重写步骤的 非统一结果将产生有效得多的结果。
[0180] 上述操作组合步骤简单而有效,然而可以以各种方式对其改进。例如,当过程到达 函数的末尾时,可用于组合的操作数量将减少,其中最坏情况是从单个操作性质最后新指 令。这在实践中不可能造成重大问题,因为在该阶段代码的高度展开和内联性质将意味着 这影响相对微小的代码部分。如果这确实变成问题,则可以通过以下操作消除该问题:预计 算组合序列并且随机重新分布其边界,直到所有序列具有足够的最小大小。
[0181] 操作实现步骤S22产生来自前一个步骤S21的重新表达后的操作的实现。操作实现 包括以下部分:
[0182] 1.操作的子操作实现部分,它们被组合以便产生新指令;
[0183] 2.参数解码逻辑一可以在多个上下文中执行某些操作(大致相当于执行程序);这 些操作将接收参数形式的上下文特定输入和输出,这些参数针对每个操作被唯一编码;以 及
[0184] 3.执行连续逻辑一在已执行每个操作之后,对下一个操作及其上下文(如果有)解 码,并且然后通过该操作的实现继续执行。
[0185] 序列合并步骤S23变换操作实现以便利用序列敏感合并(如下解释)抵抗静态分 析。在该阶段之前,操作实现直接链接到彼此,并且每个操作实现对它自己的输入/输出和 合并参数静态解码。在该阶段之后,每个操作实现链接到解码器实现,解码器实现又链接到 下一个操作实现。解码器实现负责对下一个操作实现的位置及其参数解码,并且使用序列 敏感合并值,根据解码器实现对这些参数唯一编码。
[0186] 将通过操作实现继续链接的特定解码器实现是上下文特定的,即操作实现接收该 特定解码器实现作为参数,并且没有它将链接到的解码器的静态知识。该变换的结果是操 作实现通过上下文特定的动态解码器集(它们仅在使用点被解析)彼此分离,从而使操作序 列的静态分析极其困难。
[0187] 在已完成序列合并步骤S23之后,准备以可执行形式输出实现的所有分量。在最后 步骤S24-代码生成中,所有操作实现被共同呈现为独立源代码段,其能够被编译成现有项 目并被直接执行一这通常是C源代码但可以使用其它实现语言。
[0188] 过程P2涉及生成执行机器,该执行机器能够执行白盒实现。除了由在过程P1中执 行的其它白盒生成步骤使用的技术之外,该机器生成还使用步骤S21、S22、S23的混淆技术。
[0189] 执行机器的生成假设将在执行机器中的任何位置采用所有这些额外混淆。在某些 情况下仍然可以如此,但经验已显示这些混淆与由过程P1的其它白盒生成步骤使用的混淆 相比不太有效(就保护加密算法而言),并且在性能影响和代码大小方面属于最昂贵的混 淆。
[0190] 根据一个实施例,为了最大化最有效混淆的使用并且对整体性能/大小影响提供 更多控制,以可变混淆复杂性生成执行机器,其中复杂性可以在每个操作级别变化以便实 现最大控制。在最低复杂性级别,操作的已生成代码基本上是操作的简单C实现,在操作与 它处理的数据之间具有很少(如果有)重定向机制。在该复杂性级别生成的代码通常比在最 大复杂性生成的代码快10-100倍,并且还明显更小。对于任何给定操作,可以将复杂性级别 设置为最小与最大复杂性之间的广泛级别之一。当级别增加时,逐渐启用可用于机器生成 的各种混淆,其中最大级别采用所有可用混淆。
[0191] 尽管每个操作可以具有个体复杂性级别,但在实践中可以在更大粒度指定复杂性 级别,主要在输入代码中的每个函数级别,并且在某些情况下,在函数中的每个块级别处指 定复杂性级别。经由代码注释在输入代码中指定复杂性级别。还可以在全局基础上增加或 减小应用于输入代码的复杂性级别,从而允许以各种不同复杂性容易地生成执行机器。根 据一个实施例,实现简单线性伸缩操作,但非线性模型也是可能的。
[0192] 根据各实施例,序列敏感合并的概念用于多个步骤(334、343、323),并且对提供效 用起着重要作用。在高级别,序列敏感合并是一种方法,其允许程序元素依赖运行时生成的 数据(其看似具有随机性质),以使得仅当在程序元素执行时该数据恰好具有正确值时,程 序元素才被正确执行。该技术用于以某种方式使这些程序元素的逻辑和数据混淆,该方式 极其难以静态解析,因为直到正在实际执行程序元素才知道逻辑和数据的某一部分。为使 其工作,预先知道数据生成序列,以使得能够使用补偿操作修改使用数据的程序元素,这些 补偿操作将生成的数据变换成特定已知值而不在使用点泄露这些值。
[0193] 为了有效地防止静态分析,数据生成过程可以复杂到足以使攻击者不能预先预测 数据序列。这通过在程序中注入大量数据变异操作而实现,其中每个变异操作针对数据生 成缓冲器执行唯一操作序列。这些操作可以被设计为最大化数据缓冲器中的位的混合。
[0194] 操作之间的数据流混淆涉及组合真实和引诱操作的输出。可以进一步使数据元素 本身混淆以便防止提取有用的中间数据。中间数据混淆可以应用于在白盒内部产生的几乎 任何数据元素,并且在实践中,理想地应用于每一个数据元素。根据一个实施例,通过将每 个中间数据元素与混淆上下文关联,使实现的中间数据元素混淆,该混淆上下文对于该数 据元素是唯一的并且指定如何使数据元素混淆。例如,如果通过对数据元素加密而使其混 淆,则混淆上下文将包含该元素的加密密钥。当数据元素由操作写入时,将使用混淆上下文 使其混淆,并且当它由另一个操作读取时,将使用相同混淆上下文使其被解除混淆。这确保 将数据元素以混淆形式存储在存储器中,但是当针对数据元素操作时,将其转换成非混淆 形式。因为每个数据元素使用唯一混淆上下文(例如,如果加密,则每个数据元素将具有唯 一加密密钥),所以攻击者要想了解整体中间数据,他将必须针对每个个体数据元素打破混 淆,这通常不切实际。
[0195] 2.使用动态机密的白盒实现
[0196] 使用动态机密的白盒实现方法促进白盒实现的生成,其中机密数据是动态的,即 仅在运行时已知。静态密钥是白盒解决方案的基本要素。产生白盒的过程基本上涉及以难 以导出密钥值的形式,将静态密钥嵌入到加密算法的某一版本中。相比之下,动态密钥被传 递到白盒而不是已经被嵌入白盒中,后者违反了白盒的固有静态性质。根据一个实施例,可 以通过以下操作解决该问题:组合两个加密算法,并且从组合后的算法生成单个白盒实现。 执行该操作的能力是白盒生成(图2)方法针对任意加密算法操作的能力的结果,这自然包 括组合两个或更多算法的结果。
[0197] 为了将动态密钥Kd与选定算法Ad-起使用,首先使用合适的算法(例如AES)和对 应密钥Kaes对密钥Kd加密,以便产生已加密密钥Kde:
[0198] Kde = EncryptAES(Kaes ,Kd)
[0199] 为了简单起见,假设预先产生已加密密钥Kde,并且密钥Kd从未存在于其中运行白 盒实现的设备上。动态密钥Kd的已加密版本Kde可以被传递并且被存储在白盒外部而不泄 露动态密钥值。为了安全地使用动态密钥Kd,生成白盒实现,其将对已加密版本Kde解密以 便恢复动态密钥Kd。然后可以将动态密钥Kd与算法Ad-起使用以便执行选定操作。整体操 作如下所示:
[0200] output=Ad(DecryptAES(Kaes ,Kde), input)
[0201] 为了生成白盒实现,简单地组合算法DecryptAES与Ad的源代码并且产生顶级函 数,该顶级函数使用所述算法实现上面的操作。注意,如果算法Ad也碰巧是算法 DecryptAES,则输入代码将仅包含单个算法,顶级函数将调用该算法两次。白盒生成方法然 后将生成单个白盒实现,其在白盒的保护边界内将整个操作作为单个单元执行。相同机制 还将防止从白盒提取已解密密钥Kd,这些机制通过观察经过白盒的数据流而防止密钥导 出。
[0202] 上述方法是用于将动态密钥与白盒实现一起使用的数种可能方法之一,然而它们 全部共享在单个实现中组合两个或更多加密算法的通用要素。在单个白盒中组合多个算法 的通用概念的进一步扩展将是允许针对已加密数据执行操作而不泄露数据内容。这可以通 过以下操作实现:组合解密操作DecryptAES、针对数据的操作DataOp以及加密操作 EncryptAES,如以下实例中所示:
[0203] output = EncryptAES(Kaes ,DataOp(DecryptAES(Kaes, input)))
[0204] 3.防止上下文外使用
[0205] 攻击者可能采取两种主要方式以便试图在未由应用创建者指定的上下文中使用 白盒实现。
[0206] 攻击1:隔离实现并且将其复制到另一个程序中。这对于有能力的攻击者而言相对 轻而易举地完成。某些要素可能使该操作在实践中稍微更复杂一例如,可能必须将代码放 在特定存储器位置处以便执行它一但是有能力的攻击者将相当迅速地克服这些复杂性。
[0207] 攻击2:复制包含实现的整个程序并且直接从另一个程序调用该实现。可以通过几 种不同方式执行该操作,但关键要素是实现未与使用它的程序分离。在实践中,该攻击可以 比前一个攻击稍微更困难,但这在有能力的攻击者的能力范围内,并且在某些情况下可能 甚至更容易。
[0208] 根据一个实施例,可以通过以下操作防止攻击1:将完整性检查防篡改解决方案应 用于包含白盒实现的应用,以使得白盒代码包含防篡改检查,这些检查检验应用的其余部 分实际存在于预期存储器位置中。如果攻击者然后试图仅将白盒代码复制到另一个程序 中,则包含在白盒代码中的防篡改检查将失败并且代码将拒绝执行。为使该方式最有效,防 篡改解决方案应利用由白盒实现提供的大型代码主体,并且自动将大量完整性检查注入到 该代码中以尽可能使攻击者难以击败它们并且在上下文外使用代码。
[0209] 攻击2明显更难以防止,并且防止攻击2的方法使用部分在白盒实现外部的额外机 制。该额外机制是完整性检查防篡改解决方案的扩展,称为"上下文强制"。值得注意的是, 由该机制使用的基本方法的应用超出其在本公开中的使用。
[0210] 上下文强制背后的核心理念是在白盒实现的内部细节与使用它的程序之间引入 合并,以使得仅程序对白盒的预期使用将产生正确结果。在高级别,该过程涉及将合并产生 器注入到程序中,并且将合并目标注入到白盒实现中。当程序执行时合并产生器生成合并 数据,并且合并目标将该数据与在白盒实现内部执行的操作相组合。
[0211] 构造合并数据与白盒操作的组合以使得通过程序的正常执行产生的合并数据不 会导致白盒操作的结果变化,而异常程序执行(包括根本没有执行)导致操作产生不正确结 果。基本过程包括以下步骤:
[0212] 1.在应用中选择位置集以便用作合并产生器;
[0213] 2.对于每个合并产生器,注入产生合并数据的代码;
[0214] 3.在白盒实现中选择操作集以便用作合并目标;以及
[0215] 4.变换每个合并目标以便将合并数据段与其现有操作相组合。
[0216] 选定位置沿着到达白盒实现的一个或多个稀疏执行路径分布,并且这些稀疏执行 路径表示到达实现的所有可能路径的超集。例如,在具有到达实现的10个不同路径的简单 程序中,可以存在在所有10个路径中出现的3个位置。这3个位置表示到达实现的稀疏执行 路径,并且因此可以用作上下文强制的位置。另一个实例将是具有到达实现的10个路径的 简单程序,其中这些路径的一半全部通过相同3个位置,但另一半全部通过不同的3个位置。 该程序将具有用于两组3个位置的两个稀疏执行路径。稀疏执行路径可以交叉并且甚至彼 此"包含",没有关于它们的相对拓扑的限制。仅有的要求是到达实现的所有可能路径由至 少一个稀疏执行路径表示。
[0217] 每个产生器通常产生多个合并数据段并且将每个段存储在其关联存储位置中。存 储位置可以属于当前产生器或者在它之前执行的任何产生器。如果位置属于当前产生器, 则它将初始化该位置并简单地将数据写入该位置。如果位置属于前一个产生器,则将当前 合并数据与已经在该位置处的数据相合并。以多种方式产生合并数据。最简单的方法涉及 执行变换(静态产生的)随机输入值的唯一已生成操作序列,并且使用这些操作的结果作为 合并数据。还可以通过以下操作产生合并数据:组合其它合并数据段(例如由先前产生器产 生的数据)并且使用由应用本身产生的选定值。当程序包含多个稀疏执行路径(几乎所有不 简单程序都将如此)时,也构造合并产生器以使得所有稀疏路径产生相同合并数据集。没有 这一点,白盒实现将仅从一个稀疏路径(最多)正确地操作。
[0218] 选择步骤通常优选对整体加密操作具有重大影响的操作。但是,因为这可以针对 许多加密算法产生选择群集,所以还优选地在实现中尽可能多地分布选定位置。另一个重 要选择准则是操作对支持合并变换的适合性。尽管并非所有操作都将是有效目标,但许多 操作在实践中是有效目标并且它们在实现中良好分布,因此该准则对其它准则具有很小的 影响。构造每个变换以使得仅合并数据的预期值将导致操作产生的结果与变换之前产生的 结果相同。所有其它值将产生不正确结果。
[0219] 为了防止攻击者简单地在使用合并数据之前转储合并数据并且然后在出于他自 己的目的而使用白盒之前重新产生该数据,以一种使转储相当困难的方式存储合并数据。 每个合并数据段具有不同位置,该位置由一个特定合并产生器(每个稀疏执行路径)拥有并 且可由需要更新它的其它产生器访问。存在几种不同类型的位置:
[0220] ?静态位置,其通常位于存储器中程序的可写入部分中,更像全局变量;
[0221 ] ?堆位置,其通过堆分配动态产生;以及
[0222] ?堆栈位置,其经由堆栈移位动态产生。
[0223] 堆栈位置可以仅由在到达白盒实现的调用路径(与执行路径相反)上的合并产生 器使用。始终通过已存储指针值访问位置,这些指针值针对每个位置被唯一编码。每个产生 器知道如何对它使用的指针值解码。以这种方式存储合并数据使得攻击者更难以成功定位 和转储所有位置数据,并且还使得更难以在稍后正确地重新产生数据。
[0224] 4.防止通过隔离小部分算法的攻击
[0225] 攻击算法的白盒实现的一种最有效方法是在白盒中隔离已知以某种方式针对机 密数据(例如加密密钥)操作的小部分算法,并且然后针对该部分算法使用蛮力攻击以便提 取机密。这是有效的,因为加密算法仅被设计为在其整体上对于蛮力不实用;在大多数情况 下,这些算法的个体部分对于经由蛮力的攻击非常实用。
[0226] 用于隔离算法部分的极其有效的方法是分析算法实现的存储器访问模式。大多数 加密算法具有公知的执行模式,这些执行模式通常在其对应存储器访问模式中相当准确地 反映出来,并且因此甚至通常可以使用存储器访问模式的简单可视化以足够粒度隔离算法 部分以便帮助蛮力攻击。
[0227] 例如,AES块密码算法执行10、12或14轮相同操作序列。这显示为相关存储器访问 的10/12/14个块的对应序列,当可视化时它们很容易被定位。攻击者可以使用该操作隔离 最后两轮,并且然后使用已知方法通过观察这些轮的输入和输出来导出AES密钥。
[0228] 根据一个实施例,通过消除攻击者可以赖以隔离加密操作的个体部分的访问模 式,使该类型攻击更困难。存储器访问模式消除可以通过以下操作实现:在算法的白盒实现 中注入额外随机化存储器访问操作。这些操作访问由真实操作访问的相同存储器位置集, 但使用随机化顺序和分布完成该操作,这种随机化顺序和分布添加足够的噪声以便掩藏由 真实操作展示的任何模式。
[0229] 根据一个实施例,存储器访问模式混淆被实施为上述引诱生成的扩展。该扩展包 括生成更大数量的引诱,其中额外引诱作为存储器访问操作的副本产生。还可以通过不透 明表达式将这些额外引诱与真实操作组合,但在实践中,它们中的大部分可能不按顺序以 便降低其对性能的影响。
[0230] 根据一个实施例,存储器布局混淆与存储器访问模式混淆一起执行,以便对通过 隔离小部分算法的攻击提供额外保护。不同于存储器访问模式混淆(其设法通过引入噪声 使访问模式混淆),存储器布局混淆通过随机化数据片段在存储器中的位置来达到其目标。 [0231 ]如果没有布局模糊,则相关数据段通常彼此并存,与访问它们的操作一样,这在被 可视化时导致可辨别的访问模式。尽管存储器访问模式混淆通过引入的噪声而使这些模式 难以观察,但它们仍然存在。通过随机化由真实操作在存储器中访问的数据片段的位置,将 相关数据段彼此分离,从而破坏由真实操作展示的任何模式。
[0232] 相对于示例性实施例描述了本发明。因为可以在上面的结构中进行某些更改而不 偏离本发明的范围,所以在上面描述中包含或者在附图中示出的所有事物旨在被解释为示 例性的而非限制性的。
[0233] 本发明并不专门应用于加密算法或操纵机密数据的算法,而是可以应用于任何算 法。
[0234] 还要理解的是,以下权利要求将覆盖在此描述的本发明的所有通用和具体特性, 并且本发明的范围的所有语句(事实上为语言)可被称为落入其间。
【主权项】
1. 一种生成以存储在存储器中的代码形式表达的算法的受保护实现的计算机实现的 方法,所述方法包括: 将实现所述算法的原始源代码扩展成单个真实操作集; 将使用真实数据的每个真实操作与每个真实操作所使用的真实数据相组合,以获得以 这样的方式表示的组合:该方式以不同于原始形式的形式使用实际真实数据片段; 产生应用于引诱数据的表示所述算法的备选实现的重复和变异引诱操作集; 将所述引诱操作集与包括所述组合的所述真实操作集相组合,以便获得其中所述引诱 操作与所述真实操作和由所述真实操作处理的所述真实数据交互的实现,以使得难以分析 所述实现中的真实数据流;以及 将所述实现变换成被存储在所述存储器中并且能够被执行的结果代码。2. 如权利要求1所述的方法,其中所述算法是加密算法并且所述真实数据包括机密数 据。3. 如权利要求1或2所述的方法,其中扩展所述算法包括: 由仿真器执行所述原始源代码,并且记录正在被执行的操作、发生的控制流改变以及 发生的对存储器的改变; 通过由所述仿真器使用不同运行时输入多次执行所述原始源代码并且将这些执行的 结果组合成所述真实操作集来恢复在执行期间未被执行的代码;以及 由所述仿真器通过将在所述执行期间未被执行的缺失代码注入所述真实操作集中来 协调所述缺失代码。4. 如权利要求1至3中的一项所述的方法,其中扩展所述算法包括产生对所述真实操作 集中的操作与在所述真实操作间流动的数据值之间的数据依赖性建模的数据依赖性图。5. 如权利要求3或4所述的方法,其中扩展所述算法包括消除所述真实操作集中产生静 态已知值的操作,所述产生静态已知值的操作包括针对所述真实数据的操作,以使得所述 真实数据的每个部分仅以最终导出形式存在并尽可能深入地被传播到结果真实操作集中。6. 如权利要求3至5中的一项所述的方法,其中扩展所述算法包括减小所述真实操作集 的大小,方式为:消除通过所述仿真器的执行生成的所述真实操作集的一部分内联函数代 码和展开循环,使用来自所述原始源代码的函数调用和循环替换这些内联函数代码和展开 循环,使用为函数和基本块分配得分的决策模型,所述得分表示与通过这种消除发生的真 实数据传播损失的成本相对的通过消除内联和/或展开获得的收益水平。7. 如权利要求1至6中的一项所述的方法,其中扩展所述算法包括: 将涉及导出的真实数据的所述源代码的原始操作拆分成多个新操作,以使得每个新操 作使用一段所述导出的真实数据; 将各段所述导出的真实数据变换成产生各段所述导出的真实数据块的唯一操作子集, 其中这些操作子集使用在运行时生成的序列敏感数据值;以及 将所述操作子集插入到所述真实操作集中。8. 如权利要求1至7中的一项所述的方法,其中产生重复和变异引诱操作集包括多次重 复扩展步骤以便产生多个引诱操作集,其中为每个引诱操作集供应随机生成的数据而不是 所述真实数据,以便产生表示所述算法的备选虚假实现的多个引诱操作集。9. 如权利要求1至8中的一项所述的方法,其中将所述引诱操作集与所述真实操作集相 组合包括: 使来自每个集合的操作与来自所有其它操作集的操作相交错以获得组合集,使得当所 述组合集被执行时,同时有效地执行所有操作集;以及 通过逐渐选择多组操作并且通过将每个输出转发到正确接收操作的新生成的路由操 作路由所述多组操作的输出,将来自所述组合集中不同集合的操作的数据流彼此合并,由 此使用唯一生成的不透明表达式来构造路由操作,所述唯一生成的不透明表达式使用在运 行时生成的序列敏感数据值。10. 如权利要求1至9中的一项所述的方法,其中根据小型统一指令集表达所述实现的 操作,变换所述实现包括: 使用公知的混淆变换将所述实现的操作序列变换成语义等同的备选形式; 组合变换后的操作序列的操作以便定义包括新指令的新的大得多的非统一指令集,每 个新指令被定义为与所述操作序列对应的个体函数,组合所述个体函数以产生所述新指 令;以及 使用新指令集变换所述实现,以便获得包括操作的变换后实现,每个操作对应于所述 新指令集的指令。11. 如权利要求1至10中的一项所述的方法,其中变换所述实现包括生成执行控制代 码,所述执行控制代码导致以正确序列并使用正确数据执行所述操作以便执行所述算法, 其中由解码器功能集控制执行,每个所述解码器功能被与一个操作关联,对于该操作,每个 解码器功能知道执行该操作需要的数据的位置、对应指令功能的位置,以及如何对针对每 个解码器功能唯一编码的该数据解码。12. 如权利要求11所述的方法,其中所述解码器功能使用在运行时生成的序列敏感数 据值。13. 如权利要求1至12中的一项所述的方法,其中变换所述实现包括根据复杂程度启用 混淆,当将所述复杂程度设置为最大值时,启用在变换步骤可用的所有混淆。14. 如权利要求1至13中的一项所述的方法,包括生成所述算法的新白盒实现,其中仅 在运行时才知晓机密数据,所述生成包括将所述实现与使用静态密钥的解密算法组合成使 用动态机密数据的所述新白盒实现,所述动态机密数据被使用所述静态密钥预加密,所述 解密算法解密传输到所述实现的所述动态机密数据。15. 如权利要求1至13中的一项所述的方法,包括生成新白盒实现,所述新白盒实现针 对已加密数据执行数据处理操作而不泄露所述已加密数据的内容,所述生成包括将解密算 法、所述实现以及加密算法组合成所述新白盒实现,其中所述解密和加密算法是彼此的逆 算法并且使用相同静态密钥,由此所述解密算法对要处理的数据解密,所述实现针对所述 已解密数据操作并且所述加密算法重新加密所述数据。16. 如权利要求1至15中的一项所述的方法,包括防止在除包含所述实现的程序所指定 的上下文之外的上下文中使用所述实现,所述防止包括: 通过将随机生成的数据或真实数据与现有合并数据相混合,将合并产生器注入到所述 程序中,其中当所述实现执行时所述合并产生器生成合并数据;以及 将合并目标注入到所述实现中,其中所述合并目标读取合并数据并将这些数据与由所 述实现内部的操作使用的静态数据相组合,并且其中修改由所述操作使用的所述静态数据 以使得它们不正确并且仅当将它们与所述合并数据组合时才产生所述正确数据,从而使得 所述操作依赖于通过所述程序的执行被正确地生成的所述合并数据,其中每段合并数据具 有不同位置,该位置仅对需要修改该段合并数据的所述合并产生器已知并且仅对所述实现 中的所述合并目标已知。17. 如权利要求1至16中的一项所述的方法,包括混淆每个中间数据元素,并且将每个 中间数据元素与对于该数据元素唯一并指定如何混淆该数据元素的混淆上下文相关联。18. 如权利要求1至17中的一项所述的方法,包括在所述实现中注入额外随机化的存储 器访问操作以便掩藏由所述真实操作展示的存储器访问模式。19. 如权利要求1至18中的一项所述的方法,包括随机化由所述真实操作在存储器中访 问的所述真实数据的数据片段的位置。20. -种存储应用的非瞬时性计算机可读介质,所述应用适于在设备上运行并且通过 将如权利要求1至19中的一项所述的方法应用于程序而生成。21. -种用于保护以代码形式表达的算法的设备,所述设备被配置为实现如权利要求1 至19中的一项所述的方法以便生成所述算法的受保护实现。
【文档编号】G06F21/62GK106030604SQ201580005193
【公开日】2016年10月12日
【申请日】2015年1月21日
【发明人】N·斯图尔特
【申请人】麦塔福里克有限公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1