CN117591087B - 一种针对复杂数据处理需求的高效形式化代码构建方法 - Google Patents
一种针对复杂数据处理需求的高效形式化代码构建方法 Download PDFInfo
- Publication number
- CN117591087B CN117591087B CN202311506458.XA CN202311506458A CN117591087B CN 117591087 B CN117591087 B CN 117591087B CN 202311506458 A CN202311506458 A CN 202311506458A CN 117591087 B CN117591087 B CN 117591087B
- Authority
- CN
- China
- Prior art keywords
- code
- buffer
- data processing
- heap
- processing requirements
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Active
Links
- 238000012545 processing Methods 0.000 title claims abstract description 52
- 238000010276 construction Methods 0.000 title claims abstract description 28
- 238000012795 verification Methods 0.000 claims abstract description 40
- 101100070115 Arabidopsis thaliana HACL gene Proteins 0.000 claims abstract description 28
- 239000000872 buffer Substances 0.000 claims description 114
- 230000006870 function Effects 0.000 claims description 49
- 238000000034 method Methods 0.000 claims description 30
- 230000006399 behavior Effects 0.000 claims description 10
- 230000008859 change Effects 0.000 claims description 10
- 238000012986 modification Methods 0.000 claims description 10
- 230000004048 modification Effects 0.000 claims description 10
- 238000005538 encapsulation Methods 0.000 claims description 6
- 230000007246 mechanism Effects 0.000 claims description 4
- 238000013461 design Methods 0.000 description 8
- 238000011161 development Methods 0.000 description 7
- 230000008901 benefit Effects 0.000 description 4
- 238000006243 chemical reaction Methods 0.000 description 4
- 238000010586 diagram Methods 0.000 description 4
- 230000003542 behavioural effect Effects 0.000 description 3
- 238000004422 calculation algorithm Methods 0.000 description 3
- 230000009977 dual effect Effects 0.000 description 3
- 230000000694 effects Effects 0.000 description 3
- 230000008569 process Effects 0.000 description 3
- 238000004458 analytical method Methods 0.000 description 2
- 238000013459 approach Methods 0.000 description 2
- 238000003491 array Methods 0.000 description 2
- 238000004364 calculation method Methods 0.000 description 2
- 238000004891 communication Methods 0.000 description 2
- 238000004590 computer program Methods 0.000 description 2
- 238000001514 detection method Methods 0.000 description 2
- 238000007726 management method Methods 0.000 description 2
- 230000003449 preventive effect Effects 0.000 description 2
- 230000001737 promoting effect Effects 0.000 description 2
- 238000013519 translation Methods 0.000 description 2
- 230000006978 adaptation Effects 0.000 description 1
- 230000009286 beneficial effect Effects 0.000 description 1
- 238000007796 conventional method Methods 0.000 description 1
- 238000007405 data analysis Methods 0.000 description 1
- 238000013523 data management Methods 0.000 description 1
- 230000007547 defect Effects 0.000 description 1
- 230000001419 dependent effect Effects 0.000 description 1
- 238000000605 extraction Methods 0.000 description 1
- 230000010354 integration Effects 0.000 description 1
- 230000001788 irregular Effects 0.000 description 1
- 230000014759 maintenance of location Effects 0.000 description 1
- 238000013507 mapping Methods 0.000 description 1
- 229910052754 neon Inorganic materials 0.000 description 1
- GKAOGPIIYCISHV-UHFFFAOYSA-N neon atom Chemical compound [Ne] GKAOGPIIYCISHV-UHFFFAOYSA-N 0.000 description 1
- 238000005457 optimization Methods 0.000 description 1
- 230000004044 response Effects 0.000 description 1
- 238000004088 simulation Methods 0.000 description 1
- 238000012546 transfer Methods 0.000 description 1
- 230000007704 transition Effects 0.000 description 1
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F8/00—Arrangements for software engineering
- G06F8/30—Creation or generation of source code
- G06F8/31—Programming languages or programming paradigms
- G06F8/311—Functional or applicative languages; Rewrite languages
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F11/00—Error detection; Error correction; Monitoring
- G06F11/36—Preventing errors by testing or debugging software
- G06F11/3604—Software analysis for verifying properties of programs
- G06F11/3608—Software analysis for verifying properties of programs using formal methods, e.g. model checking, abstract interpretation
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F8/00—Arrangements for software engineering
- G06F8/30—Creation or generation of source code
- G06F8/31—Programming languages or programming paradigms
- G06F8/313—Logic programming, e.g. PROLOG programming language
Landscapes
- Engineering & Computer Science (AREA)
- Software Systems (AREA)
- Theoretical Computer Science (AREA)
- General Engineering & Computer Science (AREA)
- Computing Systems (AREA)
- Physics & Mathematics (AREA)
- General Physics & Mathematics (AREA)
- Computer Hardware Design (AREA)
- Quality & Reliability (AREA)
- Stored Programmes (AREA)
Abstract
本发明公开了一种针对复杂数据处理需求的高效形式化代码构建方法,包括:通过F*语言提取所要构建的代码的数学逻辑;将所述数学逻辑基于HACL*库和Low*库进行构建实现,其中通过对HACL*库进行扩展以应对复杂数据处理需求;编译执行所述代码,以完成从规范到实现的正确性验证和内存安全性验证;通过kremlin工具自动将已验证的Low*转换为语义等效的C代码。
Description
技术领域
本发明属于计算机软件的形式化设计和编程方法技术领域,尤其涉及一种针对复杂数据处理需求的高效形式化代码构建方法。
背景技术
代码安全性一直是科技领域里的重要议题,尤其在涉及密码学应用时,任何细微的错误都可能引发重大的安全问题和财务损失。通常情况下,开发者并非从头开始编写安全软件,而是倾向于依赖已存在的大型安全库,例如OpenSSL,来开发他们的加密软件。然而,就算像OpenSSL这样经过时间检验并得到广泛认可的库,也并非无懈可击。实际上,OpenSSL一直在不断修复其漏洞,其中包含了一些重大漏洞。这些漏洞可能源于早期未被发现的问题,或者来自新的代码,对于一个如此大型的库,要始终保证自身没有漏洞或仅有很少的漏洞绝非易事。
如果我们要获取的代码执行行为和预期行为完全一致,我们可以使用形式化验证的方式从数学角度证明某一代码满足我们的要求。通过这种方法,我们可以开发出具备安全性、可靠性等特性的代码。通常使用形式化验证构建代码存在灵活性不足、开发成本较高、已验证代码性能不及原始代码等问题,往往只能用于一些小型项目的构建。
《J.-K.Zinzindohoué,K.Bhargavan,J.Protzenko,and B.Beurdouche,“HACL*:Averified modern cryptographic library,”Proceedings of the 2017ACM SIGSACConference on Computer and Communications Security,2017.doi:10.1145/3133956.3134043》提出了一种利用F*语言构建的框架,用于创建经过形式化验证的C语言密码学库HACL*。HACL*是一款经过验证的可移植C语言密码学库,支持现代加密原语,如ChaCha20、Salsa20加密算法、Poly1305和HMAC消息认证、SHA-256和SHA-512散列函数、Curve25519椭圆曲线以及Ed25519签名等;该方案的缺点为:该方案的语言对C语言特性支持不足,例如无法有效利用SIMD等CPU特性,因此在满足复杂数据处理需求的代码开发方面存在困难。
《J.Protzenko et al.,“EverCrypt:A fast,verified,cross-platformcryptographic provider,”2020IEEE Symposium on Security and Privacy(SP),2020.doi:10.1109/sp40000.2020.00114》在HACL*的基础上进一步发展,提出了EverCrypt,一种全面的加密功能集合,具备已验证、高性能特性。其API在支持敏捷性(选择同一功能的多种算法)和多路复用(在同一算法的多种实现之间选择)的同时保证了验证的简化和性能的不牺牲;该方案的缺点为:虽然提高了灵活性,但同时增加了代码构建的复杂度,对于具有复杂数据处理需求的代码构建仍存在挑战。
《M.Polubelova et al.,“HACLxN:Verified generic SIMD crypto(for allyour favourite platforms),”Proceedings of the 2020ACM SIGSAC Conference onComputer and Communications Security,2020.doi:10.1145/3372297.3423352》引入了一种针对多个架构优化的经过正式验证的密码学库构建新方法。具体而言,该方案展示了如何在F*编程语言中编写和验证利用单指令多数据(SIMD)并行性的通用加密代码,并阐述了如何将此代码编译到支持向量指令的平台,如ARM Neon和Intel AVX、AVX2和AVX512;该方案的缺点为:尽管在SIMD并行性方面有所突破,但在处理复杂数据需求的代码开发方面仍存在难度和挑战。
发明内容
针对现有技术存在的问题,本申请实施例的目的是提供一种针对复杂数据处理需求的高效形式化代码构建方法,在基于HACL*项目的基础上进行,通过对其框架做出一些扩展,能够使代码构建者轻松地使用这种方法构建具备复杂数据处理需求的代码,从而提升形式化验证的效率,降低形式化代码的构建成本。
根据本申请实施例的第一方面,提供一种针对复杂数据处理需求的高效形式化代码构建方法,包括:
建立规范:通过F*语言提取所要构建的代码的数学逻辑;
构建实现:将所述数学逻辑基于HACL*库和Low*库进行构建实现,其中通过对HACL*库进行扩展以应对复杂数据处理需求;
验证代码:编译执行所述代码,以完成从规范到实现的正确性验证和内存安全性验证;
代码生成:通过kremlin工具自动将已验证的Low*转换为语义等效的C代码。
进一步地,所述复杂数据处理需求为处理的数据量大且具有动态变化的特性,需要具备实时的内存管理机制,能够根据数据的当前规模和结构动态分配或回收内存资源,并能支持对这些数据的频繁访问和修改操作。
进一步地,所述扩展包括:
对HACL*库原有的缓冲区类型进行扩展,通过嵌套的方式定义多重缓冲区与可嵌套动态容器,以应对复杂数据处理需求;
将多重缓冲区与可嵌套动态容器的类型转换为规范使用的序列类型,以方便规范证明。
进一步地,设置多重缓冲区与可嵌套动态容器后,增加以下扩展内容:描述缓冲区在堆中状态的描述符、嵌套类型在堆修改时的引理、Low*函数的封装。
进一步地,所述缓冲区在堆中状态包括缓冲区在堆中的存活状态,缓冲区是否重叠,以及多个嵌套类型中的缓冲区是否重叠。
进一步地,所述嵌套类型在堆修改时的引理涉及嵌套类型的缓冲区在不同情况下的特性的行为证明,所述特性包括存活性、相交状态、是否被修改。
进一步地,将多重缓冲区与可嵌套动态容器的类型转换为规范使用的序列类型,具体为:将多重缓冲区与可嵌套动态容器通过函数转换为对应的嵌套序列类型,并为其动态内存分配释放操作所导致的内存状态变化设置引理。
根据本申请实施例的第二方面,提供一种针对复杂数据处理需求的高效形式化代码构建装置,包括:
建立规范模块:通过F*语言提取所要构建的代码的数学逻辑;
构建实现模块:将所述数学逻辑基于HACL*库和Low*库进行构建实现,其中通过对HACL*库进行扩展以应对复杂数据处理需求;
验证代码模块:编译执行所述代码,以完成从规范到实现的正确性验证和内存安全性验证;
代码生成模块:通过kremlin工具自动将已验证的Low*转换为语义等效的C代码。
根据本申请实施例的第三方面,提供一种电子设备,包括:
一个或多个处理器;
存储器,用于存储一个或多个程序;
当所述一个或多个程序被所述一个或多个处理器执行,使得所述一个或多个处理器实现如第一方面所述的方法。
根据本申请实施例的第四方面,提供一种计算机可读存储介质,其上存储有计算机指令,该指令被处理器执行时实现如第一方面所述方法的步骤。
本申请的实施例提供的技术方案可以包括以下有益效果:
由上述实施例可知,本申请通过F*语言构建功能规范,可以进行预防性错误检测,同时可以保证编写效率和与Low*的高度兼容性;通过多重缓冲区与可嵌套动态容器应对复杂数据处理需求,确保了程序的严格形式化验证,同时通过使用低级语言进行实现,确保了代码的高性能和兼容性。这种结合了数学抽象和实际实现的方法可以帮助开发人员编写既准确又高效的代码,有助于推动复杂系统的可靠性和健壮性;
应当理解的是,以上的一般描述和后文的细节描述仅是示例性和解释性的,并不能限制本申请。
附图说明
此处的附图被并入说明书中并构成本说明书的一部分,示出了符合本申请的实施例,并与说明书一起用于解释本申请的原理。
图1是根据一示例性实施例示出的一种针对复杂数据处理需求的高效形式化代码构建方法的流程图。
图2是根据一示例性实施例示出的一种针对复杂数据处理需求的高效形式化代码构建装置的框图。
图3是根据一示例性实施例示出的一种电子设备的示意图。
具体实施方式
这里将详细地对示例性实施例进行说明,其示例表示在附图中。下面的描述涉及附图时,除非另有表示,不同附图中的相同数字表示相同或相似的要素。以下示例性实施例中所描述的实施方式并不代表与本申请相一致的所有实施方式。
在本申请使用的术语是仅仅出于描述特定实施例的目的,而非旨在限制本申请。在本申请和所附权利要求书中所使用的单数形式的“一种”、“所述”和“该”也旨在包括多数形式,除非上下文清楚地表示其他含义。还应当理解,本文中使用的术语“和/或”是指并包含一个或多个相关联的列出项目的任何或所有可能组合。
应当理解,尽管在本申请可能采用术语第一、第二、第三等来描述各种信息,但这些信息不应限于这些术语。这些术语仅用来将同一类型的信息彼此区分开。例如,在不脱离本申请范围的情况下,第一信息也可以被称为第二信息,类似地,第二信息也可以被称为第一信息。取决于语境,如在此所使用的词语“如果”可以被解释成为“在……时”或“当……时”或“响应于确定”。
名词解释
(1)形式化方法
在计算机科学和软件工程领域,形式化方法是基于数学的特种技术,适合于软件和硬件系统的描述、开发和验证。将形式化方法用于软件和硬件设计,是期望能够像其它工程学科一样,使用适当的数学分析以提高设计的可靠性和强健性。但是,由于采用形式化方法的成本高意味着它们通常只用于开发注重安全性的高度整合的系统。
(2)Hoare逻辑
霍尔逻辑(Hoare Logic)是一种用于证明计算机程序正确性的形式系统,为程序设计和验证提供了理论基础。其基础元素是一个三元组,表示为{P}C{Q},其中P和Q是前置条件和后置条件,用于描述程序C在开始前和结束后的状态,而C是一条或多条程序指令。在这个三元组中,如果程序C在一个满足P条件的状态下开始运行并顺利结束,那么结束后的状态将满足Q条件。霍尔逻辑提供了一系列推理规则,其中顺序组合规则表述如下:如果存在{P}C1{Q}和{Q}C2{R},则可以得出{P}C1;C2{R}。此规则表明,如果按顺序执行C1和C2,从状态P可以达到状态R。
(3)内存安全
内存安全的代码不会违反内存抽象,因此不存在缓冲区溢出、空指针取消引用、释放后使用、双重释放等常见错误和漏洞。
(4)功能规范
功能规范(Functional Specification)是一种用精确的数学和逻辑语言描述软件或系统应该如何运行的文档。功能规范定义了系统的预期行为,描述了系统在给定输入或特定条件下应该如何响应。
(5)功能正确性
功能正确性(Functional Correctness)是指一个程序或系统是否符合其规定的形式化规范或需求。简单来说,功能正确性是关于程序是否按照预期的方式工作的属性。
(6)F*
在F*(读作“F star”)是一个由微软研究院和INRIA主导开发的、基于ML的依赖类型函数式程序语言,主要用于程序的形式化验证。F*的类型系统十分丰富,支持依赖类型、单子化效用(monadic effects)和细化类型(refinement types)。这使其能够准确地用于表述程序的形式化规范,包括功能正确性和安全性。F*的类型检查器通过检查手写的证明和SMT自动求解来确保程序符合规范。使用F*书写的程序可被编译到OCaml、F#或C加以执行。早期版本的F*亦支持编译到JavaScript。F*语言本身使用F*和F#实现,并可从OCaml或F#引导。
(7)Low*
Low*是F*编程语言的一个子集,它旨在允许程序员以更接近底层的方式编写代码,同时仍然利用F*的全部功能进行证明和规范。通过配套编译器KreMLin,Low*代码可以编译为C语言,因此,它提供了一种OCaml的替代方案,用于提取和运行F*程序,它包括一组F*库,这些库用于建模精选的C功能,例如C的内存模型、堆栈和堆分配数组、机器整数、C字符串文字以及某些C标准库中的函数。
图1是根据一示例性实施例示出的一种针对复杂数据处理需求的高效形式化代码构建方法的流程图,所述复杂数据处理需求为处理的数据量庞大且具有动态变化的特性,需要具备实时的内存管理机制,能够根据数据的当前规模和结构动态分配或回收内存资源,并能高效地支持对这些数据的频繁访问和修改操作,如图1所示,该方法应用于终端中,可以包括以下步骤:
S1:建立规范:提取所要构建的代码的数学逻辑;
具体地,为了形式化地构建代码,首先必须确立代码的数学逻辑框架。基于此,我们选择使用F*语言来构建功能规范。选择F*的原因在于它是一种配备了自动化程序验证工具的函数式编程语言,允许用精确的数学逻辑来描述代码功能,从而保证代码的正确性。
规范应该详细覆盖协议的各个部分,基于对代码的深度解析,借助F*强大的类型系统来定义相关的数据结构和其间的关系,确保数据在后续处理过程中保持一致性和完整性。接下来,针对代码的数学执行逻辑,为预期的每一数据操作定义相应的纯函数,从而确保每个操作步骤的准确执行。
例如下面的内容是为KKRT16中BaRK OPRF的eval函数编写的规范。该规范的具体逻辑概述如下:首先,它将128位的输入转换为一个包含16个8位无符号整数的序列,并对此序列进行哈希处理,将其转变为包含4个128位无符号整数的序列。随后,通过and_s_xor_q函数进行进一步计算,并对计算结果执行哈希操作,最终输出一个128位的无符号整数。
对于具有复杂数据处理需求的代码,简单的使用F*的序列类型来进行描述,这是出于对规范简洁性和可读性的考虑,旨在使规范更接近纯粹的数学描述。
建立规范的主要目标是利用接近数学的语言来明确和精确地表达代码的预期行为。这样,通过减少与核心逻辑无关的细节,能够更为系统地验证程序的正确性。
编写F*规范的优点包括:
1、预防性错误检测:通过在规范阶段使用F*描述代码的数学逻辑并进行形式化验证,能够早期识别并修复可能的设计或编码缺陷。
2、编写规范效率高:作为一种函数式编程语言,F*不仅提供了高速的形式化验证能力,还能清晰且可靠地描述代码行为。
3、与Low*的高度兼容性:Low*是F*的一个子集,因此Low*的实现可以直接访问和利用F*规范。这种密切的结合使我们可以高效地证明Low*实现与原始规范在行为上的等同性。
S2:构建实现:将所述数学逻辑基于HACL*库和Low*库进行构建实现,其中通过对HACL*库进行扩展以应对复杂数据处理需求;
具体地,首先在F*编程语言提供的标准库之上引入HACL*库。Low*是F*编程语言的一个子集,提供了更接近底层编程的抽象,特别是对于整数和缓冲区操作的描述。Low*的标准库包括了机器整数的抽象,这与C语言中的原始整数类型相似,并提供了用于描述缓冲区的类型和操作。
HACL*库在Low*的基础上进行了进一步的封装和扩展。特别地,在HACL*中可变缓冲区类型定义如下:
lbuffer type len
其中,lbuffer标识缓冲区类型,type定义缓冲区内数据的类型,len则指定缓冲区内该类型数据的数量。这一类型与C语言中的指针类型相对应,并且通过显式指定缓冲区大小有助于实现正确性证明,以避免诸如越界访问和非法内存操作等问题。
除了固定长度的缓冲区,Low*标准库还提供了一种动态大小的数据结构,名为vector,其定义如下:
vector type
vector是一个动态大小容器类型,其基础实现是可变缓冲区类型,type定义了容器内数据的类型。
在Low*中,缓冲区类型被视为有状态的类型。其状态可能包括缓冲区的生命周期(例如存活状态)、缓冲区之间的相交状态等。缓冲区类型通常需要与特定的堆绑定,这对于将协议转化为纯数学逻辑描述可能造成不便。
因此,在功能规范中,我们通常不直接使用缓冲区类型,而是使用F*中的类型Sequence进行替代。缓冲区类型可以方便地转换为Sequence类型,在HACL*库中通常通过以下方式实现:
as_seq h buffer
在此,as_seq是一个转换函数,接受堆描述符h和缓冲区引用名称buffer作为参数。
Low*提供了与C语言中数据表示和操作的强联系,使得在F*中进行形式化验证后能轻松地转换为高效的C语言代码。其设计有助于实现对底层数据结构的精确控制,同时允许开发者利用F*的强大形式化能力进行详细的分析和证明。
现有的HACL*库在高效数据管理方面展现了一定的限制,特别是只提供了对一维缓冲区的支持。在面临诸如安全多方计算协议等具备复杂数据处理需求的情境时,一维缓冲区可能遇到内存分配不灵活、验证困难、数据处理能力受限等挑战。
为了战胜这些挑战,本申请在F*标准库和HACL*库的基础上进行了一系列扩展,这些扩展不仅融入了形式化验证框架,还为复杂数据处理提供了全新的代码构建方案。以下进行具体说明。
(i)多重缓冲区与可嵌套动态容器
具体地,本申请首先对原有缓冲区类型进行了深入拓展,通过嵌套的方式定义了多重缓冲区和可嵌套动态容器:
lbuffer(lbuffer type len)len'
vector(vector type)
依据先前的描述,可以清晰地看出这是两个直观的嵌套类型。不过如果想要使用这样的嵌套类型,需要承担一些代价,这些代价主要来源于证明,因为使用嵌套方式构建类型自然会使证明的复杂程度呈指数级上升。为了最大程度地提高证明的速度和易用性,本申请针对这两种类型编写了以下扩展内容:
1、描述缓冲区在堆中状态的描述符:这些描述符可以用于描述缓冲区在堆中的存活状态,缓冲区是否重叠,以及多个嵌套类型中的缓冲区是否重叠。对于Low*来说,我们必须显式地证明缓冲区的状态,同样地,对于嵌套的缓冲区,我们需要单独描述其中每一块缓冲区的状态,考虑到这种复杂性,我们提供了一些描述符来统一描述。
2、嵌套类型在堆修改时的引理:当堆发生改变时,我们需要编写证明来证明每一块缓冲区的状态变化。对于一维缓冲区,Low*提供的证明足以支持自动化证明,但由于嵌套类型的复杂性,我们需要额外的证明来帮助自动化证明器进行证明。为此,引入了一系列详尽的引理,这些引理涉及到嵌套类型的缓冲区在不同情境下(例如自身被修改或其他不相交缓冲区被修改时)的存活性、相交状态和是否被修改等特性的行为证明。在实际应用中,自动证明器可以自动引用这些引理,这有利于关于缓冲区状态的自动化证明工作。
3、封装的操作:为了提高嵌套类型的易用性,我们为其提供了一些封装Low*函数操作,这些操作已经被证明实现的正确性,通过使用这些操作,可以提高代码的编写速度。在本申请中,如果一些针对嵌套类型的操作需要被频繁使用、并且具备一定的复杂性,那么就考虑封装,因为这一方面提高了代码编写效率,另一方面消除了重复证明的开销。
以下以双重缓冲区为例来展示如何构建这些扩展,首先需要定义几个描述符,用于跟踪双重缓冲区包含的缓冲区内存状态的变化,包括:
(1)live_mutibuffer:这个描述符标记双重缓冲区的存活状态。
(2)internally_disjoint:这个描述符表示双重缓冲区内部缓冲区之间是互不相交的。
(3)disjoint_multi:这个描述符表示双重缓冲区和其他一维缓冲区不相交。
(4)disjoint_multi_multi:这个描述符表示两个二维缓冲区之间是互不相交的。
由于二重缓冲区内部包含大量的分散缓冲区,很难做到对所有的缓冲区的状态进行单个描述,为了简化双重缓冲区的证明过程,还需定义一个递归类型,用于简洁地描述双重缓冲区内部缓冲区的更改。定义如下:
此函数被标记为递归函数,它的主要功能是递归获取双重缓冲区内部的所有缓冲区。这样,在不需要单独描述某一个内部缓冲区,或者需要简洁地描述多个缓冲区时,我们可以使用此函数。尽管这降低了证明的精细度,但其带来的好处远大于其可能的副作用。这大大简化了我们的编程工作。由于这并非Low*的内建原语,因此我们需要为其编写一系列引理,使其更好地融入我们的编程框架,如loc_multi_sub_modify_lemma,它可以帮助证明器自动证明内部缓冲区的更改等价于对双重缓冲区中的整体区域的更改。
需要说明的是,可以采用一维缓冲区将数据处理任务拆分为更小、更可管理的部分,可以确保每个步骤不涉及大量数据的处理,然而,这种方法的可行性很大程度上依赖于程序员的专业知识和经验,可能需要投入更多的设计和开发时间,此外,对于一些固有复杂性的任务,这种方法可能并不适用;也可以采用较大的一维缓冲区,通过使用单个较大的缓冲区来存储所有所需数据,并通过多个索引来访问和修改特定值,这种方法的优势在于其简单和直观,容易实施,缺点是可能会浪费内存空间,特别是当数据结构复杂或访问模式不规则时。因此本申请优选采用了上述的多重缓冲区。
(ii)多重序列
为了方便规范证明,需要将缓冲区类型转换为规范使用的序列类型,同样以双重缓冲区为例,我们使用以下函数来帮助我们将双重缓冲区类型转换为功能规范中使用的序列类型:
这个函数能够对序列类型中的每一个元素执行函数f。对于堆h中的双重缓冲区mutibuffer,我们可以使用gmap(as_seq h)(as_seq h mutibuffer)的表达式方便地将其转换为lseq(lseq Type len_sub)len的嵌套序列类型。这样我们就可以方便地在规范和实现之间进行等价证明。嵌套的动态大小容器可以用相似的方法来实现,不过因为需要涉及动态内存分配,因此我们还需要为其动态内存分配释放操作所导致的内存状态变化撰写引理。
在代码的规范和实现的阶段,采用F*作为形式化语言描述所需编写的代码的正式规范。为了确保规范的可读性与标准文档或伪代码的兼容性,规范设计将采用纯函数式编程范式,并借助诸如无限精度整数(int)和自然数(nat)等抽象数学概念,从而消除对特定(如32位或64位)硬件架构的依赖。以下是正整数类型的定义,并引入了名为“add”的函数定义:
type pos=x:nat{0<x}
let add(x:pos)(y:pos):pos=x+y
在这里,F*可以使用SMT求解器自动化地证明add函数的输出结果为正整数的断言。
值得注意的是,虽然由F*编写的规范可以被方便地翻译为OCaml或F#程序进行实际运行,但最终目标是生成C语言实现。因此,在完成规范文件的撰写后,还需使用Low*编写与C语言类似的代码实现。在Low*环境中,虽可使用有限精度的机器整数(如uint8、uint32等),但不支持无界整数(int)、序列或其他堆分配的数据结构,例如列表,因为这些不可直接映射到C语言中的原生概念。不过,Low*允许使用不可变的记录(相当于C的结构体)以及可变缓冲区(相当于C的数组)
此设计方法的优势在于它确保了程序的严格形式化验证,同时通过使用低级语言进行实现,确保了代码的高性能和兼容性。这种结合了数学抽象和实际实现的方法可以帮助开发人员编写既准确又高效的代码,有助于推动复杂系统的可靠性和健壮性。
S3:验证代码:编译执行所述代码,以完成从规范到实现的正确性验证和内存安全性验证;
具体地,验证包括内存安全性验证和功能正确性验证。以下进行具体说明。
(1)内存安全性验证
Low*的Buffer库是对C语言数组的精确模拟,其提供了一套具有严格前提条件和后置条件的类型化接口。这些界定了一个安全的操作边界,确保缓冲区在访问和操作过程中的内存安全性。并且通过应用Hoare逻辑的理论基础,可以便捷地构建对一系列函数执行后状态的转移和变化的形式化证明。
为了确保代码安全并避免常见的错误和漏洞,例如缓冲区溢出、空指针取消引用、释放后使用和双重释放,必须严格遵循内存抽象的原则。具体来说,当进行任何缓冲区的读取或写入操作时,必须确保缓冲区保持活动状态,即缓冲区在其使用期间保持有效,并且不会被非法访问或修改,以避免悬挂指针或无效指针的问题,同时,其指针(即输入参数中缓冲区的首地址)指向当前堆中的有效分配数组,并确保所有的访问操作都严格限制在数组的边界内。以下是一个Low*中编写的32位无符号整数减法函数,其中添加了确保缓冲区a和b在初始堆中活动的前提条件。作为后置条件,期望证明函数minus仅修改了缓冲区a:
val minus:a:lbuffer uint32 1ul→b:lbuffer uint32 1ul→Stack unit
(requires(λh0→live h0 a∧live h0 b))
(ensures(λh0_h1→modifies_1a h0 h1))
requires子句包含输入和初始堆h0的前提条件;ensures子句给出返回值和初始堆h0与最终堆h1之间任何修改的后置条件。F*自动证明minus函数符合此前置后置条件,从而证明它具有内存安全性。
(2)功能正确性验证
具体地,要证明功能实现是正确的,就需要映射到它的规范中,功能规范是对代码行为的抽象描述,假设功能规范被正确编写,在此基础上需要证明实现也是正确的,那么可以通过证明Low*函数和规范中的函数行为(运算结果)是否相同来得到证明。而由于规范中的一些类型和Low*实现中使用的类型不同,无法直接判断是否相等,因而需要通过一些被证明和正确性无关的转换函数将low*实现中的类型转换为规范中的类型(即映射)。映射到规范的主要方法是使用和正确性无关的转换函数将Low*实现中的类型转换为规范中的类型,主要目的其实就是比较两者的执行结果是否相同。例如需要验证minus,首先假设规范中编写的minus函数声明如下:
val minus:a:uint32→b:uint32→uint32
那么需要修改Low*中编写的minus函数如下:
val minus:a:lbuffer uint32 1ul→b:lbuffer uint32 1ul→Stack unit
(requires(λh0→live h0 a∧live h0 b))
(ensures(λh0_h1→modifies_1a h0 h1
/\(get h1 a 0)==Spec.minus(get h0 a 0)(get h0 b 0)))
在这里,引入了新的后置条件,来形式化地证明Low*中的实现与规范的一致性,即使用精确、严格的数学逻辑和语法来描述函数的行为,而不是依赖于模糊或非正式的描述。这儿通过(get h1 a 0)==Spec.minus(get h0 a 0)(get h0 b 0)))这一条语句告诉自动化工具去验证这一性质(即该函数的执行结果需要能够被证明等同于规范中的函数使用相同输入运算得到的结果)。get函数用于检索给定堆状态下缓冲区中特定数据的值,而Spec是我们的规范命名空间,用于调用规范中定义的函数。
这种功能验证方法强调了实现与规范之间的一致性,提高了代码的可信度和健壮性。
S4:代码生成:通过KreMLin工具将已验证的Low*代码转化为语义等效的C代码;
具体地,从已验证的Low*代码提取到C由KreMLin工具完成,在这一过程中,KreMLin工具会擦除Low*代码中的所有形式化证明,并将其它部分翻译为C代码。这一过程不仅涉及语法的转换,还包括了一系列针对目标代码的优化和重构。
KreMLin工具特别强调提高代码的可读性。通过保留原始名称并生成符合编程习惯的、结构化的代码,KreMLin确保最终生成的C代码库不仅精确,而且可读。这对于进一步的代码审计和集成到现有代码库具有重要价值。
更具体地说,KreMLin实现了从Low*到CompCert C语言子集Clight的精确翻译方案。这种翻译方法遵循严格的语义保留原则。换句话说,如果一个程序在F*中经过了内存安全和功能正确性的证明,那么翻译后的Clight程序将继续享有相同的安全和正确性保证。
此外,为了进一步确保编译后代码的功能正确性和内存安全性,可以选择使用已验证的编译器如CompCert对生成的C代码进行编译。CompCert编译器能够保持从Clight到目标架构(如x86)的语义一致性,从而确保了整个编译链从源代码到目标机器代码的正确性保证。
综上所述,本申请识别了在满足复杂数据处理需求方面现有代码开发方案的局限性。此困难主要源于Low*仅支持一维缓冲区,导致对复杂、分散的大数据处理能力受限。为了克服这一难题,本申请提出了一种新方案,它具有多重缓冲区和可嵌套动态大小容器的特性。并且,鉴于嵌套类型证明的复杂性,设计了一组原语和证明来辅助这些嵌套类型的实现和验证。
本方案可实现以下技术效果:
1)内存分配的灵活性:多重缓冲区方案不仅解决了一维缓冲区的内存分配不灵活问题,还实现了嵌套动态容器,从而更好地满足了复杂数据处理需求。
2)验证的自动化:通过引入描述符和引理的封装,将复杂嵌套类型的证明过程自动化,显著提高了证明的效率和可用性。
3)代码构建的便捷性:通过封装的Low*函数操作和接口,降低了开发复杂性,从而提升了代码的编写效率和准确性。
4)广泛的应用适用性:本方案不局限于密码学库的构建,其可扩展性使其能够适应更多涉及复杂数据处理的应用领域,如大数据分析、并行计算等。
与前述的针对复杂数据处理需求的高效形式化代码构建方法的实施例相对应,本申请还提供了针对复杂数据处理需求的高效形式化代码构建装置的实施例。
图2是根据一示例性实施例示出的一种针对复杂数据处理需求的高效形式化代码构建装置框图。参照图2,该装置可以包括:
建立规范模块21:通过F*语言提取所要构建的代码的数学逻辑;
构建实现模块22:将所述数学逻辑基于HACL*库和Low*库进行构建实现,其中通过对HACL*库进行扩展以应对复杂数据处理需求;
验证代码模块23:编译执行所述代码,以完成从规范到实现的正确性验证和内存安全性验证;
代码生成模块24:通过kremlin工具自动将已验证的Low*转换为语义等效的C代码。
关于上述实施例中的装置,其中各个模块执行操作的具体方式已经在有关该方法的实施例中进行了详细描述,此处将不做详细阐述说明。
对于装置实施例而言,由于其基本对应于方法实施例,所以相关之处参见方法实施例的部分说明即可。以上所描述的装置实施例仅仅是示意性的,其中所述作为分离部件说明的单元可以是或者也可以不是物理上分开的,作为单元显示的部件可以是或者也可以不是物理单元,即可以位于一个地方,或者也可以分布到多个网络单元上。可以根据实际的需要选择其中的部分或者全部模块来实现本申请方案的目的。本领域普通技术人员在不付出创造性劳动的情况下,即可以理解并实施。
相应的,本申请还提供一种电子设备,包括:一个或多个处理器;存储器,用于存储一个或多个程序;当所述一个或多个程序被所述一个或多个处理器执行,使得所述一个或多个处理器实现如上述的针对复杂数据处理需求的高效形式化代码构建方法。如图3所示,为本发明实施例提供的一种针对复杂数据处理需求的高效形式化代码构建装置所在任意具备数据处理能力的设备的一种硬件结构图,除了图3示的处理器、内存以及网络接口之外,实施例中装置所在的任意具备数据处理能力的设备通常根据该任意具备数据处理能力的设备的实际功能,还可以包括其他硬件,对此不再赘述。
相应的,本申请还提供一种计算机可读存储介质,其上存储有计算机指令,该指令被处理器执行时实现如上述的针对复杂数据处理需求的高效形式化代码构建方法。所述计算机可读存储介质可以是前述任一实施例所述的任意具备数据处理能力的设备的内部存储单元,例如硬盘或内存。所述计算机可读存储介质也可以是外部存储设备,例如所述设备上配备的插接式硬盘、智能存储卡(Smart Media Card,SMC)、SD卡、闪存卡(Flash Card)等。进一步的,所述计算机可读存储介还可以既包括任意具备数据处理能力的设备的内部存储单元也包括外部存储设备。所述计算机可读存储介质用于存储所述计算机程序以及所述任意具备数据处理能力的设备所需的其他程序和数据,还可以用于暂时地存储已经输出或者将要输出的数据。
本领域技术人员在考虑说明书及实践这里公开的内容后,将容易想到本申请的其它实施方案。本申请旨在涵盖本申请的任何变型、用途或者适应性变化,这些变型、用途或者适应性变化遵循本申请的一般性原理并包括本申请未公开的本技术领域中的公知常识或惯用技术手段。
应当理解的是,本申请并不局限于上面已经描述并在附图中示出的精确结构,并且可以在不脱离其范围进行各种修改和改变。
Claims (5)
1.一种针对复杂数据处理需求的高效形式化代码构建方法,其特征在于,包括:
建立规范:通过F*语言提取所要构建的代码的数学逻辑;
构建实现:将所述数学逻辑基于HACL*库和Low*库进行构建实现,其中通过对HACL*库进行扩展以应对复杂数据处理需求;
验证代码:编译执行所述代码,以完成从规范到实现的正确性验证和内存安全性验证;
代码生成:通过kremlin工具自动将已验证的Low*转换为语义等效的C代码;
其中,所述复杂数据处理需求为处理的数据量大且具有动态变化的特性,需要具备实时的内存管理机制,能够根据数据的当前规模和结构动态分配或回收内存资源,并能支持对这些数据的频繁访问和修改操作;
所述扩展包括:
对HACL*库原有的缓冲区类型进行扩展,通过嵌套的方式定义多重缓冲区与可嵌套动态容器,以应对复杂数据处理需求;
将多重缓冲区与可嵌套动态容器的类型转换为规范使用的序列类型,以方便规范证明;
设置多重缓冲区与可嵌套动态容器后,增加以下扩展内容:描述缓冲区在堆中状态的描述符、嵌套类型在堆修改时的引理、Low*函数的封装;
其中,所述缓冲区在堆中状态包括缓冲区在堆中的存活状态,缓冲区是否重叠,以及多个嵌套类型中的缓冲区是否重叠;
所述嵌套类型在堆修改时的引理涉及嵌套类型的缓冲区在不同情况下的特性的行为证明,所述特性包括存活性、相交状态、是否被修改。
2.根据权利要求1所述的方法,其特征在于,将多重缓冲区与可嵌套动态容器的类型转换为规范使用的序列类型,具体为:将多重缓冲区与可嵌套动态容器通过函数转换为对应的嵌套序列类型,并为其动态内存分配释放操作所导致的内存状态变化设置引理。
3.一种针对复杂数据处理需求的高效形式化代码构建装置,其特征在于,包括:
建立规范模块:通过F*语言提取所要构建的代码的数学逻辑;
构建实现模块:将所述数学逻辑基于HACL*库和Low*库进行构建实现,其中通过对HACL*库进行扩展以应对复杂数据处理需求;
验证代码模块:编译执行所述代码,以完成从规范到实现的正确性验证和内存安全性验证;
代码生成模块:通过kremlin工具自动将已验证的Low*转换为语义等效的C代码;
其中,所述复杂数据处理需求为处理的数据量大且具有动态变化的特性,需要具备实时的内存管理机制,能够根据数据的当前规模和结构动态分配或回收内存资源,并能支持对这些数据的频繁访问和修改操作;
所述扩展包括:
对HACL*库原有的缓冲区类型进行扩展,通过嵌套的方式定义多重缓冲区与可嵌套动态容器,以应对复杂数据处理需求;
将多重缓冲区与可嵌套动态容器的类型转换为规范使用的序列类型,以方便规范证明;
设置多重缓冲区与可嵌套动态容器后,增加以下扩展内容:描述缓冲区在堆中状态的描述符、嵌套类型在堆修改时的引理、Low*函数的封装;
其中,所述缓冲区在堆中状态包括缓冲区在堆中的存活状态,缓冲区是否重叠,以及多个嵌套类型中的缓冲区是否重叠;
所述嵌套类型在堆修改时的引理涉及嵌套类型的缓冲区在不同情况下的特性的行为证明,所述特性包括存活性、相交状态、是否被修改。
4.一种电子设备,其特征在于,包括:
一个或多个处理器;
存储器,用于存储一个或多个程序;
当所述一个或多个程序被所述一个或多个处理器执行,使得所述一个或多个处理器实现如权利要求1-2任一项所述的方法。
5.一种计算机可读存储介质,其上存储有计算机指令,其特征在于,该指令被处理器执行时实现如权利要求1-2中任一项所述方法的步骤。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202311506458.XA CN117591087B (zh) | 2023-11-13 | 2023-11-13 | 一种针对复杂数据处理需求的高效形式化代码构建方法 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202311506458.XA CN117591087B (zh) | 2023-11-13 | 2023-11-13 | 一种针对复杂数据处理需求的高效形式化代码构建方法 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN117591087A CN117591087A (zh) | 2024-02-23 |
CN117591087B true CN117591087B (zh) | 2024-07-05 |
Family
ID=89915911
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN202311506458.XA Active CN117591087B (zh) | 2023-11-13 | 2023-11-13 | 一种针对复杂数据处理需求的高效形式化代码构建方法 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN117591087B (zh) |
Citations (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
GB0317226D0 (en) * | 2002-08-08 | 2003-08-27 | Hewlett Packard Development Co | Method for increasing performance of select and poll applications without recompilation |
CN107820604A (zh) * | 2015-04-14 | 2018-03-20 | 吉佳维申公司 | 具有联网设备的计算机驱动系统的半虚拟化安全威胁防护 |
Family Cites Families (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN110347405A (zh) * | 2019-07-01 | 2019-10-18 | 电子科技大学 | 一种schedule调度模块的形式化验证方法 |
CN112199271A (zh) * | 2020-08-31 | 2021-01-08 | 南京创联智软信息科技有限公司 | 源代码形式化验证方法 |
-
2023
- 2023-11-13 CN CN202311506458.XA patent/CN117591087B/zh active Active
Patent Citations (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
GB0317226D0 (en) * | 2002-08-08 | 2003-08-27 | Hewlett Packard Development Co | Method for increasing performance of select and poll applications without recompilation |
CN107820604A (zh) * | 2015-04-14 | 2018-03-20 | 吉佳维申公司 | 具有联网设备的计算机驱动系统的半虚拟化安全威胁防护 |
Also Published As
Publication number | Publication date |
---|---|
CN117591087A (zh) | 2024-02-23 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
Protzenko et al. | Verified low-level programming embedded in F | |
CN109375899B (zh) | 一种形式验证Solidity智能合约的方法 | |
TWI453671B (zh) | 用於程式碼轉換期間之本機碼和目標碼的組合執行之方法與裝置 | |
US11106437B2 (en) | Lookup table optimization for programming languages that target synchronous digital circuits | |
CN110870249A (zh) | 用于将高级语言代码编译为区块链平台上可执行的脚本的系统和方法 | |
US10908885B2 (en) | Quantum compiler | |
US20240020109A1 (en) | Method and system for supporting smart contracts in a blockchain network | |
US10942718B2 (en) | Systems and/or methods for type inference from machine code | |
JP2007528059A (ja) | ソフトウェアのモデル化、抽象、および分析のためのシステムと方法 | |
WO2022139952A1 (en) | Detecting added functionality in open source package | |
Ahmad et al. | Leveraging parallel data processing frameworks with verified lifting | |
Paraskevopoulou et al. | Computing correctly with inductive relations | |
CN115525287A (zh) | 多阶段编译器架构 | |
Sun et al. | Clover: Closed-loop verifiable code generation | |
Niemetz et al. | Towards satisfiability modulo parametric bit-vectors | |
Affeldt et al. | Towards formal verification of TLS network packet processing written in C | |
CN117591087B (zh) | 一种针对复杂数据处理需求的高效形式化代码构建方法 | |
Affeldt et al. | An intrinsic encoding of a subset of C and its application to TLS network packet processing | |
Bajwa et al. | Stack-aware hyperproperties | |
Šinkarovs et al. | Choosing is Losing: How to combine the benefits of shallow and deep embeddings through reflection | |
CN114579135B (zh) | 一种安装包生成方法及装置 | |
Kimmitt | A type-safe apparatus executing higher order functions in conjunction with hardware error tolerance | |
Johnson | Flibcpp user manual | |
Sanjel et al. | Partitionable programs using tyro v2 | |
Mullen | Pushing the Limits of Compiler Verification |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
GR01 | Patent grant | ||
GR01 | Patent grant |