开放科学(资源服务)标志码(OSID):
0 概述
《中国制造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,创新性地将分组密码作为构建块,充分利用分组密码计算链中的每个节点,将其前身作为加密密钥的输入、常量作为加密消息、链尾节点作为初始验证点、其他节点作为用于身份验证的一次性密码。
1 相关工作
由于静态密码[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上进行测试。
2 预备知识
2.1 符号定义
本文使用的符号定义如表 1所示。
表 1
(Table 1)
表 1 符号定义
Table 1 Symbol definition
符号 |
描述 |
$ \kappa $ |
安全参数 |
$ \left|\right| $ |
字符串的连接 |
$ |\cdot | $ |
值的位长 |
$ \stackrel{\mathrm{\$}}{\leftarrow } $ |
均匀随机抽取元素 |
$ <<<, \mathrm{\;}>>> $ |
循环左移,循环右移 |
$ \left[a\right] $ |
0~$ (a-1) $的整数集合 |
|
下载CSV
表 1 符号定义
Table 1 Symbol definition
|
2.2 分组密码
本节描述了一个分组密码方案$ \mathrm{B}\mathrm{C} $。该方案由3种概率性多项式时间算法$ (\mathrm{B}\mathrm{C}.\mathrm{G}\mathrm{e}\mathrm{n}, \mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}, $ $ \mathrm{B}\mathrm{C}.\mathrm{D}\mathrm{e}\mathrm{c}) $组成,具体步骤如下:
1)初始化算法$ k\stackrel{\mathrm{\$}}{\leftarrow }\mathrm{B}\mathrm{C}.\mathrm{G}\mathrm{e}\mathrm{n}\left({1}^{\kappa }\right) $。该算法输入安全参数$ \kappa $,输出加密和解密使用的密钥$ k $,其中密钥位长为$ {l}_{k} $。
2)分组加密算法$ c\leftarrow \mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}(k, m) $。该算法输入位长为$ {l}_{k} $的加密密钥$ k $和位长为$ {l}_{m} $的消息$ m $,输出位长为$ {l}_{c} $的密文$ c $,其中$ {l}_{k}\le {l}_{m}={l}_{c} $。
3)解密算法$ m\leftarrow \mathrm{B}\mathrm{C}.\mathrm{D}\mathrm{e}\mathrm{c}(k, c) $。该算法输入解密密钥$ k $和1条密文$ c $,输出1个明文$ m $。
本节定义了一个安全相关游戏$ \mathrm{G}\mathrm{a}\mathrm{m}{\mathrm{e}}_{\mathrm{B}\mathrm{C}, \mathcal{A}}^{\mathrm{I}\mathrm{N}\mathrm{D}\mathrm{⁃}\mathrm{C}\mathrm{P}\mathrm{A}}\left(\kappa \right) $来形式化定义选择明文攻击下的不可区分性(INDistinguishability Under Chosen-Plaintext Attack,IND-CPA)。给定安全参数、分组密码方案$ \mathrm{B}\mathrm{C} $、挑战者$ \mathcal{B} $和攻击者$ \mathcal{A} $,游戏过程具体如下:
1)挑战者$ \mathcal{B} $开始运行初始化算法,并向攻击者$ \mathcal{A} $提供密钥$ k $。
2)攻击者$ \mathcal{A} $选择2个消息$ {m}_{0} $和$ {m}_{1} $发送给挑战者,其中$ \left|{m}_{0}\right|=\left|{m}_{1}\right| $。
3)挑战者随机选择b$ \stackrel{\mathrm{\$}}{\leftarrow } ${0,1},然后运行加密算法$ \mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c} $,得到密文$ c\leftarrow \mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}(k, {m}_{b}) $,将结果返回给攻击者$ \mathcal{A} $。
4)$ \mathcal{A} $根据$ c $输出对$ b $的猜测$ b\text{'} $。
5)若$ b\text{'}=b $,Game输出1,则攻击者赢得游戏。
定义1(IND-CPA安全) 若概率多项式时间攻击者以不可忽略的优势攻破了上述安全模型,则$ \mathrm{B}\mathrm{C} $方案是IND-CPA安全的,其中,攻击者$ \mathcal{A} $的优势概率为$ \left|\mathrm{P}\mathrm{r}\left[\mathrm{G}\mathrm{a}\mathrm{m}{\mathrm{e}}_{\mathrm{B}\mathrm{C}, \mathcal{A}}^{\mathrm{I}\mathrm{N}\mathrm{D}\mathrm{⁃}\mathrm{C}\mathrm{P}\mathrm{A}}\right(\kappa )=1]\right.\left.-1/2\right| $。
2.3 PRESENT和SPECK分组密码算法
2.3.1 PRESENT分组密码算法
PRESENT是SP网络[27]结构的超轻量级分组密码算法,支持64位的分组长度和80位、128位的密钥长度,它一共需要31轮加密,其中每轮的轮密钥$ {K}_{i}(1\le i\le 31) $为64位,在31轮加密完成后,$ {K}_{32} $再运行一次轮密钥加得到密文。本文主要关注密钥长度为128位的PRESENT算法,算法步骤具体如下:
1)密钥生成算法$ k\stackrel{\mathrm{\$}}{\leftarrow }\mathrm{P}\mathrm{R}\mathrm{E}\mathrm{S}\mathrm{E}\mathrm{N}\mathrm{T}.\mathrm{G}\mathrm{e}\mathrm{n}\left({1}^{\kappa }\right) $。该算法输入安全参数$ \kappa $,输出密钥$ k $。
2)分组加密算法$ c\leftarrow \mathrm{P}\mathrm{R}\mathrm{E}\mathrm{S}\mathrm{E}\mathrm{N}\mathrm{T}.\mathrm{E}\mathrm{n}\mathrm{c}(k, m) $。该算法输入加密密钥$ k $和位长为$ {l}_{m} $的消息$ m $,输出长度为$ {l}_{c} $的密文$ c $。该算法首先做密钥编排得到轮密钥,将密钥寄存器中存储的128位密钥记为$ K={k}_{127}{k}_{126}\cdots $ $ {k}_{0} $,在加密算法第$ i $轮使用的轮密钥是密钥寄存器$ K $最左边的64位,即$ {K}_{i}={k}_{127}{k}_{126}\cdots {k}_{64} $。然后执行以下步骤更新密钥寄存器$ K={k}_{127}{k}_{126}\cdots {k}_{0} $:
(1)密钥寄存器循环左移61位:
$ ({k}_{127}{k}_{126}\cdots {k}_{0})=({k}_{66}{k}_{65}\cdots {k}_{68}{k}_{67}) $
|
(2)换字盒(SBox)代换:
$ \left({k}_{127}{k}_{126}{k}_{125}{k}_{124}\right)=\mathrm{S}\mathrm{B}\mathrm{o}\mathrm{x}\left({k}_{127}{k}_{126}{k}_{125}{k}_{124}\right) $
|
$ \left({k}_{123}{k}_{122}{k}_{121}{k}_{120}\right)=\mathrm{S}\mathrm{B}\mathrm{o}\mathrm{x}\left({k}_{123}{k}_{122}{k}_{121}{k}_{120}\right) $
|
(3)$ {k}_{66}{k}_{65}{k}_{64}{k}_{63}{k}_{62} $与加密轮数做异或运算:
$ \left({k}_{66}{k}_{65}{k}_{64}{k}_{63}{k}_{62}\right)=\left({k}_{66}{k}_{65}{k}_{64}{k}_{63}{k}_{62}\right)\oplus i $
|
通过以上步骤得到轮密钥$ K=\left({K}_{0}\right||{K}_{1}{K}_{2}\cdots {K}_{T-1}) $,其中$ T=32 $。然后,利用轮密钥和消息$ m $执行以下步骤:
(1)轮密钥加$ \mathrm{A}\mathrm{d}\mathrm{d}\mathrm{R}\mathrm{o}\mathrm{u}\mathrm{n}\mathrm{d}\mathrm{K}\mathrm{e}\mathrm{y} $。对于$ z\in \left[64\right] $,该过程输入64位的状态$ s $和轮密钥$ {K}_{i} $,然后得到更新的状态$ s $通过计算$ s\left[z\right]:=s\left[z\right]\oplus {K}_{i}\left[z\right] $,其中,初始状态为消息$ m $,$ {K}_{i}\left[z\right] $为轮密钥$ {K}_{i} $的第$ z $个比特。
(2)换字盒代换$ \mathrm{S}\mathrm{B}\mathrm{o}\mathrm{x}\mathrm{L}\mathrm{a}\mathrm{y}\mathrm{e}\mathrm{r} $。该过程将64位的输入状态$ s $分为16个4位的半字$ {w}_{15}{w}_{14}\cdots {w}_{0} $,即$ w\left[a\right]=st[4a+3] $,其中$ a\in \left[16\right] $,然后通过查找换字盒$ \mathrm{S}\mathrm{B}\mathrm{o}\mathrm{x}\left(w\right[a\left]\right) $,最后输出更新后的状态值$ s $。
(3)换位盒置换$ \mathrm{P}\mathrm{B}\mathrm{o}\mathrm{x}\mathrm{L}\mathrm{a}\mathrm{y}\mathrm{e}\mathrm{r} $。该过程将状态$ s $进行重排,即$ s $的第$ i $位移动到$ \mathrm{P}\mathrm{B}\mathrm{o}\mathrm{x}\left(s\right[i\left]\right) $指定的位置。
当31轮循环完成后,加密算法使用$ {K}_{32} $再次运行轮密钥加$ \mathrm{A}\mathrm{d}\mathrm{d}\mathrm{R}\mathrm{o}\mathrm{u}\mathrm{n}\mathrm{d}\mathrm{K}\mathrm{e}\mathrm{y} $得到密文$ c $。
3)解密算法$ m\leftarrow \mathrm{P}\mathrm{R}\mathrm{E}\mathrm{S}\mathrm{E}\mathrm{N}\mathrm{T}.\mathrm{D}\mathrm{e}\mathrm{c}(k, c) $。该算法为加密算法的逆过程,输入密钥$ k $和1条密文$ c $,输出1个明文$ m $。
2.3.2 SPECK分组密码算法
SPECK分组密码支持不同的分组长度和密钥长度,$ {l}_{e}\in \left\{\mathrm{16, 24, 32, 48, 64}\right\} $为字的位长,$ {l}_{m}=2{l}_{e} $为分组长度,加密密钥的位长为$ {l}_{k}={l}_{e}{l}_{w} $,其中$ {l}_{w}\in \{\mathrm{2, 3}, 4\} $。如果$ {l}_{e}=16 $,则位移常量$ \alpha :=7 $、$ \beta :=2 $,在其他情况下$ \alpha :=8 $、$ \beta :=3 $,算法步骤具体如下:
1)密钥生成算法$ k\stackrel{\mathrm{\$}}{\leftarrow }\mathrm{S}\mathrm{P}\mathrm{E}\mathrm{C}\mathrm{K}.\mathrm{G}\mathrm{e}\mathrm{n}\left({1}^{\kappa }\right) $。该算法输入安全参数$ \kappa $,输出密钥$ k $,其中$ k=({k}_{0}, {k\text{'}}_{0}, \cdots , {k\text{'}}_{{l}_{w}-2}) $。
2)分组加密算法$ c\leftarrow \mathrm{S}\mathrm{P}\mathrm{E}\mathrm{C}\mathrm{K}.\mathrm{E}\mathrm{n}\mathrm{c}(k, m) $。该算法输入加密密钥$ k $和1条消息$ m=\left({m}_{0}\right|\left|{m}_{1}\right) $,输出1个密文$ c=\left({c}_{0}\right|\left|{c}_{1}\right) $,其中,$ \left|{m}_{0}\right|=\left|{m}_{1}\right| $,$ c=\left({c}_{0}\right|\left|{c}_{1}\right) $。该算法先做密钥排程,即使用$ k $生成每轮加密需要的轮密钥,对于$ i\in [T-1] $,具体计算如下:
(1)$ {k\text{'}}_{i+{l}_{w}-1}:=({k}_{i}+({k\text{'}}_{i}>>>\alpha \left)\right)\oplus i $。
(2)$ {k}_{i+1}:=({k}_{i}<<<\beta )\oplus {k\text{'}}_{i+{l}_{w}-1} $。
在得到轮密钥$ K=\left({k}_{0}\right||{k}_{1}{k}_{2}\cdots {k}_{T-1}) $后,每轮加密过程都需要执行$ \mathrm{S}\mathrm{P}\mathrm{E}\mathrm{C}\mathrm{K}.\mathrm{R}{\mathrm{F}}_{k}(x, y)=(x\text{'}, (y<<<\beta )\oplus x\text{'}) $,其中$ x\text{'}=\left(\right(x>>>\alpha )+y)\oplus k $,即整个加密过程为$ \mathrm{S}\mathrm{P}\mathrm{E}\mathrm{C}\mathrm{K}.\mathrm{R}{\mathrm{F}}_{{k}_{T-1}}\circ $ $ \mathrm{S}\mathrm{P}\mathrm{E}\mathrm{C}\mathrm{K}.\mathrm{R}{\mathrm{F}}_{{k}_{T-2}}\circ \cdots \circ \mathrm{S}\mathrm{P}\mathrm{E}\mathrm{C}\mathrm{K}.\mathrm{R}{\mathrm{F}}_{{k}_{0}} $,其中$ \circ $代表加密过程的结合,运行$ T $次轮函数。第1轮的初始状态为$ x={m}_{1} $、$ y={m}_{0} $,最后一轮得到$ {c}_{1}=x $、$ {c}_{0}=y $。
3)解密算法$ m\leftarrow \mathrm{S}\mathrm{P}\mathrm{E}\mathrm{C}\mathrm{K}.\mathrm{D}\mathrm{e}\mathrm{c}(k, c) $。该算法输入密钥$ k $和1条密文$ c=\left({c}_{0}\right|\left|{c}_{1}\right) $,输出1个明文$ m=\left({m}_{0}\right|\left|{m}_{1}\right) $,利用$ k $得到轮密钥$ K\text{'}=\left({k}_{T-1}\right||{k}_{T-2}{k}_{T-1}\cdots {k}_{0}) $。解密算法利用轮函数的逆,每轮执行$ \mathrm{S}\mathrm{P}\mathrm{E}\mathrm{C}\mathrm{K}.\mathrm{R}{\mathrm{F}}_{k}^{-1}(x, y)=\left(\right(x\oplus k)-y\text{'})<<<\alpha , y\text{'}) $,其中$ y\text{'}=(x\oplus y)>>>\beta $。第1轮的初始状态为$ x={c}_{1} $、$ y={c}_{0} $,最后一轮得到$ {m}_{1}=x $、$ {m}_{0}=y $。
3 BC-TOTP方案
本节详细介绍BC-TOTP方案在罗克韦尔Allen Bradley的PLC上的运行过程。由于基于哈希的时间基一次性密码不适用于PLC,因此本文设计一个通用的基于分组密码的时间基一次性密码方案BC-TOTP。链上的每个节点(尾节点除外)都是一个证明,用于在相应时间内向验证方证明身份,如果验证方在容忍时间内收到至少一个有效证明,则证明方身份验证成功,这些节点将以从尾节点到头节点的方向被消耗。同时,本节进一步学习了如何通过PRESENT和SPECK分组密码算法实例化BC-TOTP,并且基于理想密码模型[28]和分组密码IND-CPA的安全假设,证明了BC-TOTP的安全性。
3.1 基于分组密码的通用型TOTP方案
BC-TOTP是一个链式结构,它采用类似于T/Key的一次性密码,其链的每个内部节点(尾节点除外)都是一个身份认证的密码。对于$ 1\le i\le N $,链上的第$ i $个密码$ {x}_{i}=\mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}({x}_{i-1}, m) $都可由头节点$ {x}_{0}=k $计算得到,用于证明方在相应的时间内向验证方证明其身份。证明方保存头节点$ {x}_{0} $,便于生成每一个验证密码,尾节点$ {x}_{N} $中存在验证方,用于验证证明方发送的密码的正确性。证明方可以使用$ {x}_{0} $得到BC-TOTP链上任何一个一次性密码,并将该密码发送给验证方进行身份验证。验证方在验证时,第一次使用的验证点为尾节点$ {x}_{N} $,验证点是动态变化的,上一次身份验证成功的密码将成为下一个验证点。在BC-TOTP方案中,设置如下重要参数:$ {\Delta }_{\mathrm{T}\mathrm{L}} $为单链的使用周期,$ n $为一次性密码的长度,$ N $为单链的密码节点数,离散时间槽$ \left\{{t}_{i}\right\} $为时间的流逝,即$ {t}_{i+1}-{t}_{i}={\Delta }_{\mathrm{I}} $,$ {\Delta }_{\mathrm{I}} $为每个密码的验证有效期(一般为30 s),$ {t}_{\mathrm{t}\mathrm{o}\mathrm{l}} $为身份验证容忍时间,$ {t}_{\mathrm{a}\mathrm{c}\mathrm{k}} $为验证方收到有效密码的最新时间。BC-TOTP步骤具体如下:
1)初始化算法$ (\mathrm{s}{\mathrm{t}}_{\mathrm{i}\mathrm{d}\mathrm{c}}, \mathrm{s}{\mathrm{t}}_{\mathrm{i}\mathrm{d}\mathrm{v}})\leftarrow \mathrm{S}\mathrm{e}\mathrm{t}\mathrm{u}\mathrm{p}(k, N, {t}_{\mathrm{s}\mathrm{t}\mathrm{a}\mathrm{r}\mathrm{t}}, {\mathrm{\Delta }}_{\mathrm{T}\mathrm{L}}, $ $ {t}_{\mathrm{t}\mathrm{o}\mathrm{l}}) $。该算法在初始化阶段证明方输入头节点$ {x}_{0}=k $,使用分组加密函数$ \mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c} $初始化分组密码链,从头节点$ {x}_{0} $开始到尾节点$ {x}_{N} $结束,其中$ N=⌊{\Delta }_{\mathrm{T}\mathrm{L}}/{\Delta }_{\mathrm{I}}⌋ $。对于$ 1\le i\le N $,第$ i $个密码节点$ {x}_{i}=\mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}({x}_{i-1}, m) $,其中$ m\in \left[N\right] $。若证明方将计算后的尾节点值$ {x}_{N} $发送给验证方,验证方将初始验证点$ {\pi }_{\mathrm{i}\mathrm{d}\mathrm{c}} $设置为$ {\pi }_{\mathrm{i}\mathrm{d}\mathrm{c}}={x}_{N} $,则证明方将保持状态$ \mathrm{s}{\mathrm{t}}_{\mathrm{i}\mathrm{d}\mathrm{c}}=(k, {t}_{\mathrm{e}\mathrm{n}\mathrm{d}}, \mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}) $,验证方的初始状态设置为$ \mathrm{s}{\mathrm{t}}_{\mathrm{i}\mathrm{d}\mathrm{v}}=({\pi }_{\mathrm{i}\mathrm{d}\mathrm{c}}, {t}_{\mathrm{a}\mathrm{c}\mathrm{k}}, \mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}) $。
2)密码生成算法$ {x}_{t}\leftarrow \mathrm{P}\mathrm{r}\mathrm{o}\mathrm{v}\mathrm{e}\mathrm{r}(\mathrm{s}{\mathrm{t}}_{\mathrm{i}\mathrm{d}\mathrm{c}}, t) $。该算法的证明方输入当前时间$ t $和状态$ \mathrm{s}{\mathrm{t}}_{\mathrm{i}\mathrm{d}\mathrm{c}}=(k, {t}_{\mathrm{e}\mathrm{n}\mathrm{d}}, \mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}) $,对于$ i\in \left[M\right] $,证明方通过计算第$ i $个密码$ {x}_{i}=\mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}({x}_{i-1}, m) $得到一次性密码$ {x}_{t} $,其中$ M=⌈{t}_{\mathrm{e}\mathrm{n}\mathrm{d}}-t⌉/{\Delta }_{\mathrm{I}} $,然后将$ {x}_{t} $发送给验证方。
3)身份验证算法$ s\leftarrow \mathrm{V}\mathrm{e}\mathrm{r}\mathrm{i}\mathrm{f}\mathrm{i}\mathrm{e}\mathrm{r}(\mathrm{s}{\mathrm{t}}_{\mathrm{i}\mathrm{d}\mathrm{v}}, {x}_{t}, t, {t}_{\mathrm{a}\mathrm{c}\mathrm{k}}) $。该算法的验证方首先检查密码接收时间$ t $和最近一次身份验证时间$ {t}_{\mathrm{a}\mathrm{c}\mathrm{k}} $的差值是否小于容忍时间$ {t}_{\mathrm{t}\mathrm{o}\mathrm{l}} $,即$ t-{t}_{\mathrm{a}\mathrm{c}\mathrm{k}}<{t}_{\mathrm{t}\mathrm{o}\mathrm{l}} $;然后检查当前验证点$ {\pi }_{\mathrm{i}\mathrm{d}\mathrm{c}} $是否可以由密码$ {x}_{t} $计算得到。具体为:对于$ i\in \left[Z\right] $,$ Z=⌈t-{t}_{\mathrm{a}\mathrm{c}\mathrm{k}}⌉/{\Delta }_{\mathrm{I}} $,通过计算第$ i $个密码$ {x}_{i}=\mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}({x}_{i-1}, m) $得到一次性密码$ {x}_{Z} $,其中$ {x}_{0}={x}_{t} $。如果$ {x}_{Z} $与$ \mathrm{s}{\mathrm{t}}_{\mathrm{i}\mathrm{d}\mathrm{v}} $的验证点$ {\pi }_{\mathrm{i}\mathrm{d}\mathrm{c}} $相等,则证明方身份验证成功,输出$ s=1 $,同时验证方更新状态值$ \mathrm{s}{\mathrm{t}}_{\mathrm{i}\mathrm{d}\mathrm{v}} $为$ {\pi }_{\mathrm{i}\mathrm{d}\mathrm{c}}={x}_{t} $,$ {t}_{\mathrm{a}\mathrm{c}\mathrm{k}}=t $;否则身份验证失败,输出$ s=0 $。
如图 1所示,最近验证方成功验证的密码为$ {\pi }_{\mathrm{i}\mathrm{d}\mathrm{c}}={x}_{N-2} $,它将作为验证点检查下一个密码。证明方在时间$ t={t}_{\mathrm{e}\mathrm{n}\mathrm{d}}-{\Delta }_{\mathrm{I}} $时发送一次性密码$ {x}_{t}={x}_{1} $给验证方,验证方首先判断是否在容忍时间内收到一次性密码$ {x}_{t} $,如果收到则运行$ N-3 $次分组加密函数$ \mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c} $得到结果$ {x}_{Z} $,最终判断$ {x}_{Z} $是否与验证点$ {\pi }_{\mathrm{i}\mathrm{d}\mathrm{c}} $相等。如果相等,则身份验证成功,输出$ s=1 $,并且更新验证方的状态值$ \mathrm{s}{\mathrm{t}}_{\mathrm{i}\mathrm{d}\mathrm{v}} $;否则身份验证失败,输出$ s=0 $。在图 1中密码$ {x}_{t}={x}_{1} $到验证点$ {\pi }_{\mathrm{i}\mathrm{d}\mathrm{c}} $的计算过程为$ \mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}({x}_{1}, m)\circ \mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}({x}_{2}, m)\circ \cdots \circ \mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}({x}_{N-3}, m) $,即共运行$ N-3 $次加密函数$ \mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c} $。
3.2 算法实例
在随机预言模型中,本文使用分组密码实例化$ \mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c} $分组加密函数,并且利用分组长度为64位、密钥长度为128位的分组密码SPECK和PRESENT在ECB模式下实现$ \mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c} $。ECB是将整个明文分成若干段相同的小段,然后对每一小段进行加密。因为在分组加密函数$ \mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c} $中,输出的密文将作为计算下一个密文的密钥,所以需使用ECB模式连接两次具体分组密码实例的密文,这样才可以得到128位的密文。本节定义函数$ <\mathrm{E}\mathrm{n}\mathrm{c}> $表示具体分组密码实例,其$ <\mathrm{E}\mathrm{n}\mathrm{c}>\in \{\mathrm{P}\mathrm{R}\mathrm{E}\mathrm{S}\mathrm{E}\mathrm{N}\mathrm{T}.\mathrm{E}\mathrm{n}\mathrm{c}, \mathrm{S}\mathrm{P}\mathrm{E}\mathrm{C}\mathrm{K}.\mathrm{E}\mathrm{n}\mathrm{c}\} $的输入位长为$ {l}_{k} $的密钥$ k $和位长为$ {l}_{m} $的消息$ m $,输出$ {l}_{c} $的密文$ c $,其中$ 2{l}_{m}=2{l}_{c}={l}_{k} $,计算如下:
$ c=\mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}(k, m)=<\mathrm{E}\mathrm{n}\mathrm{c}>(k, {m}_{0})\left|\right|<\mathrm{E}\mathrm{n}\mathrm{c}>(k, {m}_{1}) $
|
其中,$ m=\left({m}_{0}\right|\left|{m}_{1}\right) $并且$ \left|{m}_{0}\right|=\left|{m}_{1}\right|=64 $。
对于$ 1\le i\le N $,BC-TOTP链中的每个密码节点可由下式计算得到:
$ {x}_{i}=<\mathrm{E}\mathrm{n}\mathrm{c}>({x}_{i-1}, {m}_{0})\left|\right|<\mathrm{E}\mathrm{n}\mathrm{c}>({x}_{i-1}, {m}_{1}) $
|
其中:$ {x}_{0}=k $。
3.3 安全性分析
定理1 假设分组密码BC在理想密码模型下是IND-CPA安全的,则本文提出的BC-TOTP方案也是安全的。
证明 假设攻击者$ \mathcal{A} $能够攻破BC-TOTP方案,即注入一个合法的密码$ {x}_{i-1} $,那么就可以构建一个高效的算法$ \mathcal{B} $来攻破分组密码$ \mathrm{B}\mathrm{C} $的IND-CPA安全性。
在理想密码模型下,由于初始密钥$ {x}_{0} $是随机选择的,因此此后基于其产生的每一个已知密码$ {x}_{i}=\mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}({x}_{i-1}, m) $也是随机的并且具有唯一性。因此,$ \mathcal{B} $可以首先猜测$ \mathcal{A} $成功输出的密文的索引值为$ i-1 $,如果$ \mathcal{B} $猜测正确则继续,否则终止实验,其中$ \mathcal{B} $猜中的概率为$ 1/N $。在猜测正确的情况下,$ \mathcal{B} $通过询问分组密码的挑战者,获得一个挑战密文$ c\mathrm{*}=\mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}({x}_{i-1}, {m}_{b}) $,其中消息$ ({m}_{0}, {m}_{1}) $由$ \mathcal{B} $任意选取。然后,$ \mathcal{B} $基于密文$ c\mathrm{*} $来模拟索引值$ i $到$ N $的所有密码。如果攻击者$ \mathcal{A} $能成功输出密钥$ {x}_{i-1} $,那么$ \mathcal{B} $可以容易地通过对比$ c\mathrm{*} $和基于密钥$ {x}_{i-1} $与消息$ ({m}_{0}, {m}_{1}) $分别产生的密文,从而返回正确的$ b $来攻破$ \mathrm{B}\mathrm{C} $的安全性。至此定理1得证。
4 算法实现与性能分析
4.1 PRESENT算法实现
PRESENT需要4位换字盒和64位换位盒,同时处理$ {l}_{m}=64 $的分组长度和支持两种长度$ {l}_{k}\in \left\{\mathrm{80, 128}\right\} $的密钥,本文主要关注密钥长度为128位的密钥。首先将用数组$ k\left[4\right] $表示的128位密钥$ k $计算每轮64位的轮密钥,64位的轮密钥用$ K\left[0\right], K\left[1\right] $表示,密钥的最后4位$ \left({k}_{127}{k}_{126}{k}_{125}{k}_{124}\right) $可用$ \left(k\right[3].[28], k[3].[29], $ $ k\left[3\right].\left[30\right], k\left[3\right].\left[31\right]) $表示,因为PLC可以直接访问变量的每一位。然后执行轮密钥加、换字盒和换位盒的过程。最后该算法再运行一次轮密钥加得到$ {l}_{c}=64 $的密文$ c $。
算法1 PRESENT分组密码算法
输入 消息数组$ m\left[2\right] $、密钥数组$ k\left[4\right] $
输出 密文数组$ c\left[2\right] $
1.$ \mathrm{s}\mathrm{t}\left[0\right]:=\mathrm{m}\left[0\right];\mathrm{\;}\mathrm{s}\mathrm{t}\left[1\right]:=\mathrm{m}\left[1\right]; $
2.$ \mathrm{f}\mathrm{o}\mathrm{r}\mathrm{\;}\mathrm{i}:=0\mathrm{\;}\mathrm{t}\mathrm{o}\mathrm{\;}\mathrm{T} $-$ 1\mathrm{\;}\mathrm{b}\mathrm{y}\mathrm{\;}1\mathrm{\;}\mathrm{d}\mathrm{o} $
3.$ \mathrm{K}\left[0\right]:=\mathrm{k}\left[2\right];\mathrm{\;}\mathrm{K}\left[1\right]:=\mathrm{k}\left[3\right]; $
4.密钥k左移61位;
5.$ \mathrm{t}\mathrm{m}\mathrm{p}.\left[0\right]:=\mathrm{k}\left[3\right].\left[28\right];\cdots ;\mathrm{t}\mathrm{m}\mathrm{p}.\left[3\right]:=\mathrm{k}\left[3\right].\left[31\right]; $
6.$ \mathrm{t}\mathrm{m}\mathrm{p}:=\mathrm{S}\mathrm{B}\mathrm{o}\mathrm{x}\left(\mathrm{t}\mathrm{m}\mathrm{p}\right); $
7.$ \mathrm{t}\mathrm{m}\mathrm{p}.\left[0\right]:=\mathrm{k}\left[3\right].\left[28\right];\cdots ;\mathrm{t}\mathrm{m}\mathrm{p}.\left[3\right]:= $ $ \mathrm{k}\left[\mathrm{\;}3\mathrm{\;}\right].\left[\mathrm{\;}31\mathrm{\;}\right]\mathrm{\;}; $
8.$ \mathrm{t}\mathrm{m}\mathrm{p}.\left[0\right]:=\mathrm{k}\left[3\right].\left[24\right];\cdots ;\mathrm{\;}\mathrm{t}\mathrm{m}\mathrm{p}.\left[3\right]:=\mathrm{k}\left[3\right].\left[27\right]; $
9.$ \mathrm{t}\mathrm{m}\mathrm{p}:=\mathrm{S}\mathrm{B}\mathrm{o}\mathrm{x}\left(\mathrm{t}\mathrm{m}\mathrm{p}\right); $
10.$ \mathrm{k}\left[3\right].\left[24\right]:=\mathrm{t}\mathrm{m}\mathrm{p}.\left[0\right];\mathrm{\;}\cdots ;\mathrm{\;}\mathrm{k}\left[3\right].\left[27\right]:=\mathrm{t}\mathrm{m}\mathrm{p}.\left[3\right]; $
11.K[1].[30],K[1].[31],K[2].[0],K[2].[1],K[2].[2]与$ \mathrm{i} $的有效低位做异或运算;
12.$ \mathrm{t}\mathrm{m}\mathrm{p}:=0; $
13.$ \{\mathrm{s}\mathrm{t}{\left[\mathrm{i}\right]\}}_{\mathrm{i}\in \left[2\right]}:=\{\mathrm{s}\mathrm{t}{\left[\mathrm{i}\right]\}}_{\mathrm{i}\in \left[2\right]}\mathrm{X}\mathrm{O}\mathrm{R}\mathrm{\;}\{\mathrm{K}{\left[\mathrm{i}\right]\}}_{\mathrm{i}\in \left[2\right]} $;
14.$ \{\mathrm{s}\mathrm{t}{\left[\mathrm{i}\right]\}}_{\mathrm{i}\in \left[2\right]}:=\mathrm{S}\mathrm{B}\mathrm{o}\mathrm{x}(\left\{\mathrm{s}\mathrm{t}{\left[\mathrm{i}\right]\}}_{\mathrm{i}\in \left[2\right]}\right); $
15.$ \{\mathrm{s}\mathrm{t}{\left[\mathrm{i}\right]\}}_{\mathrm{i}\in \left[2\right]}:=\mathrm{P}\mathrm{B}\mathrm{o}\mathrm{x}(\left\{\mathrm{s}\mathrm{t}{\left[\mathrm{i}\right]\}}_{\mathrm{i}\in \left[2\right]}\right); $
16.$ \mathrm{e}\mathrm{n}\mathrm{d}\_\mathrm{f}\mathrm{o}\mathrm{r}; $
17.再次运行$ \mathrm{A}\mathrm{d}\mathrm{d}\mathrm{R}\mathrm{o}\mathrm{u}\mathrm{n}\mathrm{d}\mathrm{K}\mathrm{e}\mathrm{y} $得到最后的密文;
18.将密钥$ \mathrm{k} $清零
在算法1中:步骤1~步骤12是密钥编排过程,$ \mathrm{t}\mathrm{m}\mathrm{p} $获取密钥的其中4位;步骤13将内部状态与对应的轮密钥做异或运算;步骤14是$ \mathrm{S}\mathrm{B}\mathrm{o}\mathrm{x}\mathrm{P}\mathrm{L}\mathrm{a}\mathrm{y}\mathrm{e}\mathrm{r} $通过查找换字盒每4位更新内部状态;步骤15、步骤16是$ \mathrm{P}\mathrm{B}\mathrm{o}\mathrm{x}\mathrm{P}\mathrm{L}\mathrm{a}\mathrm{y}\mathrm{e}\mathrm{r} $实现的功能基于换字盒将内部状态的第$ i $个比特即$ \mathrm{s}\mathrm{t}.\left[i\right] $移动到$ \mathrm{P}\mathrm{B}\mathrm{o}\mathrm{x}\left[i\right] $指定的新位置,这里表示为$ \mathrm{s}\mathrm{t}\left[\mathrm{P}\mathrm{B}\mathrm{o}\mathrm{x}\right[i\left]\right]:=\mathrm{s}\mathrm{t}.\left[i\right] $;步骤17运行一次轮密钥加后得到最终的密文。由于考虑网络攻击者对PLC的读写攻击,因此在步骤18时进行密钥清零。图 2给出了PRESENT密钥编排过程,并采用ST语言直接获取密钥寄存器所需的位。
4.2 SPECK算法实现
SPECK主要由循环移位、异或和加法运算组成。SPECK首先使用$ \left(k\right[0], k\text{'}[0], k\text{'}[1], k\text{'}[2\left]\right) $表示输入的128位密钥,计算加密算法所需的轮密钥$ K\left[T\right] $,而非直接采用预计算的轮密钥。然后将输入分成$ {l}_{e}=32 $的两个消息,计算$ T $次轮函数。最后得到$ c\left[2\right] $表示的64位密文。
算法2 SPECK分组密码算法
输入 消息数组$ m\left[2\right] $、密钥数组$ k\left[T\right]\mathrm{和}\mathrm{k}\text{'}\left[T\right] $
输出 密文数组$ c\left[2\right] $
1.$ \mathrm{f}\mathrm{o}\mathrm{r}\mathrm{\;}\mathrm{i}:=0\mathrm{\;}\mathrm{t}\mathrm{o}\mathrm{\;}\mathrm{T} $-$ 2\mathrm{\;}\mathrm{b}\mathrm{y}\mathrm{\;}1\mathrm{\;}\mathrm{d}\mathrm{o} $
2.$ \mathrm{i}\mathrm{d}\mathrm{x}:=\mathrm{i}+{\mathrm{l}}_{\mathrm{w}} $-1;
3.$ \mathrm{k}\text{'}\left[\mathrm{i}\mathrm{d}\mathrm{x}\right]:=\left(\mathrm{k}\right[\mathrm{i}]+\mathrm{k}\text{'}[\mathrm{i}]>>>\mathrm{\alpha }))\mathrm{\;}\mathrm{X}\mathrm{O}\mathrm{R}\mathrm{\;}\mathrm{i}; $
4.$ \mathrm{k}[\mathrm{i}+1]:=\left(\mathrm{k}\right[\mathrm{i}]<<<\mathrm{\beta })\mathrm{\;}\mathrm{X}\mathrm{O}\mathrm{R}\mathrm{\;}\mathrm{k}\text{'}\left[\mathrm{i}\mathrm{d}\mathrm{x}\right]; $
5.$ \mathrm{e}\mathrm{n}\mathrm{d}\_\mathrm{f}\mathrm{o}\mathrm{r}; $
6.$ \mathrm{c}\left[0\right]:=\mathrm{m}\left[0\right];\mathrm{\;}\mathrm{c}\left[1\right]:=\mathrm{m}\left[1\right];\mathrm{\;}\mathrm{\alpha }:=8;\mathrm{\;}\mathrm{\beta }:=3; $
7.$ \mathrm{i}\mathrm{f}{\mathrm{l}}_{\mathrm{e}}=16\mathrm{\;}\mathrm{t}\mathrm{h}\mathrm{e}\mathrm{n} $
8.$ \mathrm{\alpha }:=7;\mathrm{\;}\mathrm{\beta }:=2; $
9.$ \mathrm{e}\mathrm{n}\mathrm{d}\_\mathrm{i}\mathrm{f}; $
10.$ \mathrm{f}\mathrm{o}\mathrm{r}\mathrm{\;}\mathrm{i}:=0\mathrm{\;}\mathrm{t}\mathrm{o}\mathrm{\;}\mathrm{T} $-$ 1\mathrm{\;}\mathrm{b}\mathrm{y}\mathrm{\;}1\mathrm{\;}\mathrm{d}\mathrm{o} $
11.$ \mathrm{c}\left[1\right]:=\left(\right(\mathrm{c}\left[1\right]>>>\mathrm{\alpha })+\mathrm{c}[0\left]\right)\mathrm{\;}\mathrm{X}\mathrm{O}\mathrm{R}\mathrm{\;}\mathrm{k}\left[\mathrm{i}\right]; $
12.$ \mathrm{c}\left[0\right]:=\left(\mathrm{c}\right[0]<<<\mathrm{\beta })\mathrm{\;}\mathrm{X}\mathrm{O}\mathrm{R}\mathrm{\;}\mathrm{c}\left[1\right]; $
13.$ \mathrm{e}\mathrm{n}\mathrm{d}\_\mathrm{f}\mathrm{o}\mathrm{r}; $
14.将密钥$ \mathrm{k} $清零
在算法2中:步骤1~步骤5是轮密钥计算过程;步骤6~步骤9是判断$ \alpha $和$ \beta $的值;步骤10~步骤13是算法加密过程;步骤14是将密文的密钥$ k $清零。图 3给出了SPECK密钥编排中的循环左移操作,该操作基于ST语言直接对变量的每一位进行赋值。
4.3 BC-TOTP算法实现
BC-TOTP是利用分组密码实现的时间基一次性密码算法,数组$ k\left[4\right] $表示128位的密钥,证明方使用密钥作为链的头节点$ {x}_{0}\left[4\right] $计算每一个节点,利用$ {x}_{u}\left[4\right]=<\mathrm{E}\mathrm{n}\mathrm{c}>\left({x}_{u-1}\right[4], {m}_{0})\mathrm{\;}\left|\right|<\mathrm{E}\mathrm{n}\mathrm{c}>\left({x}_{u-1}\right[4], {m}_{1}) $得到链上的每一个节点,尾节点$ {x}_{N}\left[4\right] $发送给验证方保存。在时间$ t $时证明方可发送密码$ {x}_{t}\left[4\right] $给验证方进行身份验证,验证方如果在容忍时间内收到密码$ {x}_{t}\left[4\right] $,然后$ {x}_{t}\left[4\right] $经过$ Z $次分组加密函数计算后得到的结果若等于$ {\pi }_{\mathrm{i}\mathrm{d}\mathrm{c}}\left[4\right] $,则证明方身份验证成功,输出$ s=1 $,同时验证方更新$ \mathrm{s}{\mathrm{t}}_{\mathrm{i}\mathrm{d}\mathrm{v}} $为$ {\pi }_{\mathrm{i}\mathrm{d}\mathrm{c}}\left[4\right]={x}_{t}\left[4\right] $,$ {t}_{\mathrm{a}\mathrm{c}\mathrm{k}}=t $;否则身份验证失败,输出$ s=0 $。
算法3 BC-TOTP算法
1.$ \{\mathrm{x}{[0, \mathrm{i}]\}}_{\mathrm{i}\in \left[4\right]}:=\{\mathrm{k}{\left[\mathrm{i}\right]\}}_{\mathrm{i}\in \left[4\right]} $;
2.$ \mathrm{f}\mathrm{o}\mathrm{r}\mathrm{\;}\mathrm{u}:=1\mathrm{\;}\mathrm{t}\mathrm{o}\mathrm{\;}\mathrm{N}\mathrm{\;}\mathrm{b}\mathrm{y}\mathrm{\;}1\mathrm{\;}\mathrm{d}\mathrm{o} $
3.$ \{\mathrm{x}{[\mathrm{u}, \mathrm{i}]\}}_{\mathrm{i}\in \left[4\right]}:=\mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}(\left\{\mathrm{x}\right[\mathrm{u} $-$ {1, \mathrm{i}\left]\right\}}_{\mathrm{i}\in \left[4\right]}, \mathrm{u}) $;
4.$ \mathrm{e}\mathrm{n}\mathrm{d}\_\mathrm{f}\mathrm{o}\mathrm{r}; $
5.$ \{{\mathrm{\pi }}_{\mathrm{i}\mathrm{d}\mathrm{c}}{\left[\mathrm{i}\right]\}}_{\mathrm{i}\in \left[4\right]}:=\{\mathrm{x}{[\mathrm{N}, \mathrm{i}]\}}_{\mathrm{i}\in \left[4\right]} $;
6.$ {\mathrm{t}}_{\mathrm{a}\mathrm{c}\mathrm{k}}:={\mathrm{t}}_{\mathrm{s}\mathrm{t}\mathrm{a}\mathrm{r}\mathrm{t}} $;
7.$ {\mathrm{t}}_{\mathrm{e}\mathrm{n}\mathrm{d}}:={\mathrm{t}}_{\mathrm{s}\mathrm{t}\mathrm{a}\mathrm{r}\mathrm{t}}+{\mathrm{\Delta }}_{\mathrm{T}\mathrm{L}};\mathrm{s}{\mathrm{t}}_{\mathrm{i}\mathrm{d}\mathrm{v}}=({\mathrm{\pi }}_{\mathrm{i}\mathrm{d}\mathrm{c}}, {\mathrm{t}}_{\mathrm{a}\mathrm{c}\mathrm{k}}, \mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}); $
8.$ \mathrm{s}{\mathrm{t}}_{\mathrm{i}\mathrm{d}\mathrm{c}}:=\left(\right\{\mathrm{k}{\left[\mathrm{i}\right]\}}_{\mathrm{i}\in \left[4\right]}, {\mathrm{t}}_{\mathrm{e}\mathrm{n}\mathrm{d}}, \mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}) $;
9.$ \mathrm{s}{\mathrm{t}}_{\mathrm{i}\mathrm{d}\mathrm{v}}:=\left(\right\{{\mathrm{\pi }}_{\mathrm{i}\mathrm{d}\mathrm{c}}{\left[\mathrm{i}\right]\}}_{\mathrm{i}\in \left[4\right]}, {t}_{\mathrm{a}\mathrm{c}\mathrm{k}}, \mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}) $;
10.$ \mathrm{M}:=({\mathrm{t}}_{\mathrm{e}\mathrm{n}\mathrm{d}} $-$ \mathrm{t})\mathrm{\;}\mathrm{D}\mathrm{I}\mathrm{V}{\mathrm{\Delta }}_{\mathrm{I}}; $
11.$ \mathrm{f}\mathrm{o}\mathrm{r}\mathrm{\;}\mathrm{u}:=1\mathrm{\;}\mathrm{t}\mathrm{o}\mathrm{\;}\mathrm{M}\mathrm{\;}\mathrm{b}\mathrm{y}\mathrm{\;}1\mathrm{\;}\mathrm{d}\mathrm{o} $
12.$ \{\mathrm{x}{[\mathrm{u}, \mathrm{i}]\}}_{\mathrm{i}\in \left[4\right]}:=\mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}(\left\{\mathrm{x}\right[\mathrm{u} $-$ {1, \mathrm{i}\left]\right\}}_{\mathrm{i}\in \left[4\right]}, \mathrm{u}) $;
13.$ \mathrm{e}\mathrm{n}\mathrm{d}\_\mathrm{f}\mathrm{o}\mathrm{r}; $
14.$ \{\mathrm{x}{[\mathrm{t}, \mathrm{i}]\}}_{\mathrm{i}\in \left[4\right]}:=\{\mathrm{x}{[\mathrm{M}, \mathrm{i}]\}}_{\mathrm{i}\in \left[4\right]}; $
15.$ \mathrm{i}\mathrm{f}\mathrm{\;}\mathrm{t} $-$ {\mathrm{t}}_{\mathrm{a}\mathrm{c}\mathrm{k}}>{\mathrm{t}}_{\mathrm{t}\mathrm{o}\mathrm{l}}\mathrm{t}\mathrm{h}\mathrm{e}\mathrm{n} $
16.身份验证失败;
17.$ \mathrm{e}\mathrm{n}\mathrm{d}\_\mathrm{i}\mathrm{f}; $
18.$ \mathrm{Z}:= $($ \mathrm{t} $-$ {\mathrm{t}}_{\mathrm{a}\mathrm{c}\mathrm{k}} $)$ \mathrm{D}\mathrm{I}\mathrm{V}{\mathrm{\Delta }}_{\mathrm{I}}; $
19.$ \{\mathrm{x}\text{'}{[0, \mathrm{i}]\}}_{\mathrm{i}\in \left[4\right]}^{}:=\{\mathrm{x}{[\mathrm{t}, \mathrm{i}]\}}_{\mathrm{i}\in \left[4\right]}; $
20.$ \mathrm{f}\mathrm{o}\mathrm{r}\mathrm{\;}\mathrm{u}:=1\mathrm{\;}\mathrm{t}\mathrm{o}\mathrm{\;}\mathrm{Z}\mathrm{\;}\mathrm{b}\mathrm{y}\mathrm{\;}1\mathrm{\;}\mathrm{d}\mathrm{o} $
21.$ \{\mathrm{x}\text{'}{[\mathrm{u}, \mathrm{i}]\}}_{\mathrm{i}\in \left[4\right]}:=\mathrm{B}\mathrm{C}.\mathrm{E}\mathrm{n}\mathrm{c}(\left\{\mathrm{x}\text{'}\right[\mathrm{u} $-$ {1, \mathrm{i}\left]\right\}}_{\mathrm{i}\in \left[4\right]}, \mathrm{u}) $;
22.$ \mathrm{e}\mathrm{n}\mathrm{d}\_\mathrm{f}\mathrm{o}\mathrm{r}; $
23.$ \mathrm{i}\mathrm{f}\mathrm{\;}\{\mathrm{x}\text{'}{[\mathrm{Z}, \mathrm{i}]\}}_{\mathrm{i}\in \left[4\right]}:=\{{\mathrm{\pi }}_{\mathrm{i}\mathrm{d}\mathrm{c}}{\left[\mathrm{i}\right]\}}_{\mathrm{i}\in \left[4\right]}\mathrm{t}\mathrm{h}\mathrm{e}\mathrm{n} $
24.身份验证成功,输出$ \mathrm{s}=1 $,更新状态值
$\{{\mathrm{\pi }}_{\mathrm{i}\mathrm{d}\mathrm{c}}{\left[\mathrm{i}\right]\}}_{\mathrm{i}\in \left[4\right]}:=\{\mathrm{x}\text{'}{[0, \mathrm{i}]\}}_{\mathrm{i}\in \left[4\right]};{\mathrm{t}}_{\mathrm{a}\mathrm{c}\mathrm{k}}=\mathrm{t}\text{;}$
25.$ \mathrm{e}\mathrm{n}\mathrm{d}\_\mathrm{i}\mathrm{f} $
在算法3中:步骤1~步骤9是初始化过程,证明方计算尾节点$ {x}_{N}\left[4\right] $将其发送给验证方,并且输出证明方和验证方的初始状态值$ \mathrm{s}{\mathrm{t}}_{\mathrm{i}\mathrm{d}\mathrm{c}} $和$ \mathrm{s}{\mathrm{t}}_{\mathrm{i}\mathrm{d}\mathrm{v}} $;步骤10~步骤14证明方在当前时间$ t $内计算一次性密码$ {x}_{t}\left[4\right] $并发送给验证方;步骤15~步骤25验证方检查证明方提交密码的正确性,并更新状态值。
4.4 性能分析
本文在罗克韦尔Allen-Bradley的PLC上测试了BC-TOTP方案的性能。该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 $越大,则生成尾节点所需的计算时间越长。
由于BC-TOTP采用长链,为减少生成密码所需的加密次数,参考T/Key方案[16],根据证明方使用情况来缓存验证点。如图 5所示,密码生成算法有worst和average两种情况,worst是在整条链上平均分布验证点,average验证点的位置选择是动态变化的。因为网络攻击者可以通过Pycomm读取和改写PLC上的变量值,以致PLC无法调整新的验证点,所以验证点必须预计算保存。图 6给出了在worst情况下SPECK和PRESENT算法的身份验证时间比较结果。
由图 6看出,链上的节点越多,身份验证所需时间越长。本文考虑PLC内存大小,设置200个缓存检查点,并参考T/Key方案的密码使用间隔$ {\Delta }_{\mathrm{I}}=30 $ s,如果$ N=1\mathrm{\;}051\mathrm{\;}200 $,则单链使用周期将近1年。
5 结束语
本文构造基于分组密码的时间基一次性密码方案BC-TOTP,利用PRESENT和SPECK分组密码算法对其进行实例化。通过基于理想密码模型和分组密码IND-CPA的安全假设证明了BC-TOTP方案的安全性,并在罗克韦尔Allen-Bradley PLC上的测试结果验证了BC-TOTP方案的高效性与实用性。后续将使用伪随机生成器链连接多个单链,打破单链密码数量的限制,构造一种全新的时间基一次性密码方案。