具体实施方式
很明显,需要这样一种方法和系统:通过它可以使构造使用白盒密码功能的应用程序的周围隐含和相互隐含部分的步骤自动操作,从而使得当前用于构建这种系统的容易出错的方法可以由相当可靠的自动化方法来代替。为了实现这一点,公开了一些实施例,在这些实施例中,应用程序的普通内部隐含(intra-cryptic)部分(实际执行白盒运算的部分)与这些部分的惯常情况相比变得更加灵活,以适应于上述自动化系统。
这种系统的好处类似于通过编译代码而非写手工汇编代码所得到的好处。理论上,好的程序员应该能够以手工汇编代码的方式写应用程序。然而,实际上手工汇编代码极其容易出错,并且编译器通过将低级的、高度详细的软件构造体制(regime)用更为自动化的软件构造体制来替代,使得在汇编代码级别从未实现的复杂性的软件系统成为可能。
本申请的一方面是要提供这样的系统和方法,通过它可以对白盒实现的周围隐含和相互隐含方面进行抽象并使之自动操作,使得其用户可以实现在之前通过周围隐含和相互隐含的手写编码软件要么难以实现要么不可实行的复杂性的级别上的白盒加密实现的使用,同时还通过使它们更易于为程序员/用户创建,而有益于甚至更简单地使用白盒密码术,正如非常简单的程序通过用从诸如C++之类的高级语言的源代码编译的代码取代手工汇编代码而受益。
这种自动操作的一方面是对表达不同形式的密码功能所采用的方式的统一。例如,在诸如C++之类的编译语言中,相同的句法形式用于加法,无论正在被加的是两个整数、两个浮点数还是两个复数。该语言及其编译器将加法抽象为针对它所使用的每种环境适当地实现的概念,不管该实现是内置于该编译器(当它用于整数和浮点数时)还是标准库的一部分(当它用于复数时)。针对白盒密码运算,这里公开了类似的统一:如果每个密码运算具有它自己唯一的接口并且需要它自己唯一的表达方式,则程度小的自动化是可能的;进行适当选择的许多职责必需属于程序员/用户。如果接口和表达方式被统一,则系统可以从特定的密码中抽象出来并且以自动化方式处理每种环境的需要。
相应地,公开了使安全性相关参数与用户定义的软件分离的实施例,其中用户定义的软件包括用于访问白盒库工具的API调用。这允许简单通过改变参数而不需要改变用户定义的软件而容易地改变应用于应用程序的保护的类型和安全级别。这允许现场升级能力,其中安全实现和代码可以被改变,或者额外的工具和/或保护级别可以被使用。在黑客攻破安全性的情况下,这种系统可以进行如下响应:通过改变参数并重新编译应用程序而向黑客提供新的和/或额外的挑战。
当前优选的实施例提供了对许多多样安全性实现的可能使用,许多安全性措施对于每个应用程序来说是可能的。这有益于确保对一个实现的成功攻击不会变成对使用白盒密码术的给定软件应用程序的所有或许多实现的成功攻击。
一般而言,所公开的实施例提供了计算机实现的用于将白盒密码术集成到软件文件中的方法和系统,其包括将API与用于加密、混淆或以其它方式保护应用程序或文件的参数分离。通过使用可以在应用程序中应用并且被白盒加密实现所理解的数据转换,这种集成的开发套件的特别的好处是对密码应用程序和周围应用程序之间的边界进行保护。
在下列描述中,为了说明的目的,各种细节被阐述以便提供对本发明的充分理解。然而,对于本领域技术人员来说明显的是,为了实践本发明,并不需要这些具体细节。在其它情况下,公知的电结构和电路以框图的形式示出,从而不会使得本发明难以理解。例如,关于这里描述的本发明的实施例是实现为软件例程、硬件电路、固件还是它们的结合,并没有提供具体细节。本发明的实施例可以被表示为存储在机器可读介质(也称为计算机可读介质、处理器可读介质或者其中嵌入有计算机可读程序代码的计算机可用介质)中的软件产品。机器可读介质可以是包括磁、光或电存储介质的任何合适的有形介质,包括磁盘、只读光盘存储器(CD-ROM),存储器设备(易失性的或非易失性的),或者类似的存储机制。机器可读介质可以包含各种指令集、代码序列、配置信息或其它数据,其在被执行时使得处理器执行根据本发明的实施例的方法中的步骤。本领域技术人员会理解的是,还可以在机器可读介质上存储为实现所描述的发明所需的其它指令或运算。从机器可读介质中运行的软件可以与电路交互以执行所描述的任务。
在整个该文献中,术语“白盒”频繁地用作前缀,从而创建了像“白盒调用”、“白盒库”、“白盒函数”等术语。当用作这种前缀时,术语“白盒”是“被设计为提供对抗白盒攻击者的安全性的密码实现”的简写。类似地,术语“白盒密码术”本身是“被设计为提供对抗白盒攻击者的安全性的密码实现”的简写。清楚的是,“白盒”前缀决不是指该项本身;因为所描述的实施例在软件环境中运行,所以假设这些实施例和用户的应用程序对于攻击者来说是一目了然的事;换句话说,它们是白盒。事实上,这些术语只是另一种简写。例如,“白盒库”是包含提供对抗白盒攻击者的安全性的密码函数的实现的库,或者稍微更加简便地,是包含白盒密码术的库(因此,这里我们明白“白盒库”怎么是双重简写)。“白盒函数”是白盒库中的函数之一。“白盒函数调用”或者仅仅“白盒调用”是对白盒函数的调用。其它术语应当被类似地进行解释。
所描述的实施例将白盒密码术集成到软件开发套件中。参见图1,在非常高的级别处,根据本发明的将白盒密码术集成到应用程序中涉及用户对在他们的全部应用程序中的密码功能和重要安全性参数流进行功能性的和健壮性相关的若干次选择。如在100处示出的,用户将抽象的调用(示出为wbfunc(...))添加到白盒API以实现所期望的密码功能,并且还在他们的全部代码中添加命令以识别重要安全性参数所需要的保护。然后,利用若干白盒工具和库(步骤102)创建健壮的代码104,健壮的代码104可以被编译并链接(步骤106)到白盒库108以创建可执行文件109,可执行文件109以安全方式执行密码运算,并且在全部应用程序的整个数据流中保护重要安全性参数。
然而,在概念上,更容易将该过程理解为演化,其中用户首先对他们的应用程序中的密码功能和密钥流进行并实现最基本的选择,然后,进一步提炼这些功能参数并最终采取措施增加健壮性。在每个阶段,存在编连(build)并测试应用程序的能力,并且在最后,用户调整健壮的应用程序并且可选地使每个编连个性化。图2中示出此扩展的设计流程,并且涉及存根(stub)编连110、平滑(smooth)编连112以及健壮(robust)编连114。存根编连110和平滑编连112是可选的,并且仅仅以宽泛的术语进行描述。如本领域技术人员应当清楚的是,它们的实现是设计选择,并且在这里仅仅为了示出根据本发明的白盒应用程序开发流程的实施例的目的进行讨论。
在存根编连110中,用户将白盒函数调用添加到合适的白盒密码API以添加诸如对称加密、非对称加密以及散列之类的功能,从而创建输入源文件100。用户依赖在白盒存根库118中定义的白盒调用的存根实现,对他们的程序进行编译和链接(步骤116)以生成存根可执行120,然后对存根可执行120进行测试(步骤122)以检查编译和链接错误,以及密钥流中的基本错误。存根库118中实现的存根加密函数是简单的,但是以加密和解密彼此不太可能互逆除非将匹配参数传递给两个函数的这种方式进行构造。例如,动态密钥解密必须使用与动态密钥加密相同的密钥,以便恢复原始消息。如果这些密钥由于编码错误而不相同,则存根解密不太可能正确地解密存根加密的结果以产生原始消息。
在平滑编连112中,用户进行一些初始的、功能性相关的选择以使每个调用参数化,并且创建详细说明那些选择的白盒参数化文件124。然后,用户应用代码生成工具(步骤126)以应用所进行的选择,并且依赖在白盒库130的平滑版本中定义的白盒调用的平滑实现来编译并链接(步骤128)他们的程序。白盒库130的平滑版本仅指实现与真的白盒库相同的API的库,但其是平滑的。然后,所得到的平滑可执行132可以被测试(步骤134)以确保基本的功能性正在正确地工作。
在健壮编连114,用户在他们的受保护的应用程序中进行关于尺寸、速度和安全折衷的选择。用户应用下面详细说明的白盒加密工具(步骤136),以生成健壮的转换后的代码138。然后,该健壮的转换后的代码138被编译并链接(步骤140)以保护在白盒库144中的白盒调用的实现以生成受保护的可执行146。然后,该受保护的可执行可以被测试(步骤147)以确保功能性和安全性。然后,用户为了个别化目的利用更轻便的过程可选地生成(步骤148)数据的许多多样实例149。
参见图5和图6,现在将更详细地描述健壮编连的过程和组件。图5提供健壮编连的简化概述,而图6示出下面详细描述的详细实现的实施例。
图5的实施例包括三个模块,用于产生例如软件应用程序文件的受保护的文件,该三个模块即白盒代码生成工具(wbcodegen)150、数据转换引擎(xcode)152以及白盒数据生成工具(wbdatagen)154。在白盒密码术环境中,数据转换引擎152用于保护密码运算与周围代码之间的边界。具体而言,数据转换引擎152用于将数据转换应用到密码运算的输入和输出。如果用户经由白盒参数化文件124指定需要转换,则wbcodegen 150将由用户指定的信息翻译成数据转换引擎152理解的形式,即作为有关数据变量和函数原型的修饰符。然后,数据转换引擎152应用所指定的转换,并且将关于选择什么转换的信息传递给wbdatagen 154。
用于实现这个的数据流在图5中以高的级别示出。白盒代码生成工具150接收包括应用程序源代码和抽象的白盒函数调用的至少一个输入源文件100(useCode)以及包含用于每个抽象的白盒函数调用的密码域参数的参数化文件124。白盒代码生成工具150根据每个抽象的白盒函数调用的加密域参数并且以数据转换引擎152会理解的方式处理这些输入,以生成用于定义每个抽象的白盒函数调用的白盒调用定义数据156(wb glue.c)。然后,数据转换引擎152将一个或多个数据转换应用到输入源文件100以及白盒调用定义数据156,以生成转换后的源文件160和转换后的白盒调用定义数据158(wb.xwbm)。然后,数据生成工具154根据转换后的白盒调用定义数据158生成包含用于每个白盒函数调用的特定实例数据的数据初始化162(wb-gluedata)。然后,数据初始化162和转换后的源文件160可以利用本地编译器进行编译并链接到白盒库。
白盒API
一旦用户已识别在他们的应用程序中需要加密,针对他们将会进行的对API的每个调用,他们具有两种选择。这些选择将会确定他们的应用程序的基本密钥流。(1)待执行的密码运算是什么?可能的运算包括加密、解密、签名、签名验证、散列等等。(2)用于该调用的密钥将仅在运行时可用还是将在之前可用?诸如会话密钥或内容密钥之类的密钥通常要么被动态地产生,要么作为非对称解密的结果被计算出。我们宽泛地称这种密钥为动态的。在另一方面,在编连时已知的或者可以通过一些离线签约/更新过程获取的密钥被称为固定密钥。当然,所有的密钥可以被处理为动态的,但在密钥可以被处理为固定的情况下,这样做具有安全性的优点。
一旦已经做出上述决定,用户应用程序代码可以被写成调用适合于该选择的API。作为输入源文件100的用户应用程序由源代码(例如用C或C++)组成,该源代码包含使用非常最小化的API对诸如密钥调度、加密、解密等等之类的密码运算进行的调用。诸如密文、明文、iv(初始化向量)等等之类的密钥用户提供数据作为参数,连同用于将相关的调用分组成单个密码域的数值常量ID参数一起,被传递给这些调用。在优选的实施例中,用户应用程序代码将需要包括包含文件170:xc/xc_wb.h,其定义白盒类型和宏。所有密码运算可以利用来自该包含文件170的宏来调用。优选地,白盒包含文件170(xc/xc_wb.h)为所有密码类型的密码运算中的每一个提供单个宏定义。这些宏将用户供应参数(通常诸如明文/密文之类的应用程序数据)的最小集、单个ID参数(用来识别运算的密码域)以及选项参数作为参数。例如,下面示出块密码加密调用。请注意,宏调用(XC_Fixed_Key_Block_Cipher_Encrypt)是非常抽象的,并且仅仅指定密码运算所需的实际应用程序数据。
#include″xc/xc_wb.h″
XC_Octet plain[16];
XC_Octet cipher[16];
int csize;
int ret;
/*Load plaintext into plain*/
ret=XC_Fixed_Key_Block_Cipher_Encrypt(1,plain,16,cipher,&csize,
NULL,0,NULL);
if(ret!=XC_OK){
/*issue error*/
}
/*Process ciphertext*/
白盒包含文件170(xc/xc_wb.h)从用户的应用程序代码的角度定义整个白盒API。该API采用类似函数的宏形式,该宏对可用于应用程序代码的所有抽象密码运算进行定义。此外,该包含文件170再次以宏定义的形式描述以下描述的白盒粘合(glue)文件的内容。下列示例性代码片断示出用于固定密钥、块密码加密运算的单个抽象API的高级细节:
__
#ifdef XC_WB_INFO
//Definitions common to Smooth and Robust invocations;
#define XC_Fixed_Key_Block_Cipher_Encrypt(ID,PLAIN,PLAINSIZE,CIPHER,
PCIPHERSIZE,IV,IVSIZE,OPTIONS)\
<XC_Fixed_Key_Block_Cipher_Encrypt>\
_XC_TCGEN(_XC_GLUE,ID,MAIN,cat(XC_Fixed_Key_Block_Cipher_Encrypt_,ID),\
_XC_TCGEN(_XC_ASSERT,\
FunctionType=BlockCipher\
KeyLocation=Fixed\
Operation=Encrypt\
)\
XC_Block_Cipher_Glue(ID,)\
)
#define XC_Block_Cipher_Glue(ID,SUBOP)\
XC_Block_Cipher_Externs(ID,SUBOP)\
int MangledName cat(XC_Block_Cipher_Op_Prefix(SUBOP),Prototype){\
return XC_Block_Cipher_Main_Invocation(ID,SUBOP){\
cat(XC_Block_Cipher_Op_Prefix(SUBOP),Base_Params)(ID)\
XC_Block_Cipher_Additional_Params(ID,SUBOP)\
};\
}
#ifdef XC_WB_SMOOTH
//Definitions of such sub-macros as XC_Block_Cipher_Externs etc.
//for a Smooth implementation
#else /* not XC_WB_SMOOTH*/
//Definitions of such sub-macros as XC_Block_Cipher_Externs etc.
//for a Robust implementation
//All_Params macros generated by XC_Robust*_Prefix are defined here:
#include″xc_wb_bc_dk_aes_keysched_tables.h″
#include″xc_wb_bc_fk_aes_tables.h″
#include″xc_wb_bc_dk_aes_tables.h″#endif/*XC_WB_SMOOTH*/
#endif/*XC_WB_SMOOTH*/
#else/*not XC_WB_INFO*/
//This section is for normal macro-expansion
//xcWBCodeGen is not in play,and thus_XC_TCGEN()operators may not
appear
#ifdef XC_WB_STUB
//Stub build
#define XC_Dynamic_Key_Block_Cipher_Encrypt_Key_Schedule(ID,KEY,
KEYSIZE,PRKS,OPTIONS)\
XC_Dynamic_Key_Block_Cipher_Encrypt_Key_Schedule_Stub(ID,KEY,
KEYSIZE,PRKS,OPTIONS)
#else/*not XC_WB_STUB*/
//Smooth or Robust build(these are identical at macro-expansion level)
#define XC_Dynamic_Key_Block_Cipher_Encrypt_Key_Schedule(ID,KEY,
KEYSIZE,PRKS,OPTIONS)\
cat(XC_Dynamic_Key_Block_Cipher_Encrypt_Key_Schedule,ID)(KEY,
KEYSIZE,PRKS,OPTIONS)
#endif/*XC_WB_STUB*/
#endif/*XC_WB_INFO*/
经常在隔离时并不执行密码函数。代替地,应用程序包含一连串通常采用层次结构的密钥,并且进行链式加密运算,层次结构中最低的密钥用于保护内容,而更有价值的密钥用于保护较低级的密钥。在层次结构的顶部,会有一个或多个“可信根(roots of trust)”,即其公开将会暴露其它全部密钥从而导致安全性完全被攻破的密钥。
层次结构的简单实例将会具有诸如音乐文件之类的内容,这些内容利用具有称为内容密钥的随机密钥的AES加密进行保护。该内容密钥本身将会利用具有客户端指定的公钥的RSA加密进行保护。然后,该可信根是(经常固定的)RSA私钥,RSA私钥为客户端应用程序的一部分。图3中示出该层次结构。一般而言,一个加密运算的输出成为随后加密运算的输入之一的任何场景被称为链式加密。另一频繁出现的链式加密的示例也被称为转换加密(transcryption)。这涉及使用一个算法和密钥对一些内容进行解密,接下来使用另一算法和密钥立即对同一内容进行重新加密。这经常在彼此通信的两个程序之间的边界处进行,或者在软件和硬件之间的边界处进行。
在将链式加密运算考虑为单个运算时,存在明显的安全性好处,即从一个运算传递到下一运算的值可以被很好的隐藏,这与在这两个运算之间的边界处被暴露正好相反。虽然在运算之间的边界处转换该值当然也是可行的并且确实提供了保护,但是链式运算的真正混合(blending)在可以应用的安全性技术方面提供更大的灵活性,从而提供更好的全面保护。
这里描述的白盒基础结构和API可以容易地被扩展以支持多种链式加密场景。下面给出具体示例。该示例对应于图3的客户端侧,被修改为将RSA解密和AES解密结合成单个链式解密。图4示出这个改变。请注意,被解密的内容密钥不再出现在该图中。该示例仅仅是示例性的。
#include″xc/xc_wb.h″
XC_Octet ekey[128];
XC_Octet cipher[65536];
XC_Octet plain[65536];
int psize;
int ret;
/*Load encrypted content into cipher*/
/*Load encrypted content key into ekey*/
ret=XC_Fixed_Key_Chained_Cipher_Decrypt(2,cipher,65536,plain,&psize,
ekey,128,NULL);
if(ret!=XC_OK){
/*issue error */
}
/*Process plaintext*/
白盒参数化
一旦用户已经使他们的密钥流生效,则他们不得不进行一连串的功能选择以进一步使每个白盒加密函数调用参数化。这些问题中的大部分是密码特有的,但是一般问题中的一些示例为:(1)需要什么算法?经常,使用的算法由某些相关标准指定。(2)需要什么尺寸的密钥?这里的有效选择取决于该算法。这些决定在用户提供的白盒参数化文件124中被捕获,然后,白盒参数化文件124连同用户的源代码一起被处理,以便构建可执行文件。
用户对密码运算的特定方面进行选择所依据的主要机制(基础到使用哪个算法,并且详细到使用哪个密钥)是经由白盒参数化文件124。由用户写的该文件提供了关于对白盒函数的每个调用的细节。在实施例中,白盒参数化文件124的格式是面向行的文本,由密码域参数名和密码域参数值组成。这些参数名/值对(下文称为“密码域参数”或简称为“参数”)被分组以组成独立的白盒参数化记录。每个记录的开始是以标识符(ID)参数的存在来划界的,并且在标识符下一次出现(或文件结束)时结束。在参数化记录的范围内,可以列出任意数目的唯一参数(任何参数名的重复都是错误)。正如本领域技术人员将会理解的,某些参数可能被省略,并且可以具有缺省值,而其它参数是强制性的并且必须被提供。在任何情况下,独立的参数的范围仅仅在于当前的参数化记录。
ID参数的值用于识别白盒调用。同样,优选的是:
1、ID是字面值整数常量,使得给定的调用一致地映射到参数化文件124中的给定记录。
2、每个调用被给定唯一的ID,使得参数化文件124中的给定记录映射到唯一的调用。这个规则可以有例外:
a、选择用来共享数据的调用必须被给定相同的ID。
b、其它的密码特有的例外。
对于每个ID,白盒参数化文件124会包含一记录,该记录将会列出与该记录相关的某些参数,文件的每行列出一个参数。白盒记录的参数可以被分成三个宽的种类:
●分类参数:这些参数描述有待使用的密码算法的种类,例如,块密码或非对称密码以及固定密钥对动态密钥。这些参数用于双重目的;第一,在用户可以看见这种记录并且确切地知道相应的白盒调用的行为将会是什么的意义上,它们使参数化文件记录自包含,并且第二,当这些参数的指定准确地确定哪些用户提供的参数被期望时,它们允许进行错误检查。
●功能参数:这些参数描述有待使用的密码算法的特定属性,例如循环(round)的次数,并且将作为参数或选项传递给白盒API(这被自动执行并且对终端用户是透明的)。请注意,算法(Algorithm)被认为是功能参数(例如Algorithm=AES对Algorithm=DES),并且不是分类参数。
●健壮性参数:这些参数描述与白盒调用的健壮性特点相关的具体决定,例如,对所选择的参数的转换。
最高级别的分类参数是FunctionType(功能类型)。其它有效分类参数以及功能和健壮性参数取决于为FunctionType指定的值。下列示例示出用于块密码的典型白盒参数化条目(entry)。所列出的参数中的大部分是密码特有的,并且它们的意义在这里没有进行描述。
Identifier 1
FunctionType BlockCipher
KeyLocation Fixed
Operation Encrypt
Algorithm AES
Mode ECB
FixedKey 00000000000000000000000000000000
KeySize 16
KeyType Standard
NumRounds 10
在这点上,用户必须进行若干安全性相关的选择。在可能的情况下,应当转换对白盒密码函数的调用的所有输入和输出。具体来说,对于块密码,应当转换明文、密文、密钥(用于动态密钥函数)和初始化向量(用于ECB之外的模式)。作为示例,按安全性的升序,可用转换的集合可以是:
转换族 |
性能 |
Finite(有限的) |
高 |
ArrayFinite(有限数组) |
高 |
LinearMBA(线性MBA) |
中 |
MultiMBA(多个MBA) |
中 |
RandomByte(随机字节) |
高 |
ArrayRandomByte(随机字节数组) |
高 |
RandomMatrix(随机矩阵) |
低 |
RandomMatrixAndByte(随机矩阵和字节) |
低 |
优选地,所有的数据转换可以用在输入和输出上。用户可以为白盒参数化文件124中的输入和输出指定逻辑转换类型。例如,用户可以为给定的id指定下列条目:PlainTransform blue(明文转换蓝)。这表示与该给定ID对应的调用的明文将利用“蓝”逻辑转换类型进行转换。待转换的所有密码输入和输出必须在白盒参数化文件124中具有合适的Transform(转换)条目。许多白盒函数,最著名的白盒AES,可以以若干不同的方式被实现。被称为加密类型的这些方式中的每一方式在尺寸、速度以及安全性之间进行不同的折衷。用户负责为白盒参数化文件124中列出的每个逻辑转换类型提供转换类型映射。这在正常情况下经由配置文件来执行,但也可以在命令行上直接提供。
如上所述,白盒调用与参数化文件记录之间的连接(因此,代码和数据的特定实例集)为ID参数。因此,如果对相同函数的两个调用被给定相同的ID参数值,则它们将指相同的白盒参数化文件记录,并且将最终决定相同的白盒库调用,从而共享与该调用相关的数据。换句话说,为了使两个白盒调用共享数据,它们可以被给予相同的ID。请注意,如果这两个调用是对相同的抽象的API,并且如果在输入和输出上的数据转换是相同的,则共享的数据才有意义。
只要用户已经选择在外部存储白盒密码调用的数据,则必须添加相应的调用以检索外部数据并且将其翻译成适合的形式。例如,固定密钥的块密码加密示例可以如下被增强。
示例性的输入源文件:
#include″crypto.h″
#endif
#include″xc/xc_wb.h″
_xc_transformtype(blue)XC_Octet plain[16];
_xc_transformtype(green)XC_Octet cipher[16];
int csize;
XC_BlockCipherOptions options;
int ret;
/*Load plaintext into plain*/
#ifdef XC_ENABLED
ret=XC_Import_Data_From_File(1,&options);
if(ret!=XC_OK){
/*issue error*/
}
#endif
ret=XC_Fixed_Key_Block_Cipher_Encrypt(1,plain,16,cipher,&csize,
NULL,0,options);
if(ret!=XC_OK){
/*issue error*/
}
ret=XC_Free_Data_Holder(1,&options);
/*Process ciphertext*/
示例性的参数化文件(wbinfo.wbp):
Identifier 1
FunctionType BlockCipher
KeyLocation Fixed
Operation Encrypt
Algorithm AES
Mode ECB
FixedKey 1ED0861E06A180AC197BDB3FB54D50D9
KeySize 16
KeyType Standard
NumRounds 10
EncryptionType Eta
DataStorage Export
OutputFile″cryptodata.dat″
白盒代码生成
防止攻击的困难之一在于白盒密码实现本身可以取代密钥。如果白盒软件实现通过部分赋值嵌入密钥,并且实现解密,则可以使用该整个应用程序而非密钥来执行解密。也就是说,代替确定正在实现什么密码以及该密钥是什么,攻击者可以简单地提取整个白盒解密实现并且使用它进行解密。这是所谓的“剪断(snipping)”或“代码盗用(code-lifiting)”白盒解密。
防御这种攻击的复杂性为自动操作使用白盒密码术的系统的周围隐含方面和相互隐含方面的优点提供了好的示例。例如,白盒密码实现使用数据数组。为了使这种数组或表难以通过“剪切”去除,每个表可以被分割成两部分,一部分是在白盒实现外部的软件中某处的可执行代码段。另一部分是包含‘xor’数据的相同尺寸的数据表,该‘xor’数据在用该代码段的相应部分进行异或时产生所期望的表。这使得难于盗用白盒代码,因为它仅仅在需要的数据段存在时才正确执行。另一方法是要用位于白盒密码实现外部的其它应用程序数据代替该代码段,使得在没有不具有位于白盒实现外部的数据的情况下,在它内部的数据数组是没有用的。在又一方法中,这些数据表可以被这样一些表来取代,这些表访问在使用白盒密码术的全部程序中的散布位置。然后,每个数据表被其指针指向程序余部的全部代码或数据中的许多位置的表来取代,其中在该程序中可以发现合适片断的数据,也就是说,每个原始表被其指针指向包含所期望的原始数据的位置的指针的表来取代。这些方法需要工具以及访问应用程序的余部的编译后的二进制代码的高水平程序员,以编辑可执行代码并且用‘xor’数据取代原始表或者用其它方式修改这些表。白盒代码生成工具150使这样的方法自动操作并且生成“粘合”代码以确保在加密运算的边界处的输入和输出被有效地混淆。
一旦参数化文件124已经被创建,用户必须运行白盒代码生成工具150,白盒代码生成工具150解析参数化文件124并且生成白盒调用定义文件172,白盒调用定义文件172将对白盒库进行适合的调用。白盒代码生成工具150在下文中被称为wbcodegen 150。wbcodegen 150主要负责处理用户应用程序代码(具体而言,包含对白盒加密API的调用的文件)连同白盒参数化文件124,并且生成白盒调用定义数据(在这里也称为白盒调用定义或“粘合”文件),其包括将会被数据转换引擎152理解的转换修饰符。白盒调用定义数据提供“粘合”例程的函数定义的集合,这些“粘合”例程在用于用户应用程序中的高度抽象的API与在白盒库中提供的低级白盒例程之间进行映射。
基于对用户源代码中的白盒API的调用以及包含在白盒参数化文件124中的密码域的描述,Wbcodegen工具150负责生成白盒粘合代码。白盒粘合代码用作用户源代码中高度抽象的API与白盒库密码运算的实际调用之间的填隙片(shim),并且确保当对白盒参数化进行改变时不必修改用户源代码。wbcodegen 150可以被设计为预处理器的扩展,以提高处理速度。优选地,wbcodegen 150完全独立于数据转换引擎152。
优选地,wbcodegen 150并未以任何方式修改用户应用程序代码,并且它产生的白盒粘合文件在想要被编译并链接到最终应用程序的独立源文件中。另外,wbcodegen 150可以用作白盒参数化文件124的验证工具(用于检查参数名是否合法、参数值是否有效以及用于对记录内的指定参数进行一致性检查)。最终,wbcodegen 150也可以用于检测错误,这些错误涉及用户应用程序代码中的白盒运算的显性和隐性参数错误(例如,ID参数的指定指块密码运算上的非对称密码)。
wbcodegen 150将参数化文件124以及包含白盒密码调用的输入源文件100作为输入。输出是白盒调用定义文件172(userCode-glue.c),其包含发现的每个白盒密码调用的定义。该工具还生成相应的白盒粘合头174或者简单地头文件(userCode-glue.h),包含生成的函数中的每一个的原型,其可以例如是“粘合”例程的外部声明的集合,每个ID和基本密码运算的组合一个。wbcodegen 150还生成输出的白盒元数据文件176,其拥有关于为每个白盒调用所进行的选择的元数据;该元数据被传递给下面描述的数据生成工具154(wbdatagen)。
要么每当用抽象的白盒API的新调用对应用程序代码进行更新时,要么当对白盒参数化文件124进行修改时,用户负责重新运行wbcodegen 150。
如上所述,wbcodegen工具150负责处理用户的源代码连同白盒参数化文件124,并且负责将用户的抽象的白盒API调用扩展到对低级白盒库例程的完全参数化调用。例如,wbcodegen 150工具可以由将接受并解析参数的顶级Perl前端(或驱动器)组成。该Perl前端还可以验证参数化文件内容,从而检查面向行的文本内容中的句法/语义错误,并将它转换成wbcodegen后端可接受的形式。wbcodegen后端可以处理用户的源代码连同转换后的参数化文件。
wbcodegen后端必须做的大部分事情非常类似于宏扩展。抽象的白盒API的每个调用被扩展为“变换的(mangled)”形式,其中ID参数以该“变换的”形式成为调用名的部分。每个白盒API调用的源位置被记录在独立的元数据文件中。唯一变换名(即具有附加ID参数的白盒API名)的第一调用触发适合的函数定义的生成,该适合的函数定义调用实际的下层白盒库函数。各种形式的参数一致性检查还可以在编译/链接/执行时之前被执行,并且错误被发出以确保用户应用程序和参数化文件124的正确性。
命令行参数/选项的解析可以由Perl驱动器执行。Perl驱动器将对参数值进行智能检查(sanity checking),并且可以可选地调用白盒参数化文件处理器/验证工具(未示出)。然后,该驱动器可以调用每个命令行指定的源文件上的wbcodegen后端。该方法的一种复杂情况在于某个状态信息必须在wbcodegen后端的调用之间持续(具体而言,它必须知道哪些白盒运算/ID结合在之前处理过的源文件中已经见到,使得它可以合适地生成唯一的粘合代码函数定义,以及关于重复调用的警告)。为了解决这个问题,wbcodegen驱动器可以被设置为打开临时文件,该临时文件将被传递给每个后端调用,并且将包含任何这种状态信息。这个临时文件的生存期是wbcodegen 150的一个调用,并且可以在wbcodegen 150终止之前被去除。同样,该文件对于用户完全不可见。
由于白盒参数化文件格式化的相对复杂性(即使不存在时,在某些环境下也可以暗含有参数,即它们具有缺省值),或者在与其它参数值结合时可能是非法的。结果是,可以在由wbcodegen 150进行解析之前实现对参数化文件124的预处理。由于该语言的规则表达的便利非常强大,因此该预处理可以用Perl写成。可以包括白盒参数化验证工具(未示出)以通过将缺省值显式地插入记录来处理错过的缺省参数,并且验证参数值是否合法并验证参数的结合是否一致。同时,白盒参数化处理器可以将自由格式文本ID记录转换成合适的宏调用。
考虑到典型的使用场景将涉及多个输入源文件100和单个白盒参数化文件124的应用程序的编连,从而暗示将存在wbcodegen 150的一个调用(将所有包含对白盒API的调用的源文件连同单个白盒参数化文件124一起作为输入)。然而,在设计中并未排除将应用程序分割成若干模块,每个模块具有它自己的白盒参数化文件124(或者对于所有模块确实具有单个共享的白盒参数化文件124),并且用wbcodegen 150的相应调用处理这些模块中的每一个。
一旦单个开发者已运行wbcodegen 150,就不需要其它开发者重新运行它来作为他们的编连的一部分。相反,开发者可以包括如上所述的所生成的头文件174,并且添加所生成的文件以编连脚本。在这点上,希望编译并链接该应用程序的任何人仅仅需要本地编译工具。
白盒数据转换
一旦代码生成工具150已经运行,就优选执行数据转换以保护白盒调用的输入和输出。附图中示出为xcode的数据转换引擎152对输入源文件100和包含白盒函数调用定义的粘合代码执行该功能(在这里也称为“代码转换(transcoding)”)。诸如Cloakware TranscoderTM之类的数据转换引擎152在所描述的实现中用于利用数据转换提供白盒功能。该数据转换的输出是经过伪装的或经过混淆的转换后的源文件180(userCode.cloaked.c)、经过伪装的或经过混淆的调用定义文件182(userCode-glue.cloaked.c)以及包含外部转换元数据184(粘合元数据)的文件。所生成的转换元数据文件184描述了关于所选择的给白盒粘合函数的参数的数据转换选择。
白盒加密实现假设,已经在白盒调用的范围外应用对应用程序数据(例如用于加密的明文、用于解密的密码,在适当的情况下,加上密钥和IV)的转换,并且在初始步骤中安全地去除那些转换。类似地,在加密运算的最后步骤中安全地应用了对输出变量(例如用于加密的明文、用于解密的密码)的转换;数据转换引擎152假设对这些变量中的数据进行了转换。
数据转换引擎152的功能在本文献的范围之外,但是可以一般地理解为应用数据转换以对变量和数据的数学运算进行混淆或伪装,特别是加密运算,以确保攻击者不可见并且不会泄露有损重要资产的信息。数据转换引擎152还可以应用控制流转换以伪装应用程序的程序流,使得攻击者很难静态或动态地跟踪应用程序的运行。数据转换引擎152可以被认为是这样的实用程序,其将源代码转换成经过算术修改的源代码。转换后的应用程序在功能上与原应用程序相同,但是对逆向工程和篡改攻击而言有很高的抵抗力。在无需特殊的硬件和额外的软件的情况下,受保护的应用程序在开放的计算平台上可靠地执行。
数据转换引擎152还利用代码转换链接白盒密码术以传递集成的和分层的保护,其远比只有单独的技术要安全。白盒密码术,其细节也在本说明书的范围之外,以防止攻击者获取加密密钥(或者在非对称‘公钥’密码术的情况下,防止获取私钥)或者在黑客可以十分详细地观察加密运算的环境中防止获取可以取代该密钥的东西的方式实现标准加密算法。白盒密码术可以实现诸如RSA和AES之类的密码,以确保即使在加密运算期间也不会泄露重要的密钥数据。
在下列专利文献中可以找到数据转换和白盒密码术实现的示例:TAMPER RESISTANT SOFTWARE ENCODING AND ANALYSIS(防篡改软件编码和分析),美国专利公开2004/0236955-A1;SOFTWARECONDITIONAL ACCESS SYSTEM(软件条件访问系统),美国专利公开2005/0039025-A1;METHOD AND SYSTEM FOR SECURE ACCESS(安全访问的方法和系统),美国专利No.7,325,141;METHOD AND SYSTEM FORSUSTAINABLE DIGITAL WATERMARKING(可支撑数字水印的方法和系统),美国专利公开2005/0021966 A1;SECURE METHOD AND SYSTEM FORBIOMETRIC VERIFICATION(用于生物验证的安全方法和系统),美国专利公开005/0138392 A1;SECURE METHOD AND SYSTEM FORCOMPUTER PROTECTION(计算机保护的安全方法和系统),美国专利公开2004/0268322 A1;SECURE METHOD AND SYSTEM FOR HANDLINGAND DISTRIBUTING DIGITAL MEDIA(用于处理和分发数字媒体的安全方法和系统),美国专利公开2005/0021989-A1;SYSTEM AND METHOD FOROBSCURING BIT-WISE AND TWO’S COMPLEMENT INTEGERCOMPUTATIONS IN SOFTWARE(用于使软件中的位元和两个补码整数计算混淆的系统和方法),美国专利公开2005/0166191 A1;SYSTEM ANDMETHOD FOR PROTECTING COMPUTER SOFTWARE FROM A WHITEBOX ATTACK(用于保护计算机软件免受白盒攻击的系统和方法),美国专利公开2006/0140401-A1;SYSTEM AND METHOD FOR PROTECTINGCOMPUTER SOFTWARE FROM A WHITE BOX ATTACK(用于保护计算机软件免受白盒攻击的系统和方法),美国专利公开2004/0139340-A1;SYSTEMAND METHOD OF FOILING BUFFER-OVERFLOW AND ALIEN-CODEATTACKS(阻挡缓冲区溢出和外来代码攻击的系统和方法),美国专利公开003/0172293-A1;SYSTEM AND METHOD OF HIDINGCRYPTOGRAPHIC PRIVATE KEYS(隐藏密码私钥的系统和方法),美国专利公开2005/0002532-A1;TAMPER RESISTANT SOFTWARE-CONTROLFLOW ENCODING(防篡改软件控制流编码),美国专利No.6,779,114;TAMPER RESISTANT SOFTWARE ENCODING(防篡改软件编码),美国专利No.6,594,761;TAMPER RESISTANT SOFTWARE ENCODING(防篡改软件编码),美国专利No.6,842,862;TAMPER RESISTANTSOFTWARE-MASS DATA ENCODING(防篡改软件大规模数据编码),美国专利No.7,350,085;其内容通过引用整体合并于此。
白盒数据生成
每个唯一识别的对白盒密码函数的调用将具有相关联的数据,其必须基于为该调用所进行的功能和安全性相关的选择来生成。生成该数据的白盒数据生成工具154在下文中被称为wbdatagen 154。
wbdatagen 154负责以初始化表数据的形式生成白盒库所需要的白盒调用的特定实例数据的初始化。在用户的应用程序的某处的密码运算中使用的每个密码域将使得生成这种表数据成为必要。初始化数据的精确值取决于由用户的源代码的任何转换所产生的用户的密码数据(明文/密文等等)的转换。例如,不同的调用(甚至具有相同函数参数的那些调用)可能使用不同的密钥并且对它们的输入和输出进行不同转换。同样,通过每个白盒调用的工具链进行随机实现选择。wbdatagen 154生成封装所有这些选择的特定实现数据。
在调用期间,该数据被传递给密钥不可知者和转换不可知者(key-andtransformation-agnostic)白盒库代码(xc-wb.xlib)。wbdatagen 154不需要处理用户应用程序代码本身,因为期望wbcodegen 150已经分析了源代码并且将任何需要的信息写入了白盒元数据176。
wbdatagen工具154将由wbcodegen 150生成的白盒元数据176和由数据转换引擎152创建的外部转换或粘合元数据184(如果粘合代码被转换)作为输入。该信息告诉wbdatagen 154在用户应用程序代码中发现了哪些密码运算、在白盒参数化文件中针对这些运算指定了什么密码参数以及什么数据转换被应用于作为实际参数传递的用户数据。wbdatagen工具154生成定义白盒数据的代码以及可选地生成导出数据文件186。
wbdatagen 154的输出是包含与参数化文件124中的每个记录相对应的数据的数据初始化文件188(userCode-data.c)。数据初始化文件188包含一组数据变量(“数据初始化”),其封装每个白盒调用的特定实例数据。这些数据值要么还存储在这个文件中,要么存储在由用户在参数化文件124中指定的一个或多个输出文件中。如果有待生成的所有数据是导出数据,则wbdatagen 154实际上可以在编译和链接后运行。wbdatagen 154可以被运行以通过单个开发者生成嵌入数据(并且可选地,导出数据)。在这点上,希望编译和链接应用程序的任何人仅仅需要本地编译工具。
由wbdatagen 154生成白盒数据表数据参数的定义,但粘合代码必须确保在合适的时候将它们作为实际参数传递给白盒库引用。特别要注意的是以上详细说明的与示例性白盒包含文件170相关的子包含文件(xc_wb_bc_fk_aes_tables.h等等)。这些详细定义给白盒密码运算的每个可能变量的形式参数,并且用于生成白盒粘合文件172、174中的成批文本。这些子包含文件优选由还生成白盒库代码本身的程序自动生成。这样,自动维持对精确形式的低级白盒API的很大程序上的依赖。
要么每当用抽象的白盒API的新调用对应用程序代码进行更新时,要么当对白盒参数化文件124进行修改时,要么对应用程序代码进行转换时,一般重新运行wbdatagen 154。
编译并链接转换后的代码
为了编译并链接代码转换后的代码或转换后的代码,利用用于对用户应用程序代码进行编译的相同本地工具编译器190,对转换后的源文件180(userCode.cloaked.c)、转换后的白盒调用定义文件182(userCode-glue.cloaked.c)以及数据初始化文件(userCode-data.c)进行编译,以生成目标文件152,并且依赖于白盒库196(xc_wb.lib)通过链接器194(xlink)进行链接,以生成受保护的可执行文件198。由白盒库实现的加密运算的细节和独立子例程的精确API在本文献的范围之外。
性能调整
在对转换后的代码进行测试期间,用户可能发现他们并不满意于应用程序的性能或尺寸,或者可替代地,可能发现该性能超出可接受的程度,并且存在可以提高安全性的区域。在这点上,可以重新访问在较早阶段所进行的功能性或安全性选择中的任何一个,并且仅仅需要对参数化文件124进行改变。若干参数可以被改变以对不同尺寸/速度/安全性进行折衷。例如:
●可以将加密类型改变成要么更高性能的变量要么更高安全性的变量。
●针对较高性能和较小尺寸可以减少循环的次数(有意义的情况下)或者针对较高的安全性增加循环的次数。
●针对较高的安全性可以开启数据混洗(shuffling)或者针对较高的性能关闭数据混洗。
●可以将相同的ID给予不同的白盒调用以减少尺寸,或者可以将不同的ID给予具有相同ID的调用以提高安全性。
●可以降低对应用程序代码或所生成的代码进行转换所基于的数据转换设置以提高性能,或者提高以提高安全性。用户甚至可以选择根本不转换所生成的代码。
所描述的白盒工具链对于用户的在他们的应用程序中使用反跟踪和完整性验证的能力没有影响。进一步,通过例如将反跟踪时序点放置在这种调用之前和之后或者通过对包括白盒库的模块进行签名和完整性检查,用户可以向他们的白盒调用添加深度防御。
生成多样的实例
从安全性的立场来看,具有应用程序的多于一个的实例经常是有好处的。应用程序多样性可以意味着向用户基地分发应用程序的若干不同的但是功能等同的版本,或者对现场的应用程序进行频繁更新以减轻已知的脆弱性或者防止攻击不断发生(执行这种“及时多样性”的能力被称为可更新性)。
当然,可以通过简单运行上述步骤若干次(每个实例一次),创建利用白盒密码术的应用程序的多样实例。然而,该方法除了比较慢之外,还必须对每个实例进行独立测试,其严重限制了可以应用的多样性的数量。不同的方法是要使大部分应用程序在实例之间保持相同,并且要使多样性被数据驱动,这意味着多样性实例实际上可以在该应用程序已经编译和链接之后被创建。基于数据的多样性还有利于非常简单的可更新性,因为经常有适当的通道,通过该通道可以更新客户端上的数据。为已经编连的应用程序生成多样数据的过程被称为“个别化”。白盒加密数据的个别化可以通过利用导出表并且在该应用程序编连之后重复运行wbdatagen 154来实现。实现这个的一个方法是要使用wbdatagen 154将不同的固定密钥与应用程序的每个实例相关联。为了便于这种使用而无需每当wbdatagen 154运行时改变参数化文件124,固定密钥还可以在命令行上被指定。
总结
在之前的部分中,已经描述了需要将白盒密码功能集成到应用程序中的步骤。这些步骤可以被概述如下。
●用户将对白盒加密API的调用添加到他们的应用程序中。
●用户创建白盒参数化文件并且为每个调用添加记录。
●用户运行wbcodegen,紧接着xcode,紧接着wbdatagen以生成用于代码转换的编连的支持代码和数据。
●用户编译、链接并测试它们的应用程序。
●用户重复步骤直到他们对尺寸、性能和安全性满意。
●用户重复运行wbdatagen以创建该支持数据的多样实例。
本发明以上描述的实施例意在仅仅作为示例。在不偏离这里所附权利要求单独限定的本发明的范围的情况下,本领域技术人员可以对特定的实施例进行更改、修改和改变。