包致婷,柯俊明,楊 錚,3,龍 華,黃 東
(1.重慶理工大學 計算機科學與工程學院,重慶 400054;2.山東大學 計算機科學與技術學院,濟南 250000;3.新加坡科技設計大學信息系統技術與設計系,新加坡 138682;4.重慶機電職業技術大學信息工程學院,重慶 402760)
《中國制造2025》[1]提出要推進信息化和工業化的深度融合,但隨著工業互聯網的發展,工業控制系統逐漸從最初的封閉狀態向開放狀態轉變,使暴露在互聯網上的工控設備越來越多,從而對工控設備及系統安全構成了巨大威脅。工業互聯網的核心部件是信息物理系統(Cyber-Physical Systems,CPS)[2],但傳統CPS本身沒有安全措施,導致近年來CPS 受到一些大型攻擊[3-5]。CPS 的核心是控制物理過程的可編程邏輯控制器(Programmable Logic Controller,PLC)[6],因為PLC可以直接控制物理過程,所以成為攻擊者攻擊的主要目標。根據工業安全國家聯合實驗室[7]的調查顯示,全球的工控設備接入工業互聯網數量從2011 年80 億臺增長到2019 年的174 億臺。對工控設備遭受攻擊的數量進行統計,在2017 年上半年受攻擊設備的比例為36.61%,在2017 年下半年該比例增長至37.75%,并且這一增長趨勢一直延續到2018 年。
CPS使用防火墻[8]保證監控和數據采集(Supervisory Control And Data Acquisition,SCADA)系統和PLC 之間的安全通信和訪問控制,但防火墻并不能提出針對具體某個PLC 的直接身份認證,而現有PLC 沒有任何身份相關的機密信息,因此監控系統不能確定被監控PLC 身份的真實性。為高效實現PLC 的身份認證,引入時間基一次性密碼認證要素作為特定PLC 的身份證明憑證,有效解決了現有工業控制系統中常見安全通信協議Modbus[9]、DNP3[10]及OPC-UA[11]的認證要素問題。目前,使用較廣泛且高效的身份驗證方案為時間基一次性密碼方案[12]。時間基一次性密碼的身份驗證方案由LAMPORT[13]提出,該方案使用哈希鏈的具體實例,即利用哈希函數計算鏈上每個節點的密碼。文獻[14]提出S/KEY系統,并在系統中實現和驗證了哈希鏈。文獻[15]提出時間基一次性密碼(Time-based One-Time Password,TOTP)認證算法,該算法控制了密碼的有效期。文獻[16]結合S/KEY 和TOTP 方案提出時間基一次性密碼身份驗證方案T/KEY,但目前該方案并沒有在任何商業化PLC 上進行測試和應用。
在IEC 61131-3 規定的PLC 4 種標準編程語言中,結構化文本(Structured Text,ST)語言[17]更接近計算機高級編程語言,因此適用于實現密碼算法。但由于ST 是一種類似Python 的解釋性語言,沒有提供底層優化,并且許多商業PLC 并沒有提供密碼算法實現需要的移位功能,因此基于ST 實現的程序運行速度較慢。文獻[18]提出一種輕量級哈希函數PHOTON 算法,文獻[19]提出一種SPONGENT 哈希算法。因為英特爾的CPU 集成了AES 指令集,所以基于AES 優化的PHOTON 哈希算法在PC 上運行效率較高,而在PLC 上沒有類似的優化指令,因此使用哈希函數的時間基一次性密碼并不適用于PLC。文獻[20]提出的PRESENT 密碼算法和文獻[21]提出的SPECK 密碼算法通過比較原子操作個數得到:滿足128 位安全性的PHOTON 主要做了10 萬個賦值、2 萬個加法和1.5 萬個異或,SPONGENT 主要做了42 萬個賦值、3 000 個加法和6 000 個異或,PRESENT主要做了5 000 個賦值和60 個異或,SPECK 主要做了3 000個賦值、80個加法和100個異或。通過實驗測得在羅克韋爾Allen-Bradley 的PLC 上,賦值、加法和邏輯運算的時間分別為1.17 μs、1.51 μs 和2.3 μs。由于賦值操作時間和其他開銷近似,并且這些算法的賦值語句數量較多,因此以賦值時間為參考,PHOTON 和SPONGENT 分別約為SPECK 的33 和140 倍,相比分組密碼,進一步驗證了哈希在PLC 上運行效率較低。
為解決上述問題,本文構造一種適用于PLC 的時間基一次性密碼方案BC-TOTP,創新性地將分組密碼作為構建塊,充分利用分組密碼計算鏈中的每個節點,將其前身作為加密密鑰的輸入、常量作為加密消息、鏈尾節點作為初始驗證點、其他節點作為用于身份驗證的一次性密碼。
由于靜態密碼[22]容易被猜測和遭受暴力攻擊,因此目前研究集中于時間基一次性密碼。S/KEY[14]使用哈希函數進行實例化,其一次性密碼的有效期是不確定的,很容易被盜竊和濫用,并且S/KEY 在鏈的每次迭代過程中都使用相同的哈希函數,使得它更容易被破壞。T/KEY[16]結合了S/KEY 和TOTP 的方法,不僅無需在服務器上存儲密碼,而且驗證密碼在短時間內有效,但是T/KEY 使用的哈希函數在PLC 上的效率較低。
目前,大量研究方案均允許驗證方和BC-TOTP 設備之間進行雙向數字通信[23-24]。文獻[25]研究了多種基于二維碼的身份驗證方案,在LBD-QR-PIN 方案中移動設備生成密鑰對并將公鑰發送到驗證方。隨后,驗證方會生成一個隨機的128 位質詢,并使用證明方的公鑰對其進行加密,然后將其發送至身份驗證設備。身份驗證設備將質詢編碼為二維碼,然后用戶可以使用其移動設備進行掃描。移動設備使用其存儲的私鑰解密挑戰,計算挑戰的簡短6 位哈希,并將其呈現給用戶。用戶在身份驗證設備上輸入此6 位數字代碼,并將其發送到驗證方進行驗證。
文獻[26]針對當前工業控制系統的可靠性需求,提出一種全新的密碼算法活性證明(Proof of Aliveness,PoA),并基于單向函數(One-Way Function,OWF)的時間基一次性密碼(以下簡稱為OWF-TOTP)構建PoA的具體算法實現。相比基于OWF 的Lamport 一次一密方案[13],該方案采用的OWF-TOTP 在標準模型下被證明是安全的。但是,JIN 等[26]通過實驗證明,基于哈希函數實例化的OWF-TOTP 在Raspberry Pi 平臺上效率更高,而且該方案還未在真實商業化PLC 上進行測試。
本文使用的符號定義如表1 所示。

表1 符號定義Table 1 Symbol definition
本節描述了一個分組密碼方案BC。該方案由3種概率性多項式時間算法(BC.Gen,BC.Enc,BC.Dec)組成,具體步驟如下:
2)分組加密算法c←BC.Enc(k,m)。該算法輸入位長為lk的加密密鑰k和位長為lm的消息m,輸出位長為lc的密文c,其中lk≤lm=lc。
3)解密算法m←BC.Dec(k,c)。該算法輸入解密密鑰k和1 條密文c,輸出1 個明文m。
1)挑戰者B 開始運行初始化算法,并向攻擊者A 提供密鑰k。
2)攻擊者A 選擇2 個消息m0和m1發送給挑戰者,其中|m0|=|m1|。
4)A 根據c輸出對b的猜測b′。
5)若b′=b,Game 輸出1,則攻擊者贏得游戲。
定義1(IND-CPA 安全)若概率多項式時間攻擊者以不可忽略的優勢攻破了上述安全模型,則BC方案是IND-CPA 安全的,其中,攻擊者A 的優勢概率為
2.3.1 PRESENT 分組密碼算法
PRESENT 是SP 網絡[27]結構的超輕量級分組密碼算法,支持64 位的分組長度和80 位、128 位的密鑰長度,它一共需要31 輪加密,其中每輪的輪密鑰Ki(1≤i≤31)為64 位,在31 輪加密完成后,K32再運行一次輪密鑰加得到密文。本文主要關注密鑰長度為128 位的PRESENT 算法,算法步驟具體如下:
2)分組加密算法c←PRESENT.Enc(k,m)。該算法輸入加密密鑰k和位長為lm的消息m,輸出長度為lc的密文c。該算法首先做密鑰編排得到輪密鑰,將密鑰寄存器中存儲的128 位密鑰記為K=k127k126…k0,在加密算法第i輪使用的輪密鑰是密鑰寄存器K最左邊的64 位,即Ki=k127k126…k64。然后執行以下步驟更新密鑰寄存器K=k127k126…k0:
(1)密鑰寄存器循環左移61 位:
(k127k126…k0)=(k66k65…k68k67)
(2)換字盒(SBox)代換:
(k127k126k125k124)=SBox(k127k126k125k124)
(k123k122k121k120)=SBox(k123k122k121k120)
(3)k66k65k64k63k62與加密輪數做異或運算:
(k66k65k64k63k62)=(k66k65k64k63k62)⊕i
通過以上步驟得到輪密鑰K=(K0||K1K2…KT-1),其中T=32。然后,利用輪密鑰和消息m執行以下步驟:
(1)輪密鑰加AddRoundKey。對于z∈[64],該過程輸入64 位的狀態s和輪密鑰Ki,然后得到更新的狀態s通過計算s[z]:=s[z]⊕Ki[z],其中,初始狀態為消息m,Ki[z]為輪密鑰Ki的第z個比特。
(2)換字盒代換SBoxLayer。該過程將64 位的輸入狀態s分為16 個4 位的半字w15w14…w0,即w[a]=st[4a+3],其中a∈[16],然后通過查找換字盒SBox(w[a]),最后輸出更新后的狀態值s。
(3)換位盒置換PBoxLayer。該過程將狀態s進行重排,即s的第i位移動到PBox(s[i])指定的位置。
當31 輪循環完成后,加密算法使用K32再次運行輪密鑰加AddRoundKey 得到密文c。
3)解密算法m←PRESENT.Dec(k,c)。該算法為加密算法的逆過程,輸入密鑰k和1 條密文c,輸出1 個明文m。
2.3.2 SPECK 分組密碼算法
SPECK 分組密碼支持不同的分組長度和密鑰長度,le∈{16,24,32,48,64}為字的位長,lm=2le為分組長度,加密密鑰的位長為lk=lelw,其中lw∈{2,3,4}。如果le=16,則位移常量α:=7、β:=2,在其他情況下α:=8、β:=3,算法步驟具體如下:
2)分組加密算法c←SPECK.Enc(k,m)。該算法輸入加密密鑰k和1 條消息m=(m0||m1),輸出1 個密文c=(c0||c1),其中,|m0|=|m1|,c=(c0||c1)。該算法先做密鑰排程,即使用k生成每輪加密需要的輪密鑰,對于i∈[T-1],具體計算如下:

在得到輪密鑰K=(k0||k1k2…kT-1)后,每輪加密過程都需要執行SPECK.RFk(x,y)=(x′,(y<<<β)⊕x′),其中x′=((x>>>α)+y)⊕k,即整個加密過程為,其中°代表加密過程的結合,運行T次輪函數。第1 輪的初始狀態為x=m1、y=m0,最后一輪得到c1=x、c0=y。
3)解密算法m←SPECK.Dec(k,c)。該算法輸入密鑰k和1條密文c=(c0||c1),輸出1個明文m=(m0||m1),利用k得到輪密鑰K′=(kT-1||kT-2kT-1…k0)。解密算法利用輪函數的逆,每輪執行y′)<<<α,y′),其中y′=(x⊕y)>>>β。第1 輪的初始狀態為x=c1、y=c0,最后一輪得到m1=x、m0=y。

本節詳細介紹BC-TOTP 方案在羅克韋爾Allen Bradley 的PLC 上的運行過程。由于基于哈希的時間基一次性密碼不適用于PLC,因此本文設計一個通用的基于分組密碼的時間基一次性密碼方案BC-TOTP。鏈上的每個節點(尾節點除外)都是一個證明,用于在相應時間內向驗證方證明身份,如果驗證方在容忍時間內收到至少一個有效證明,則證明方身份驗證成功,這些節點將以從尾節點到頭節點的方向被消耗。同時,本節進一步學習了如何通過PRESENT 和SPECK 分組密碼算法實例化BC-TOTP,并且基于理想密碼模型[28]和分組密碼IND-CPA 的安全假設,證明了BC-TOTP 的安全性。
BC-TOTP 是一個鏈式結構,它采用類似于T/Key 的一次性密碼,其鏈的每個內部節點(尾節點除外)都是一個身份認證的密碼。對于1≤i≤N,鏈上的第i個密碼xi=BC.Enc(xi-1,m)都可由頭節點x0=k計算得到,用于證明方在相應的時間內向驗證方證明其身份。證明方保存頭節點x0,便于生成每一個驗證密碼,尾節點xN中存在驗證方,用于驗證證明方發送的密碼的正確性。證明方可以使用x0得到BCTOTP 鏈上任何一個一次性密碼,并將該密碼發送給驗證方進行身份驗證。驗證方在驗證時,第一次使用的驗證點為尾節點xN,驗證點是動態變化的,上一次身份驗證成功的密碼將成為下一個驗證點。在BC-TOTP 方案中,設置如下重要參數:ΔTL為單鏈的使用周期,n為一次性密碼的長度,N為單鏈的密碼節點數,離散時間槽{ti} 為時間的流逝,即ti+1-ti=ΔI,ΔI為每個密碼的驗證有效期(一般為30 s),ttol為身份驗證容忍時間,tack為驗證方收到有效密碼的最新時間。BC-TOTP 步驟具體如下:
1)初始化算法(stidc,stidv)←Setup(k,N,tstart,ΔTL,ttol)。該算法在初始化階段證明方輸入頭節點x0=k,使用分組加密函數BC.Enc 初始化分組密碼鏈,從頭節點x0開始到尾節點xN結束,其中N對于1≤i≤N,第i個密碼節點xi=BC.Enc(xi-1,m),其中m∈[N]。若證明方將計算后的尾節點值xN發送給驗證方,驗證方將初始驗證點πidc設置為πidc=xN,則證明方將保持狀態stidc=(k,tend,BC.Enc),驗證方的初始狀態設置為stidv=(πidc,tack,BC.Enc)。
2)密碼生成算法xt←Prover(stidc,t)。該算法的證明方輸入當前時間t和狀態stidc=(k,tend,BC.Enc),對于i∈[M],證明方通過計算第i個密碼xi=BC.Enc(xi-1,m) 得到一次性密碼xt,其中M=然后將xt發送給驗證方。
3)身份驗證算法s←Verifier(stidv,xt,t,tack)。該算法的驗證方首先檢查密碼接收時間t和最近一次身份驗證時間tack的差值是否小于容忍時間ttol,即ttack<ttol;然后檢查當前驗證點πidc是否可以由密碼xt計算得到。具體為:對于,通過計算第i個密碼xi=BC.Enc(xi-1,m)得到一次性密碼xZ,其中x0=xt。如果xZ與stidv的驗證點πidc相等,則證明方身份驗證成功,輸出s=1,同時驗證方更新狀態值stidv為πidc=xt,tack=t;否則身份驗證失敗,輸出s=0。
如圖1 所示,最近驗證方成功驗證的密碼為πidc=xN-2,它將作為驗證點檢查下一個密碼。證明方在時間t=tend-ΔI時發送一次性密碼xt=x1給驗證方,驗證方首先判斷是否在容忍時間內收到一次性密碼xt,如果收到則運行N-3 次分組加密函數BC.Enc 得到結果xZ,最終判斷xZ是否與驗證點πidc相等。如果相等,則身份驗證成功,輸出s=1,并且更新驗證方的狀態值stidv;否則身份驗證失敗,輸出s=0。在圖1 中密碼xt=x1到驗證點πidc的計算過程為BC.Enc(x1,m)°BC.Enc(x2,m)°…°BC.Enc(xN-3,m),即共運行N-3 次加密函數BC.Enc。

圖1 基于分組密碼的TOTP 流程Fig.1 Procedure of TOTP based on block cipher
在隨機預言模型中,本文使用分組密碼實例化BC.Enc 分組加密函數,并且利用分組長度為64 位、密鑰長度為128 位的分組密碼SPECK 和PRESENT在ECB 模式下實現BC.Enc。ECB 是將整個明文分成若干段相同的小段,然后對每一小段進行加密。因為在分組加密函數BC.Enc 中,輸出的密文將作為計算下一個密文的密鑰,所以需使用ECB 模式連接兩次具體分組密碼實例的密文,這樣才可以得到128 位的密文。本節定義函數<Enc >表示具體分組密碼實例,其<Enc >∈{PRESENT.Enc,SPECK.Enc}的輸入位長為lk的密鑰k和位長為lm的消息m,輸出lc的密文c,其中2lm=2lc=lk,計算如下:
c=BC.Enc(k,m)=<Enc >(k,m0)||<Enc >(k,m1)
其中,m=(m0||m1)并且|m0|=|m1|=64。
對于1≤i≤N,BC-TOTP 鏈中的每個密碼節點可由下式計算得到:
xi=<Enc >(xi-1,m0)||<Enc >(xi-1,m1)
其中:x0=k。
定理1假設分組密碼BC 在理想密碼模型下是IND-CPA 安全的,則本文提出的BC-TOTP 方案也是安全的。
證明假設攻擊者A 能夠攻破BC-TOTP 方案,即注入一個合法的密碼xi-1,那么就可以構建一個高效的算法B 來攻破分組密碼BC 的IND-CPA 安全性。
在理想密碼模型下,由于初始密鑰x0是隨機選擇的,因此此后基于其產生的每一個已知密碼xi=BC.Enc(xi-1,m)也是隨機的并且具有唯一性。因此,B可以首先猜測A 成功輸出的密文的索引值為i-1,如果B 猜測正確則繼續,否則終止實驗,其中B 猜中的概率為1/N。在猜測正確的情況下,B 通過詢問分組密碼的挑戰者,獲得一個挑戰密文c*=BC.Enc(xi-1,mb),其中消息(m0,m1)由B 任意選取。然后,B 基于密文c*來模擬索引值i到N的所有密碼。如果攻擊者A 能成功輸出密鑰xi-1,那么B 可以容易地通過對比c*和基于密鑰xi-1與消息(m0,m1)分別產生的密文,從而返回正確的b來攻破BC 的安全性。至此定理1 得證。
PRESENT 需要4 位換字盒和64 位換位盒,同時處理lm=64 的分組長度和支持兩種長度lk∈{80,128}的密鑰,本文主要關注密鑰長度為128 位的密鑰。首先將用數組k[4]表示的128 位密鑰k計算每輪64 位的輪密鑰,64 位的輪密鑰用K[0],K[1]表示,密鑰的最后4 位(k127k126k125k124)可用(k[3].[28],k[3].[29],k[3].[30],k[3].[31])表示,因為PLC 可以直接訪問變量的每一位。然后執行輪密鑰加、換字盒和換位盒的過程。最后該算法再運行一次輪密鑰加得到lc=64的密文c。


在算法1 中:步驟1~步驟12 是密鑰編排過程,tmp 獲取密鑰的其中4 位;步驟13 將內部狀態與對應的輪密鑰做異或運算;步驟14 是SBoxPLayer 通過查找換字盒每4 位更新內部狀態;步驟15、步驟16 是PBoxPLayer 實現的功能基于換字盒將內部狀態的第i個比特即st.[i]移動到PBox[i]指定的新位置,這里表示為st[PBox[i]]:=st.[i];步驟17 運行一次輪密鑰加后得到最終的密文。由于考慮網絡攻擊者對PLC 的讀寫攻擊,因此在步驟18 時進行密鑰清零。圖2 給出了PRESENT 密鑰編排過程,并采用ST 語言直接獲取密鑰寄存器所需的位。

圖2 PRESENT 代碼示例Fig.2 Code example of PRESENT
SPECK 主要由循環移位、異或和加法運算組成。SPECK 首先使用(k[0],k′[0],k′[1],k′[2])表示輸入的128 位密鑰,計算加密算法所需的輪密鑰K[T],而非直接采用預計算的輪密鑰。然后將輸入分成le=32 的兩個消息,計算T次輪函數。最后得到c[2]表示的64 位密文。


在算法2 中:步驟1~步驟5 是輪密鑰計算過程;步驟6~步驟9 是判斷α和β的值;步驟10~步驟13 是算法加密過程;步驟14 是將密文的密鑰k清零。圖3給出了SPECK 密鑰編排中的循環左移操作,該操作基于ST 語言直接對變量的每一位進行賦值。

圖3 SPECK 代碼示例Fig.3 Code example of SPECK
BC-TOTP 是利用分組密碼實現的時間基一次性密碼算法,數組k[4]表示128 位的密鑰,證明方使用密鑰作為鏈的頭節點x0[4]計算每一個節點,利用xu[4]=<Enc >(xu-1[4],m0)||<Enc >(xu-1[4],m1)得到鏈上的每一個節點,尾節點xN[4]發送給驗證方保存。在時間t時證明方可發送密碼xt[4]給驗證方進行身份驗證,驗證方如果在容忍時間內收到密碼xt[4],然后xt[4]經過Z次分組加密函數計算后得到的結果若等于πidc[4],則證明方身份驗證成功,輸出s=1,同時驗證方更新stidv為πidc[4]=xt[4],tack=t;否則身份驗證失敗,輸出s=0。


在算法3 中:步驟1~步驟9 是初始化過程,證明方計算尾節點xN[4]將其發送給驗證方,并且輸出證明方和驗證方的初始狀態值stidc和stidv;步驟10~步驟14 證明方在當前時間t內計算一次性密碼xt[4]并發送給驗證方;步驟15~步驟25 驗證方檢查證明方提交密碼的正確性,并更新狀態值。
本文在羅克韋爾Allen-Bradley的PLC上測試了BCTOTP 方案的性能。該PLC 配有Controllogix 5571 處理器和2 MB 內存,利用1 000 次重復實驗的平均結果驗證BC-TOTP 方案的時間效率。分組長度64 位,密鑰長度128 位的PRESENT 分組密碼算法的計算時間為14 ms,而同樣版本的SPECK 分組密碼算法的計算時間為8.2 ms,并且它們都是在實現了密鑰編排算法下的計算時間。因此,基于PRESENT 和SPECK 的鏈上相鄰密碼節點之間的計算時間分別為28 ms和16.4 ms。BC-TOTP 方案的計算成本由密碼數N決定,首先需要實例化這些參數,使得算法在PLC 上可執行。如圖4所示,若BC-TOTP 方案的鏈上密碼數N越大,則生成尾節點所需的計算時間越長。

圖4 SPECK 和PRESENT 算法的初始化時間比較Fig.4 Comparison of initialization time between SPECK and PRESENT algorithms
由于BC-TOTP 采用長鏈,為減少生成密碼所需的加密次數,參考T/Key 方案[16],根據證明方使用情況來緩存驗證點。如圖5 所示,密碼生成算法有worst 和average兩種情況,worst是在整條鏈上平均分布驗證點,average 驗證點的位置選擇是動態變化的。因為網絡攻擊者可以通過Pycomm 讀取和改寫PLC 上的變量值,以致PLC 無法調整新的驗證點,所以驗證點必須預計算保存。圖6給出了在worst情況下SPECK和PRESENT算法的身份驗證時間比較結果。

圖5 SPECK 和PRESENT 算法的密碼生成時間比較Fig.5 Comparison of password generation time between SPECK and PRESENT algorithms

圖6 SPECK 和PRESENT 算法的身份驗證時間比較Fig.6 Comparison of identity authentication time between SPECK and PRESENT algorithms
由圖6 看出,鏈上的節點越多,身份驗證所需時間越長。本文考慮PLC 內存大小,設置200 個緩存檢查點,并參考T/Key 方案的密碼使用間隔ΔI=30 s,如果N=1051200,則單鏈使用周期將近1 年。
本文構造基于分組密碼的時間基一次性密碼方案BC-TOTP,利用PRESENT 和SPECK 分組密碼算法對其進行實例化。通過基于理想密碼模型和分組密碼INDCPA 的安全假設證明了BC-TOTP 方案的安全性,并在羅克韋爾Allen-Bradley PLC 上的測試結果驗證了BCTOTP 方案的高效性與實用性。后續將使用偽隨機生成器鏈連接多個單鏈,打破單鏈密碼數量的限制,構造一種全新的時間基一次性密碼方案。