BLE配对与绑定一(原理)
一、基本概念
Paring(配对)和Bonding(绑定)是实现蓝牙射频通信安全的一种机制,它实现的是蓝牙链路层的安全,对应用来说完全透明,也就是说,不管有没有Paring/Bonding,你发送或接收应用数据的方式是一样的,不会因为加了Paring/Bonding应用数据传输需要做某些特殊处理。
流程:
- 配对特征交换得到临时密钥TK;
- 身份确认以及短期密钥STK的产生;
- 传输特定密钥。
加密、配对和绑定区别:
- 加密:确保数据的机密性,机密性即指第三方“监听”或者“攻击者”由于没有加密链路的共享秘密,因此无法拦截、破译或者读取消息的原始内容。注:数据包的报头和长度字段不会被加密,好处是接收到包后可以直接分析报头判断SN的和MESN标志。
- 配对:配对是找到并确定需要和自己通信的设备,也就是身份确定,接着是安全密钥共享,而这一过程仅仅是由启动加密到得到短期秘钥(STK)为止。其包括配对能力交换、设备认证、密钥(固定为128bit)生成、连接加密以及机密信息分发等过程,配对的目的有三个:加密连接、认证设备、以及生成密钥;
- 绑定:配对过程中会生成一个长期密钥(LTK,long-term Key),如果配对双方把这个LTK存储起来放在Flash中,(有的时候是长期密钥、身份解析密钥、连接签名解析密钥这三个密钥的某一个或者组合进行交换,然后将交换的莫要存储到数据库中)。那么这两个设备再次重连的时候,就可以跳过配对流程,而直接使用LTK对蓝牙连接进行加密,设备的这种状态称为绑定(bonding)。
特点:
- 明确为何需要进行配对:加密认证的整个过程几乎都是围绕怎么将两个设备使用到的秘钥能够安全的共享,也就是当一方把密码告诉另一方时,始终要提防第三方也可能听得到这个密钥, 把需要共享的密钥安全的送到正确的设备才是难点,这就引入了配对的复杂过程。
- 这里也需要明确一个概念,配对绑定只有在两个设备之间第一次配对时才会发生,后续的连接由于第一次的配对绑定已有“Bonding”过程(即存储),如果存储的数据库没有被人为的清空,后续的连接不要配对。并不是所有的通信都需要加密进行数据保护,因此:建立连接之前不一定需要配对和绑定,可以直接建立连接。
二、流程
配对流程图
阶段流程:
- 阶段1:配对特征交换得到临时密钥(TK)值 (配对请求、配对响应);
- 阶段2:身份确认以及短期密钥(STK)生成(通过安全管理协议(SMP)配对),确定自己正在和一个真正想要同行的设备通信,而非第三方,即确定对方身份;
- 阶段3:传输特定密钥 (密钥分配)。绑定所需存储到安全数据库的数据也是此阶段发送的。
上述三阶段总结:
- 配对认证:主从机一方提供密码,一方输入密码,如果双方密码一致,那么此密码将作为TK(临时密码);
- 加密链路:利用得到的TK(临时密码)等信息计算出STK(短期密码)用来做加密认证;
- 绑定:加密认证通过后,利用STK等信息生成LTK(长期密码),把LTK保存下来,用于下次连接时做加密认证,不需要再次配对就可以加密链路,这就是绑定了;
绑定后通讯过程 : 每次连接时,从机会向主机发送安全请求,如果主从机相互绑定过,主机不会发送配对请求,主机直接利用绑定时保存的LTK发送加密请求,从机也会利用绑定时保存的LTK来做加密回复,三次握手成功后(加密成功,三次握手通讯由底层完成,用户不可见),从机回复主机加密状态success。
三、总结
上述过程可以这样理解:
建立连接是使用的静态密码,解除绑定/配对是使用的动态密码,因为我们删除静态密码是没有意义的,这是一个已知的。回连也是需要密码的,使用的是动态密码,这是为了防止窃听,起保护作用,但是一般为了防止泄露信息用户也可以自行在应用层去实现相同功能,两者从功能和安全性上没有本质区别。Paring/Bonding是将上述的工程标准化,使用户可以无感的使用安全的蓝牙通信。
配对和绑定区别:
- 连接:通讯的基础,通讯数据为明文;
- 配对:配对仅仅是为了在连接的基础上加密(通讯数据经过加密为密文),提高蓝牙链路传输的安全性。不配对也能连接进行通信。
- 绑定:绑定是配对发起时的一个可选配置。把配对信息记录下来, 下次不用配对自动进入加密的连接;所以没在bonding列表里的设备不影响连接,照连不误。
这里涉及到一个概念,为什么我们日常使用的蓝牙产品很少要求绑定呢?
因为我们在使用绑定时,大部分是由应用层去管理的,如果需要绑定输入密码,首先会被系统层获取到,这就已经不安全了;其次,蓝牙的加密本身是不安全的,第一次连接有概率被监听到(后续的回连被监听的难度较大)
四、基于概念之代码
// Setup the GAP Bond Manager
{
uint32_t passkey = 111222; //设置配对密码,默认为六个0,这里设置为其他密码作为参考
uint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;//可配对绑定连接,这里在协议栈是有其他选项可供修改,具体参见程序备注
uint8_t mitm = 1; //中间人(MITM即第三方设备)在配对算法中是否启用密钥保护,即是否需要防止中间人攻击
uint8_t bonding = 1; //配对过程中是否绑定
uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY; //是否可以配对以及配对是否需要密钥
GAPBondMgr_SetParameter(GAPBOND_PERI_DEFAULT_PASSCODE, sizeof(uint32_t), &passkey);
GAPBondMgr_SetParameter(GAPBOND_PERI_PAIRING_MODE, sizeof(uint8_t), &pairMode);
GAPBondMgr_SetParameter(GAPBOND_PERI_MITM_PROTECTION, sizeof(uint8_t), &mitm);
GAPBondMgr_SetParameter(GAPBOND_PERI_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
GAPBondMgr_SetParameter(GAPBOND_PERI_BONDING_ENABLED, sizeof(uint8_t), &bonding);
}
附: