一、数值匹配-配对流程
低功耗安全连接是在蓝牙4.2版本中引入的经强化的安全功能。它采用符合联邦信息处理标准(FIPS)的椭圆曲线Diffie-Hellman(ECDH)算法来生成密钥。低功耗安全连接支持四种关联模型:Just Works、Numeric Comparison(数值比较)、Passkey Entry和Out-of-Band, 简称OOB。本组主要分析研究的是其中数值比较这一种关联模型,该模型适用于两个设备都能够显示一个六位数来确认Key是否一致,选择配对/取消,并且都能够让用户输入“yes”或“no”。该模式向用户提供了正确的设备彼此连接的确认,提供了针对MITM攻击的保护。
接下来介绍配对流程:
第1阶段-配对特性交换
表1是配对请求/响应分组定义。在“AuthReq”字段中,有一个名为“SC”的位。如果设备支持低功耗安全连接配对,则SC字段应设置为1,否则设置为0.如果两个设备都支持低功耗安全连接配对,则应使用低功耗安全连接配对,否则使用低功耗传统配对。因此,如果两个设备要通过低功耗安全连接配对,则必须将“SC”设置为1,以告知对等设备“我具备安全连接的能力“。
表格 1 配对请求/响应分组
第2阶段-密钥生成方法选择 完成配对特征交换之后,发起设备和响应设备应确定使用何种密钥生成方法。表2列出了数值比较发起设备和响应设备的I/O功能。当发起设备和响应设备都具有显示屏和“是/否”的I/O功能、或显示屏和键盘I/O功能时,则使用数值比较关联模型。
表格 2
第2阶段-身份验证
密钥生成后,配对将进入阶段2,即身份认证阶段,目的是保护连接不受中间人攻击(Man-In-The-Middle, MITM),同时生成即将用于加密连接链路的密钥。
在公钥交换中,每个设备生成自己的椭圆曲线Diffie-Hellman(ECDH)公私密钥对,其中包含私钥和公钥。各阶段使用参数定义如下:
符号 | 含义 |
---|---|
SKa | 发起设备的私钥 |
PKa | 发起设备的公钥 |
SKb | 响应设备的私钥 |
PKb | 响应设备的公钥 |
f4() | 用于在配对过程中生成确认值 |
g2() | 用于在身份认证阶段生成六位数字码 |
如上图所示,交换公钥后,每个设备随机选择128位n次(步骤2)。该值用于减轻重放攻击,并应在配对协议的每个实例化中最新生成。这个值应该直接从随机性的物理源生成,或者使用从物理源播种的随机值的良好的伪随机生成器生成。然后,响应设备计算对已交换的两个公钥及其自己的一次性值(步骤3c)。该承诺作为这些值的单向函数被计算,并被传输到启动装置(步骤4)。该承诺可防止攻击者在以后的时间内更改这些值。然后,启动和响应设备交换它们各自的nonce值(步骤5和6),并且启动设备确认承诺(步骤6a)。此时的故障表示存在攻击者或其他传输错误,并导致协议中止。该协议可以重复生成或不生成新的公钥-私钥对,但如果重复该协议,则必须生成新的无效协议。当使用数字比较时,假设承诺检查成功,这两个设备分别计算在各自设备上显示给用户的6位确认值(步骤7a、7b和8)。用户需要检查这些6位值是否匹配,并确认是否存在匹配。如果没有匹配,协议将中止,
第3阶段-绑定阶段
验证成功后,两个设备会开始计算将用于链路加密的LTK并保存,在此不做赘述。 3. 协议的Π演算描述
二、利用Π演算描述协议过程方法
(*申明一个公开信道一个私密信道*)
free c:channel.
free cs:channel [private].
(*申明公钥和私钥两种类型*)
type pkey.
type skey.
(*拿到私钥可对应生成公钥的函数*)
fun pk(skey):pkey.
(*定义加密函数*)
fun senc(U,pkey,X,Z):bitstring.
(*定义A进程,将按顺序执行*)
let DeviceA(pkA:pkey,skA:skey) =
out(c,pkA); (*将A的公钥通过公开信道传出*)
in(c,pkXb:pkey); (*从公开信道拿到B的公钥*)
new Na:bitstring; (*定义一个随机数Na*)
in(c,Cb:bitstring); (*从公开信道拿到B生成的Cb*)
out(c,Na); (*将A的Na通过公开信道传出*)
in(c,NXb); (*通过公开信道拿到B的公钥*)
if Cb=senc(pkXb,pkA,NXb,0) then
(*如果Cb与A计算值一致则认为不存在中间人攻击*)
let Va = senc(pkA,pkXb,Na,NXb) in out(cs,Va)
(*生成6位验证码,用户可确认Va和Vb是否一致*)
else false
(*定义B进程,按顺序执行*)
let DeviceB(pkB:pkey,skB:skey) =
in(c,pkXa:pkey); (*从公开信道拿到A的公钥*)
out(c,pkB); (*将B的公钥通过公开信道传出*)
new Nb:bitstring. (*生成B的随机数Nb*)
out(c,senc(pkB,pkXa,Nb,0));
(*通过单向加密算法生成Cb传给A*)
in(c,NXa:bitstring); (*从公开信道拿到A的Na*)
out(c,Nb); (*将自己的Nb通过公开信到传出*)
let Vb = senc(pkXa,pkB,NXa,Nb); (*计算Vb即验证码*)
in(cs,VXa:); (*用户可确认Va和Vb是否一致*)
if VXa=Vb then 0 else fail. (*用户可确认Va和Vb是否一致*)
(*主进程*)
process
new skA:skey; (*A的私钥*)
new skB:skey; (*B的私钥*)
let pkA = pk(skA) in out(c,pkA);
(*生成A的公钥并通过公开信道发出*)
let pkB = pk(skB) in out(c,pkB);
(*生成B的公钥并通过公开信道发出*)
((!DeviceA(pkA,skA)) | (!DeviceB(pkB,skB)))
(*A和B之间的身份配对可以无限进行也可多个之间进行*)
具体的关于Proverif可以参考此链接