配对(Pairing)分为三个阶段,前两个阶段是必须的,而第三阶段是可选的,三个阶段如下:
阶段1:配对功能交换(Pairing Feature Exchange)
阶段2(LE传统配对 LE legacy pairing):短期密钥(STK:Short Term Key)生成
阶段2(LE安全连接 LE Secure Connections,也叫LESC):长期密钥(LTK:Long Term Key)生成
阶段3:分发特定密钥的传输(Transport Specific Key Distribution)
可以看到阶段2分为两种:一种是LE传统配对,或者叫做LE遗留配对,它为了兼容低功耗蓝牙以前的配对而存在。另一种是蓝牙4.2新引入的LE安全连接,它安全性会更高。
这三个阶段的流程如下图所示:
上述流程可以很清晰的看出来每个阶段做的事:
阶段1两个设备交换身份验证要求和IO(Input Output输入输出)等能力,随后阶段2会根据这些能力决定使用以下哪种协议生成密钥:
1.Just Works
2.Numeric Comparison (仅在LESC中可用)
3.Passkey Entry
4.Out Of Band (OOB)
从阶段1交换的信息中还会确定是使用LE传统配对还是LESC。 阶段3只有在以下三种情况时才可选:
1.阶段2选择了LE传统配对,生成了STK
2.阶段2选择了LESC,生成了LTK
3.使用BR/EDR配对,生成了共享链路密钥
注意:阶段1和阶段2可以在加密链路上执行,也可以在不加密链路上执行!
配对功能交换流程:
阶段1的配对功能交换主要用于交换以下信息:
1.输入输出能力(IO capabilities)
2.oob认证数据是否可用(OOB authentication data availability)
3.认证要求(authentication requirements)
4.密钥大小要求(key size requirements)
5.要被传输的分发密钥(包括自己和对方的)
其中1、2、3被用作选择阶段2使用哪种密钥生成方法的条件。5则决定了阶段3会分发哪些密钥。选择LE传统配对的密钥生成方法的话,一定会生成两个密钥:TK(Temporary Key,临时密钥)和STK(Short Term Key,短期密钥)。TK用于配对过程中加密,这个过程中会再生成STK。而STK用于配对后的加密连接。
选择LESC的密钥生成方法的话则一定会生成LTK(Long Term Key,长期密钥),用于配对后以及再次连接时加密连接。
实际空中交互的数据包如下:
输入能力被分为三种:
1.No input:没有输入能力
2.Yes/No:有输入是或者否的能力,比如两个按键,一个是“是”,一个是“否”,或者更简单只有一个按键,按下就是“是”,超过一定时间没按下就认为是“否”。
3.Keyboard:设备可以输入数字0~9和确认。还应该有上述Yes/No的能力。
注意:能力3包含了能力2。
输出能力被分为两种:
1.No output:设备没有显示或者交流6位10进制数字的能力
2.Numeric output:设备具有显示或者交流6位10进制数字的能力
根据输入输出组合,IO能力分为以下六种:
注意,因为没有一个算法可以给输入是Yes/No,输出是No output所使用,所以这种类型也是 NoInputNoOutput 。
实际空中交互的数据包中,数值定义如下:
LE传统配对中,两个配对的设备都必须有对方的oob数据,才会选择oob方式。
LESC配对中,两个配对的设备只要其中一个有对方的oob数据,就选择oob方式。
实际空中数据包数值如下:
空中报文包含如下参数:
Bonding_Flags:是否绑定标志
MITM:是否启用中间人保护标志
SC:是否支持安全连接标志
Keypress:是否启用密钥输入标志,只在Passkey Entry协议中有效
CT2:是否支持h7函数标志
每个设备都有两个参数:最大密钥长度和最小密钥长度。它们的范围都在7~16个字节以内。发起设备和响应设备的最大密钥长度中较小的那个作为协商出来的密钥长度。协商得到的密钥长度不能小于自己支持的最小密钥长度,否则应该发送"Encryption Key Size"作为配对失败的错误码。
如果密钥小于16字节,优先屏蔽高位。
有以下密钥可以选择分发:
IRK(Identity Resolving Key)身份解析密钥
用于生成和解析随机地址
CSRK(Connection Signature Resolving Key)连接签名解析密钥
用于在接收设备上对数据签名和验证签名
LTK长期密钥
加密连接的会话密钥
EDIV(Encrypted Diversifier)加密分流器
用于标识LE传统配对中分发的LTK。每当一个新的LTK被分发就会生成一个新的EDIV
Rand随机值
用于标识LE传统配对中分发的LTK。每当一个新的LTK被分发就会生成一个新的Rand值
前面已经说过,阶段1的参数会影响阶段2如何选择密钥生成协议,在LE传统配对中关系如下:
上图总结一下就是:
只有当两个设备的oob flag都置位时,才选择使用oob配对。否则就看MITM置位没有,如果都没有置位,那就选择Just Works,否则就根据IO能力判断使用哪种。根据IO能力判断的方法如下:
从上图可以看出来需要综合发起设备和响应设备的IO能力确定最终选择的协议。
LE传统配对支持3种协议:
Just Works、Passkey Entry、OOB
该过程流程如下:
该方式在配对过程中没有机密性可言,只要存在窃听者或中间人就可能让后续加密失效。选择该方式时,TK固定为0。
该过程流程如下:
对于此方式来说,最少需要一方能输入10进制数字,另一方能显示6位10进制数字,这样可以一方显示,另一方把显示的数字输入进去。或者两方都可以输入数字,此时两方都输入相同的数字。当然最好是两方都既可以显示也可以输入。如果两方都只能显示,在LE传统配对中是不行的。
如果输入的6位10进制数字是 019655 ,则实际TK=0x00000000000000000000000000004Cc7
注意,密钥输入协议提供对MITM攻击的保护,但是0~999999的数字,中间人任选一个,都有0.000001的概率猜对。
该过程流程如下:
oob长度为16位,所以理论上能提供比Passkey Entry更高的安全性。但是前提是带外传输的数据不能被中间人截取,所以安全性完全取决于oob的方式。
oob协议中,TK的值就是oob的那16个字节。
回看LE传统配对的三种方式,可以发现其实三种方式不同的地方仅仅是TK的设置方式!在拿到TK后的流程其实一模一样。在Just Works中TK=0,在Passkey Entry中TK等于输入或显示的6位十进制数字,在OOB中TK是oob数据的那16个字节。而拿到TK的后续流程如下:
发起设备和应答设备分别生成一个128bits的随机数:LP_RAND_I和LP_RAND_R。然后
发起设备计算:
LP_CONFIRM_I = c1(TK,LP_RAND_I,配对请求命令,配对响应命令,发起设备地址类型,发起设备地址,响应设备地址类型,响应设备地址)
响应设备计算:
LP_CONFIRM_R = c1(TK,LP_RAND_R,配对请求命令,配对响应命令,发起设备地址类型,发起设备地址,响应设备地址类型,响应设备地址)
交互流程如下:
发起设备--> LP_CONFIRM_I -->响应设备
发起设备<-- LP_CONFIRM_R <--响应设备
发起设备--> LP_RAND_I -->响应设备
响应设备获取到了LP_CONFIRM_I和LP_RAND_I,通过c1函数计算是否正确,如果正确再进行下一步,否则结束(错误码"Confirm Value Failed")
发起设备<-- LP_RAND_R <--响应设备
发起设备获取到了LP_CONFIRM_R和LP_RAND_R,也通过c1函数计算是否正确,如果正确再进行下一步,否则结束
如果上面的步骤都没问题,两个设备就会生成STK:
该密钥遵循之前对密钥大小的要求。
和LE传统配对不同,它选择密钥生成方式的方法如下:
可以看到最明显的区别是,只要任意一方有oob,就可以使用oob。
LE安全配对的第一步是交换公钥。两个设备都先选择一个随机数作为私钥SKa、SKb,然后用算法生成对应的公钥PKa、PKb。然后发起设备和响应设备交换公钥,然后各自用自己的私钥和对方的公钥生成密钥DHKey,注意两边生成的DHKey相等。如下图所示:
这一步假如有人中间截获了PKa和PKb,无法求出DHKey。
Just Work的关联模型和Numeric Comparison(数字比较)共用一个。整体流程如下:
首先在第一步两边交换了公钥,所以设备A和设备B都有PKb和PKa了,然后两个设备都再各自选择一个随机数分别是Na和Nb。响应设备通过函数f4以及参数PKb、PKa、Nb计算出Cb,然后把Cb发给设备A,然后两个设备再交换Na、Nb。同时设备A检查Cb是否正确,如果不正确,则配对终止,否则设备A计算Va,并显示在显示屏上。与此同时,设备B在发送完Nb后就可以计算Vb并显示了,这时候就需要人参与了,如果两个设备上显示的数字相同,则在两个设备上点击确认,继续下面的流程。Just Works因为没有显示,所以不会执行7a、7b,也没有Va,Vb需要显示,自然也不需要人参与判断是否继续配对。
假如存在中间人拦截并篡改数据,有0.999999的概率导致配对双方显示不同数字,从而配对失败。
其实看得懂上一节的图,这一节的图大同小异。首先人参与输入数字,在设备A和B上分别输入相同的数字,或者一方显示,另一方输入,两个设备得到两个相等的数字ra=rb。然后实现以下过程:
//因为ra/rb最大为999999,20位,所以每次取一位需要取20次
for(int i=0;i<20;++i)
{
/*设备A上实现:*/
//每次循环都会重新生成Na/Nb
Na = rand();
//每次计算取ra/rb的一位参与计算
Ca = f4(PKa,PKb,Na,ra&(1<
每次生成的Ca和Cb都会互相发送给对方,让对方检查,如果失败就直接退出配对。
上图流程为:
设备A和设备B分别选择一个随机数ra和rb,然后用函数f4计算出Ca和Cb。通过带外的方式(比如串口)交换两个设备的地址A、B和ra、rb、Ca、Cb。双方拿到对方的数据后检测,如果成功,再各自选取一个随机数Na、Nb交换。
外围设备(Peripheral)和中心设备(Central)可以选择相互分发:
1.LTK、EDIV、Rand
2.IRK
3.CSRK
分发密钥前,会使用上个阶段生成的STK加密连接。分发完成后可以选择使用新分发的LTK、EDIV、Rand加密连接,不过如果STK是不安全的,那分发的信息可能也已经被破解,那用它们加密也是不安全的。
分发顺序:
1.外围设备的LTK
2.外围设备的EDIV和Rand
3.外围设备的IRK
4.外围设备的BD_ADDR
5.外围设备的CSRK
6.中心设备的LTK
7.中心设备的EDIV和Rand
8.中心设备的IRK
9.中心设备的BD_ADDR
10.中心设备的CSRK
该过程完整流程如下:
外围设备(Peripheral)和中心设备(Central)可以选择相互分发:
1.IRK
2.CSRK
分发密钥前,会使用上个阶段生成的LTK加密连接。
分发顺序:
1.外围设备的LTK
2.外围设备的BD_ADDR
3.外围设备的CSRK
4.中心设备的LTK
5.中心设备的BD_ADDR
6.中心设备的CSRK
流程略,和LE传统配对差不多,省略了一些步骤而已。
通过以下算法计算签名:
算法来自: 签名算法
其中K是CSRK,Tlen是计算结果MAC的长度(64bits),而M是要签名的数据m,拼接上签名计数器(SignCounter)的值。比如要签名的数据m是0x3456789ABCDEF1,签名计数器的值是0x040850F2,则M为:
0x3456789ABCDEF1F2500804
签名计数器是一个32bit的数字,初始为0,每签名一条消息,计数器+1。如果每天生成10W个签名event,大约117年后会溢出。
签名为了比较MAC和SignCounter,以验证消息是否正确,且没有遭受重放攻击。
此章节完全基于个人思考,所以全是白话,没什么专业术语。水平有限,仅供参考。
首先明确一点,为什么需要配对?
很简单:为了安全。假设A和B通信,通信内容是A的银行卡账号密码,A肯定不想让其他人知道,但是需要让B知道,要实现这一点需要加密。比如举一个简单的例子,A想要发给B一串数字123,但是为了让别人不知道,A把123*10=1230发给B,并且和B约定:发给B的所有数据都除以10得到原始数据。这就是一个简单的加密,但是这里有个问题。
假如A要和B、C、D、E、F、G通信,那它需要把加密方式,这里也就是【*10】告诉所有需要和他通信的人,这会导致A和C之间的秘密,B截获后也可以知道具体内容。于是A想了一个办法,和每个人通信的时候选择乘以不同的数字,比如和B通信乘以10,和C通信乘以67。也就是算法:乘法,是公开的,而每个人乘以的数字:密钥,是不公开的。
这里就又有两个问题,首先这个算法太简单了,C就算不知道B是乘以几,但是根据报文变化,一个个去试都能很快破解。其次,A和不同的人通信,乘以的数字总该有个范围,如果范围只是0~99,那不但很容易就试出来,而且假如有第101个人要和它通信那不是没办法了?
密码学届的前辈们想出来很多复杂的算法,让破解变得困难,也就是你就算知道算法和加密结果,只要不知道密钥,你靠一个个去试可能以目前的电脑算力,最坏情况需要几亿年才能试出来,那我们认为这种情况下是不可能被暴力破解的,因为即使破解出来了也没了意义,这就解决了问题1。另外,在每次加密的时候,密钥不是一个固定的数字,它永远在一个范围内随机,这次用完了,下次再通信就换一个新的密钥,那就可以解决问题2。
但是这又引出了一个新的问题,A和B每次都用新的密钥加密太麻烦了,那我们可以改成只在第一次通信的时候选用随机密钥,一旦已经处于加密,我们后续选择一个固定的密钥,下次重连就用这个固定的密钥。但是这并不能解决第一次通信时,怎么让A和B都用同一个密钥,也就是为了安全性,我们用K加密一段文字,就必须用K去解密,那A怎么告诉B,密钥是K呢?
最简单的方法是,A直接发送给B。但是很容易想到,假如A发给B密钥的时候,C在一旁窃听,那后续A和B之间的密文对于C来说形同虚设。但是假如C的窃听是从发完密钥后才开始的,那C是无法猜到密钥K的,也就无从破解。在LE传统配对中的Just Works就是如此,在这种情况下,A和B之间的密钥STK是由TK、LP_RAND_I、LP_RAND_R生成的,生成密钥用的加密算法c1是公开的。TK在这种情况下是0,而LP_RAND_I和LP_RAND_R正是A发给B和B发给A的,也就是如果此时有C在一旁窃听,它可以轻松拿到这三个数字,也用加密算法求出来STK,同时假如它错过了一开始传输LP_RAND_I和LP_RAND_R的阶段,那它后续就算窃听了也没办法破解了。
为了解决C的窃听问题,蓝牙还有Passkey Entry和OOB。首先Passkey的方案是TK不再等于0,而是用户输入的6位十进制数字,而TK不会出现在空中报文里,所以C就算窃听了A和B的通信,也没有办法算的STK,当然它有两种破解方法:
1.监视A或者B的键盘输入,拿到TK
2.暴力破解(试错)
第一种破解方法和蓝牙就无关了,纯粹的是取决于设备对输入或者显示内容的保护。第二种方法对于每次都输入或者显示一样的6位10进制是很有效的,因为很快就能尝试出来。但是假如每次显示的6位10进制数字都是随机的,那么相当于每次都只有百万分之一(0~999999)的概率猜到密钥。而且一旦猜错后续在这个加密基础上再传输其他密钥就不会被破解,使用新密钥加密就可以保证后续无从猜测,也就是C必须在第一次连接的时候一次猜对。如果后续没有新密钥,而是一直用的STK,那窃听者又有机会去暴力破解了。
而OOB提供的理论上比Passkey Entry更高的安全性,因为在上面TK的范围是0~999999(20bit),而OOB的TK是一个16字节的数组,也就是128bit,想要暴力破解这个明显会更难。
以上都是讲的LE传统配对,那LE安全连接为什么安全性会更高?
LE安全连接配对的第一步是交换公钥,A和B都先生成一个随机数SKA和SKB作为各自的私钥,然后用算法根据私钥生成一个公钥PKA和PKB,最后交换PKA和PKB,再使用各自的私钥和对方的公钥生成DHKey,生成公私钥对的算法和生成DHKey的算法可以保证:
A用自己的SKA和对方的PKB生成的DHKey和B用自己的SKB和对方的PKA生成的DHKey相等。
这就解决了一个大问题,C就算从头开始窃听,拿到了PKA和PKB,它也没办法生成DHKey。 因为DHKey必须要一个其中一个私钥和另一个的公钥,只有两个公钥是没办法的。而后续的LTK的生成其中一个参数就是DHKey,没有它是无法计算出LTK,后续的加密链接也就无从破解。
但是还是存在一个问题,假如攻击者有两台设备C和D,它用C和A建立连接,用D和B建立接连,让A和B以为在相互通信,其实是用C和D做转发,而且只需要和A、B通信时把公钥替换成自己的就可以完全骗取对方使用自己的私钥和攻击者的公钥生成的DHKey。
值 | 名称 | 描述 |
0x01 |
Passkey Entry Failed
|
Passkey中用户输入失败,例如用户取消了输入 |
0x02 |
OOB Not Available
|
OOB数据不可用 |
0x03 |
Authentication Requirements
|
由于一个或两个设备的IO能力不满足身份认证要求,因此无法执行配对流程 |
0x04 |
Confirm Value Failed
|
确认值与计算出来的不匹配 |
0x05 |
Pairing Not Supported
|
设备不支持配对 |
0x06 |
Encryption Key Size
|
协商得到的密钥大小不足以满足该设备安全要求 |
0x07 |
Command Not Supported
|
此设备不支持收到的SMP命令 |
0x08 |
Unspecified Reason
|
未定义原因导致配对失败 |
0x09 |
Repeated Attempts
|
不允许配对或身份认证流程,因为距上次配对或安全请求时间过短 |
0x0A |
Invalid Parameters
|
命令长度无效或参数超出指定范围 |
0x0B |
DHKey Check Failed
|
从远端接收到的DHKey与本地计算不符 |
0x0C |
Numeric Comparison Failed
|
数字比较协议中确认值不匹配 |
0x0D |
BR/EDR pairing in progress
|
由于正在通过BR/EDR发送配对请求,LE上的配对失败 |
0x0E |
Cross-transport Key Derivation/Generation not allowed
|
BR/EDR上生成的Link Key不能派生或分发LE上的密钥,或是LE上的LE LTK不能派生BR/EDR上的密钥 |
0x0F |
Key Rejected
|
设备不接受分发密钥 |
其他 | 保留 |
低功耗蓝牙配对绑定解读和实践
【精选】BLE安全之SM剖析(2)_ble just work_物联网布道师的博客-CSDN博客
BLE安全机制从入门到放弃 | Jayden's Blog