梁小虎,魏 榮,黃曉凱,袁 野,尹貴增,劉 錕
(1.中國航天科技集團(tuán)第五研究院 北京衛(wèi)星信息工程研究所,北京 100086; 2.中國航天科工集團(tuán)第二研究院 七〇六所,北京 100854)
自2009年Gentry提出第一個(gè)全同態(tài)加密(fully homomorphic encryption,F(xiàn)HE)方案以來,經(jīng)歷了三代的發(fā)展[1],取得了一系列研究成果,一些全同態(tài)加密方案已經(jīng)開始在密文檢索、密文機(jī)器學(xué)習(xí)、安全多方計(jì)算[2]等領(lǐng)域中運(yùn)用。
同態(tài)加密API在同態(tài)密碼應(yīng)用中扮演著重要的角色。設(shè)計(jì)良好的同態(tài)加密API能降低同態(tài)密碼應(yīng)用開發(fā)的難度,促進(jìn)同態(tài)密碼應(yīng)用的發(fā)展。但是,目前業(yè)界還沒有正式發(fā)布的同態(tài)加密API標(biāo)準(zhǔn)。同態(tài)加密標(biāo)準(zhǔn)化開放聯(lián)盟發(fā)布的《基于RLWE的同態(tài)加密API標(biāo)準(zhǔn)》白皮書[3]和同態(tài)加密標(biāo)準(zhǔn)1.1版[4],均沒有包含相關(guān)內(nèi)容。
微軟為推動(dòng)同態(tài)密碼的應(yīng)用,推出了同態(tài)加密軟件庫SEAL[5],其API類的設(shè)計(jì)具有職責(zé)明確、接口定義清晰的特點(diǎn),降低了同態(tài)密碼應(yīng)用開發(fā)的難度,在電子投票[6]、指紋識別[7]、虹膜認(rèn)證[8]等應(yīng)用研究中得到了廣泛的應(yīng)用。
但SEAL庫的API類較多,不便于使用,不利于應(yīng)用與SEAL庫之間的松耦合。針對該問題,本文提出一種基于門面設(shè)計(jì)模式的優(yōu)化設(shè)計(jì)方法。在不改變現(xiàn)有API類的基礎(chǔ)上,引入門面類,減少應(yīng)用與SEAL庫之間的類交互數(shù)量,降低耦合度。
在設(shè)計(jì)軟件系統(tǒng)時(shí),將一個(gè)系統(tǒng)劃分成若干子系統(tǒng),能夠降低系統(tǒng)設(shè)計(jì)和實(shí)現(xiàn)的復(fù)雜度。最小化這些子系統(tǒng)之間的通信聯(lián)系和依賴關(guān)系,可以減少子系統(tǒng)之間的耦合度,實(shí)現(xiàn)子系統(tǒng)的高內(nèi)聚。但從應(yīng)用開發(fā)的角度,應(yīng)用需要直接與系統(tǒng)中的多個(gè)子系統(tǒng)進(jìn)行交互,增加了應(yīng)用與系統(tǒng)之間的耦合度,如圖1(a)所示。門面(Facade)設(shè)計(jì)模式通過引入門面對象,為系統(tǒng)中的一組子系統(tǒng)提供一個(gè)統(tǒng)一的對外接口,可以減少交互,使訪問系統(tǒng)中的子系統(tǒng)更加容易,如圖1(b)所示[9]。
圖1 應(yīng)用與系統(tǒng)之間的交互關(guān)系
SEAL庫使用C++語言開發(fā),實(shí)現(xiàn)了BFV[10]、CKKS[11]和BGV[12]方案,提供的API類基本相同。為便于描述,本文以BFV方案為例,開展API類的優(yōu)化設(shè)計(jì)、實(shí)現(xiàn)和測試。CKKS、BGV方案額外涉及的API類,可以采用類似方法進(jìn)行優(yōu)化設(shè)計(jì)和實(shí)現(xiàn)。
SEAL庫的BFV方案實(shí)現(xiàn)主要對外提供了加密參數(shù)類(EncryptionParameters)、上下文類(SEALContext)、密鑰生成器類(KeyGenerator)、公鑰類(PublicKey)、私鑰類(SecretKey)、重線性化密鑰類(RelinKeys)、加密器類(Encryptor)、解密器類(Decryptor)、同態(tài)計(jì)算器類(Evaluator)、明文類(Plaintext)、密文類(Ciphertext)和批處理編碼器類(BatchEncoder)等12個(gè)API類,各類對應(yīng)功能描述見表1。
SEAL庫API類從邏輯上可以劃分成算法、密鑰和數(shù)據(jù)編碼3個(gè)子系統(tǒng)。各子系統(tǒng)包含的API類及API類之間的關(guān)系如圖2所示(圖中用兩端分別為菱形和三角形的連接線表示包含關(guān)系,菱形端連接的類包含三角形端連接的類;用一端為三角形的實(shí)線表示生成關(guān)系,三角形端連接的類由另一端的類生成;用一端為三角形的虛線表示使用關(guān)系,三角形端連接的類被另一端的類所使用)。
表1 SEAL庫主要API類
圖2 SEAL庫主要API類圖
API類優(yōu)化設(shè)計(jì)的基本原理就是將SEAL庫看成是一個(gè)提供同態(tài)密碼服務(wù)的“黑盒子”,算法參數(shù)、密鑰等都存儲在它的內(nèi)部,通過接口對外提供算法參數(shù)設(shè)置、密鑰數(shù)據(jù)裝入導(dǎo)出,以及數(shù)據(jù)編解碼、加解密和同態(tài)計(jì)算等功能。
基于上述思想,SEAL庫只需為應(yīng)用提供3個(gè)API類即可:明文類、密文類和提供同態(tài)密碼服務(wù)的“黑盒子”類。因此,在SEAL庫的現(xiàn)有API類中,除Plaintext和Ciphertext類之外,其它類都可以不直接對應(yīng)用開放,而是將它們都封裝在“黑盒子”類內(nèi)部,通過“黑盒子”類對外提供服務(wù)。這樣的設(shè)計(jì)簡化了應(yīng)用與SEAL庫之間的交互關(guān)系。
使用門面設(shè)計(jì)模式,基于“開閉原則”(即對擴(kuò)展開放、對修改封閉,open-closed principle)[13],不用對SEAL庫現(xiàn)有的API類做任何修改,直接新增一個(gè)門面類Facade,代表提供同態(tài)密碼服務(wù)的“黑盒子”,它使用SEAL庫的現(xiàn)有相關(guān)API類為同態(tài)密碼應(yīng)用提供參數(shù)設(shè)置、密鑰生成、數(shù)據(jù)編碼、加密、解密及同態(tài)計(jì)算等功能服務(wù)。SEAL庫現(xiàn)有API類之間的關(guān)系、對外提供的接口仍然保持不變,這樣既能簡化門面類的設(shè)計(jì)和實(shí)現(xiàn),也能夠保證目前已經(jīng)基于SEAL庫現(xiàn)有API類開發(fā)的同態(tài)密碼應(yīng)用可以繼續(xù)使用SEAL庫正常工作。門面類Facade與SEAL庫現(xiàn)有API類之間的關(guān)系如圖3所示,連接線代表的含義與圖2相同。
圖3 引入門面類后的API類圖
Facade類包含EncryptionParameters、SEALContext、KeyGenerator、SecretKey、PublicKey、RelinKeys、Enc-ryptor、Decryptor、Evaluator和BatchEncoder類對象指針作為內(nèi)部成員變量,并在構(gòu)造函數(shù)中創(chuàng)建它們。Facade類對外提供的函數(shù)接口,大部分可以與EncryptionParameters、SEALContext、KeyGenerator、Encryptor、Decryptor、Evaluator和BatchEncoder類的對外函數(shù)接口保持一致。另外,可以根據(jù)需要適當(dāng)增加或屏蔽一些函數(shù)接口,或?qū)δ承┖瘮?shù)接口作適當(dāng)調(diào)整。對于與現(xiàn)有API類保持一致的函數(shù)接口,其實(shí)現(xiàn)非常簡單,直接通過相應(yīng)類對象指針調(diào)用對應(yīng)的類函數(shù)接口即可。
Facade類函數(shù)聲明包括構(gòu)造函數(shù)、析構(gòu)函數(shù)、加密接口、解密接口、同態(tài)計(jì)算接口和數(shù)據(jù)編碼接口的聲明,成員變量包括算法子系統(tǒng)的EncryptionParameters、SEALContext、KeyGenerator、Encryptor、Decryptor和Evaluator類對象指針,密鑰子系統(tǒng)的SecretKey、PublicKey和RelinKeys類對象指針,以及數(shù)據(jù)編碼子系統(tǒng)的BatchEncoder類對象指針。構(gòu)造函數(shù)以方案類型(BFV/BGV/CKKS)、模多項(xiàng)式次數(shù)、密文系數(shù)模數(shù)和明文模數(shù)為參數(shù)。Facade類聲明偽代碼如下。
Facade類聲明偽代碼:
class Facade{
public:
Facade (方案類型, 模多項(xiàng)式次數(shù), 密文系數(shù)模數(shù), 明文模數(shù));
~Facade ();
//加密接口聲明
void encrypt(const Plaintext &plain, Ciphertext &cipher);
//解密接口聲明
void decrypt(const Ciphertext &cipher, Plaintext &plain);
//同態(tài)計(jì)算接口聲明
void add_plain(const Ciphertext &cipher, const Plaintext &plain, Ciphertext &destination);
void multiply(const Ciphertext &cipher1, const Ciphertext &cipher2, Ciphertext &destination);
void square(const Ciphertext &cipher, Ciphertext &destination);
void relinearize(Ciphertext &cipher);
//數(shù)據(jù)編碼接口聲明
void encode(const vector
void decode(const Plaintext &plain, vector
private:
// 算法子系統(tǒng)對象指針
EncryptionParameters* parms;
SEALContext* context;
KeyGenerator* key_generator;
Encryptor* encryptor;
Decryptor* decryptor;
Evaluator* evaluator;
// 密鑰子系統(tǒng)對象指針
SecretKey* secret_key;
PublicKey* public_key;
RelinKeys* relin_keys;
// 數(shù)據(jù)編碼子系統(tǒng)對象指針
BatchEncoder* encoder;
}
在Facade類構(gòu)造函數(shù)內(nèi)部,首先基于“方案類型”參數(shù)創(chuàng)建EncryptionParameters對象,并設(shè)置模多項(xiàng)式次數(shù)、密文系數(shù)模數(shù)和明文模數(shù)等參數(shù);然后依次創(chuàng)建SEALContext、KeyGenerator、Encryptor、Decryptor、Evaluator和BatchEncoder對象,創(chuàng)建Encryptor、Decryptor和對象之前需要先創(chuàng)建公私鑰和重線性化密鑰。Facade類構(gòu)造函數(shù)偽代碼如下。
Facade類構(gòu)造函數(shù)偽代碼:
Facade:: Facade (方案類型, 模多項(xiàng)式次數(shù), 密文系數(shù)模數(shù), 明文模數(shù))
{
parms = new EncryptionParameters(方案類型);
為parms設(shè)置模多項(xiàng)式次數(shù)、密文系數(shù)模數(shù)、明文模數(shù)參數(shù)
context = new SEALContext(parms);
Key _generator = new KeyGenerator(context);
//調(diào)用key_generator創(chuàng)建公鑰
m_key_generator->create_public_key(public_key);
//調(diào)用key_generator創(chuàng)建私鑰
secret_key = m_key_generator->secret_key();
//調(diào)用key_generator創(chuàng)建重線性化密鑰
m_key_generator->create_relin_keys(m_relin_keys);
encryptor = new Encryptor(context, public_key);
decryptor = new Decryptor(context, secret_key);
evaluator = new Evaluator(context);
encoder=new BatchEncoder (context);
}
Facade類各函數(shù)接口的實(shí)現(xiàn)基本上都可以直接調(diào)用相應(yīng)對象的相應(yīng)接口實(shí)現(xiàn)。以加密接口為例,直接調(diào)用Encryptor類的encrypt接口即可,代碼如下。
Facade類encrypt接口實(shí)現(xiàn)代碼:
void Facade::encrypt(const Plaintext &plain, Ciphertext &cipher)
{
return encryptor->encrypt(plain, cipher);
}
在同態(tài)密碼的實(shí)際應(yīng)用模型中,一般有3個(gè)參與方,密鑰管理系統(tǒng)、用戶和計(jì)算中心[14]。密鑰管理系統(tǒng)完成密鑰的生成和分發(fā)。用戶對應(yīng)用數(shù)據(jù)進(jìn)行加密,提交計(jì)算中心,或向計(jì)算中心發(fā)起計(jì)算請求,接收計(jì)算結(jié)果并解密。計(jì)算中心負(fù)責(zé)響應(yīng)用戶的計(jì)算請求,對處于加密狀態(tài)下的應(yīng)用數(shù)據(jù)進(jìn)行計(jì)算,并將計(jì)算結(jié)果返回用戶。如圖4所示。
圖4 同態(tài)密碼實(shí)際應(yīng)用模型
在實(shí)際應(yīng)用中,密鑰管理系統(tǒng)不需要初始化與加解密和同態(tài)計(jì)算有關(guān)的類對象,用戶應(yīng)用不需要初始化與密鑰生成和同態(tài)計(jì)算有關(guān)的類對象,計(jì)算中心應(yīng)用不需要初始化與密鑰生成和加解密有關(guān)的類對象。因此,可采用延遲初始化技術(shù)[15],在構(gòu)造函數(shù)中只創(chuàng)建EncryptionParameters和SEALContext類對象,其它類對象則在需要使用它們的時(shí)候再去創(chuàng)建,從而提高Facade類構(gòu)造函數(shù)的性能。
在Facade類中定義相應(yīng)的私有g(shù)et_xxx函數(shù),在get_xxx函數(shù)內(nèi)部判斷相應(yīng)類對象是否創(chuàng)建,未創(chuàng)建則加以創(chuàng)建,已創(chuàng)建則直接返回已創(chuàng)建的對象。以Encryptor類對象的延遲創(chuàng)建為例,其對應(yīng)的get_encryptor函數(shù)代碼如下。
get_encryptor函數(shù)代碼:
Encryptor* Facade::get_encryptor()
{
if(encryptor == NULL)
encryptor = new Encryptor(*m_context, public_key);
return encryptor;
}
在其它使用Encryptor對象的函數(shù)中,不直接使用encryptor指針,而是調(diào)用get_encryptor函數(shù)獲取Encryptor對象。例如,使用延遲初始化技術(shù)后,encrypt函數(shù)的代碼如下。
使用延遲初始化技術(shù)后encrypt函數(shù)實(shí)現(xiàn)代碼:
void Facade::encrypt(const Plaintext &plain, Ciphertext &cipher)
{
return get_encryptor()->encrypt(plain, cipher);
}
3.4.1 優(yōu)化設(shè)計(jì)前應(yīng)用設(shè)計(jì)
API類優(yōu)化設(shè)計(jì)前,基于SEAL庫的BFV方案進(jìn)行同態(tài)密碼應(yīng)用開發(fā),其典型流程及每個(gè)步驟使用的API類如圖5所示,圖中左側(cè)為同態(tài)密碼應(yīng)用典型流程,右側(cè)為同態(tài)密碼應(yīng)用使用的SEAL庫API類,虛線連接每個(gè)步驟要使用的API類。
圖5 引入門面類前的同態(tài)密碼應(yīng)用流程
從圖5可見,同態(tài)密碼應(yīng)用總共包含13個(gè)步驟,使用了SEAL庫的12個(gè)API類。從圖中虛線可以看出,同態(tài)密碼應(yīng)用與SEAL庫之間的交互非常多,調(diào)用關(guān)系復(fù)雜,導(dǎo)致二者之間的耦合較緊。而且,SEAL庫也將自己如何實(shí)現(xiàn)參數(shù)設(shè)置、各API類之間的關(guān)系等設(shè)計(jì)實(shí)現(xiàn)細(xì)節(jié)暴露給了應(yīng)用,不利于各自的獨(dú)立迭代演進(jìn)。
3.4.2 優(yōu)化設(shè)計(jì)后應(yīng)用設(shè)計(jì)
增加了Facade類后,基于Facade類開發(fā)的同態(tài)密碼應(yīng)用主要流程減少為創(chuàng)建門面對象、數(shù)據(jù)編碼、數(shù)據(jù)加密、同態(tài)計(jì)算、計(jì)算結(jié)果解密和解密結(jié)果解碼等6個(gè)步驟,參數(shù)設(shè)置、上下文創(chuàng)建,密鑰生成器、加密器、同態(tài)計(jì)算器、解密器和數(shù)據(jù)編碼器的創(chuàng)建,密鑰生成等步驟都隱藏在門面對象內(nèi)部進(jìn)行。應(yīng)用與SEAL庫交互的API類減少為Facade、Plaintext和Ciphertext等3個(gè)類,如圖6所示。
圖6 引入門面類后的同態(tài)密碼應(yīng)用流程
與圖5相比,使用優(yōu)化后的API類,應(yīng)用的步驟減少了7步,交互的類減少了9個(gè)。應(yīng)用和SEAL庫之間的交互關(guān)系得到了很大的降低,由于很多類的設(shè)計(jì)和實(shí)現(xiàn)細(xì)節(jié)封裝在了SEAL庫內(nèi)部,因此減少了SEAL庫對應(yīng)用暴露的信息量,從而降低了應(yīng)用與SEAL庫之間的耦合程度,同時(shí)也降低了應(yīng)用編程的復(fù)雜度,降低了應(yīng)用開發(fā)人員學(xué)習(xí)和使用SEAL庫的難度。
測試程序基于SEAL庫源碼(V4.0)[16]中的BFV基本示例(nativeexamples1_bfv_basics.cpp)和數(shù)據(jù)編碼示例(nativeexamples2_ecoders.cpp)代碼進(jìn)行設(shè)計(jì)開發(fā)。
測試程序分別使用優(yōu)化設(shè)計(jì)前后的SEAL庫API類實(shí)現(xiàn)對函數(shù) (x+a)2(x、a均為整數(shù))的同態(tài)計(jì)算。測試程序設(shè)置的密碼算法安全級別為128,模多項(xiàng)式次數(shù)為8192,系數(shù)模數(shù)和明文模數(shù)為SEAL庫依據(jù)模多項(xiàng)式次數(shù)設(shè)置的默認(rèn)值,分別為218比特和1032193。為提高計(jì)算效率,測試程序采用批處理方式,對兩個(gè)2×4096矩陣的對應(yīng)元素執(zhí)行(x+a)2同態(tài)計(jì)算。其中,x的輸入矩陣為
即前4個(gè)元素為0、1、2、3,第4097個(gè)~4100個(gè)元素為4、5、6、7,其余元素均為0。a的輸入矩陣為
即元素為1、2的循環(huán)。
測試程序主要流程如圖7所示,包括優(yōu)化設(shè)計(jì)前和優(yōu)化設(shè)計(jì)后兩個(gè)測試?yán)?,分別使用優(yōu)化設(shè)計(jì)前后的API類,執(zhí)行相同的同態(tài)計(jì)算,均包括初始化、加密、同態(tài)計(jì)算和解密4個(gè)主要階段。
圖7 測試程序流程
測試在CPU為Intel Core i5-825U 1.60 Hz、內(nèi)存8 GB、操作系統(tǒng)為64位Windows 10的機(jī)器上進(jìn)行。測試程序在Windows PowerShell命令行外殼程序和腳本環(huán)境下使用CMake工具編譯。
測試方法為運(yùn)行測試程序,比對使用優(yōu)化設(shè)計(jì)前后API類的測試?yán)痰倪\(yùn)行結(jié)果,驗(yàn)證優(yōu)化設(shè)計(jì)的功能正確性。并且記錄4個(gè)主要階段的運(yùn)行時(shí)間,以測試優(yōu)化設(shè)計(jì)對性能的影響。為平衡其它因素(例如測試機(jī)器上其它程序的運(yùn)行)對測試程序運(yùn)行時(shí)間的影響,采用交替方式,對優(yōu)化設(shè)計(jì)前后的測試?yán)谭謩e運(yùn)行1000次,分別記錄初始化、加密、同態(tài)計(jì)算和解密4個(gè)主要階段的運(yùn)行時(shí)間總和。
優(yōu)化設(shè)計(jì)前后測試?yán)痰倪\(yùn)行結(jié)果如圖8(a)、圖8(b)所示。從圖中可以看出,優(yōu)化設(shè)計(jì)前后測試?yán)痰倪\(yùn)算結(jié)果一致,均為正確結(jié)果
因此優(yōu)化設(shè)計(jì)不會對SEAL庫的功能正確性產(chǎn)生影響。
優(yōu)化設(shè)計(jì)前后的測試?yán)谈麟A段運(yùn)行時(shí)間的總和見表2。測試結(jié)果顯示,相對于優(yōu)化設(shè)計(jì)前,優(yōu)化設(shè)計(jì)后測試?yán)痰母麟A段運(yùn)行用時(shí)有增有減,且均未超過0.5%,可見優(yōu)化設(shè)計(jì)對SEAL庫運(yùn)行性能的影響不大。
圖8 測試結(jié)果
本文針對SEAL庫API類較多的問題,采用門面設(shè)計(jì)模式,引入門面對象,將多個(gè)API類封裝在門面對象內(nèi)部,使應(yīng)用通過門面對象與SEAL庫交互,屏蔽了SEAL庫的內(nèi)部實(shí)現(xiàn)細(xì)節(jié),降低了應(yīng)用與SEAL庫之間的耦合程度,降低了應(yīng)用開發(fā)的復(fù)雜度。經(jīng)測試驗(yàn)證,該優(yōu)化設(shè)計(jì)切實(shí)可行,在保證功能正確性的前提下,對應(yīng)用的性能影響較小。
表2 優(yōu)化設(shè)計(jì)前后各階段運(yùn)行時(shí)間對比
下一步可繼續(xù)基于抽象工廠設(shè)計(jì)模式,為不同的同態(tài)加密軟硬件實(shí)現(xiàn)形態(tài)設(shè)計(jì)不同的門面類,使應(yīng)用可在不同實(shí)現(xiàn)形態(tài)之間動(dòng)態(tài)切換。