51822配对

配对和绑定区别:
关于配对和绑定,一些人可能一直分不清楚他们的区别。配对是为了对提高蓝牙链路传输的安全性。而绑定是配对发起时的一个可选配置。 绑定并不是一个独立存在的过程。 可以理解成 配对有两种方式, 没有设置绑定表示的配对请求和设置绑定标志的配对请求。


对于没有设置绑定标志的配对请求,配对的过程就是
1,链路信息的交换,主要就是两边设备的i/o能力,是否需要绑定,链路是否需要MITM保护,如果设置绑定分配哪些密钥 等信息。

2,然后根据配对信息进行一种链路认证(以前的静态密码,动态密码,这个输入密码的过程就是认证的一种方式),最后链路加密


3,最后就是链路加密。




对于设置了绑定位的配对:区别就是多了一个在加密链路上分发密钥的过程。


1,链路信息的交换,主要就是两边设备的i/o能力,设置绑定标志,链路是否需要MITM保护,如果设置绑定分配哪些密钥 等信息。


2,然后根据配对信息进行一种链路认证(以前的静态密码,动态密码,这个输入密码的过程就是认证的一种方式),最后链路加密


3,进行链路加密。


4,最后进行主设备和从设备的密钥分配。

静态密码教程中提高过,对于配对其实有很多种触发方式。
静态密码和动态随机密码教程中 使用的是 对某个特征值设置一个安全权限,当手机访问它时,因为链路并未加密不符合安全要求,于是手机会收到 像是权限不足的错误返回,之后手机端就会执行配对请求从而使链路加密以符合安全要求。
不过对于这里的要求,上面的触发方式就不符合要求了。因为这里要求的是每次连接后立刻进行配对和密钥输入。上面的情况却是已经连接并发现服务并且执行某些操作后才行的。
这就需要其他触发方式,配对的其他方式还有:
1主机直接发起配对请求。
2从机直接发安全请求,这时候如果曾经配对绑定过,那么手机会直接用之前配对绑定时保存的 长期密钥(LTK) 来进行链路的加密工作。如果没有那么手机就会执行配对过程。

对于这里要实现的 每次连接时都要触发,第一种方式手机端直接发起配对请求,是最直接的。但是这里需要配对和密码输入无非是为了提高安全,例如防止别人可以随便连接的情况。所以肯定不能靠手机端,本身就是为了防止被随便连,所以肯定是需要在设备这边做出限制。
所以采用第二种方式,即每次手机连接上设备后,设备发送安全请求,因为不使用绑定。所以手机端没有保存过绑定信息,于是就会发送配对请求,从而启动配对过程。
PS:这样看似乎手机端直接发配对请求这个功能好像没什么用。
但是考虑下面的情况,app自动扫描某些设备并连接连接(比如特定的设备名字,或者设备地址等),使用配对并且通过设置配对请求中的i/o能力让手机端显示配对码,而设备端来输入配对码。这样如果其他设备如果伪造设备名,或设备地址,即使连接上了。但是连接后手机端立刻直接发送配对请求,因为”别人”看不到你手机上的配对码,所以配对也就失败了,手机端就可以让其断开连接。
综上所述,为实现 连接上后 立刻要求配对并输入配对码 的功能,我们要添加连接上后 发送 安全请求的代码,以及判断配对过程是否成功,如果不成功则断开连接。 从而实现防止别人随意连接的目的。所以我们需要做的步骤如下:
1:手机连接上后立刻 调用安全请求apisd_ble_gap_authenticate。
这样手机收到后就会发送配对请求
2:回复手机的配对请求,设置不绑定。(这样手机每次收到设备的安全请求就会发配对请求过来从而启动配对)

3:之后的配对过程会自动进行。我们只需要根据收到的 BLE_GAP_EVT_AUTH_STATUS事件,判断其状态是否是成功,来决定配对是不是成功了,从而决定断不断开链接。
为了方便我们在静态密码的基础上,添加代码。从而实现要求功能。这里为了方便没看过静态密码教程的人来理解整体,依旧将静态密码需要的相关设置也写出来。具体的细节看 静态密码教程。
以hrs为例 D:\myfile\test\examples\ble_peripheral\ble_app_hrs
【51822配对】 定义一些参数和变量:
#define SEC_PARAM_BOND0/**< Perform bonding. */
#define SEC_PARAM_MITM1/**< Man In The Middle protection not required. */
#define SEC_PARAM_LESC0/**< LE Secure Connections not enabled. */
#define SEC_PARAM_KEYPRESS0/**< Keypress notifications not enabled. */
#define SEC_PARAM_IO_CAPABILITIESBLE_GAP_IO_CAPS_DISPLAY_ONLY/**< No I/O capabilities. */
#define SEC_PARAM_OOB0/**< Out Of Band data not available. */
#define SEC_PARAM_MIN_KEY_SIZE7/**< Minimum encryption key size. */
#define SEC_PARAM_MAX_KEY_SIZE16/**< Maximum encryption key size. */

#define STATIC_PASSKEY "123456"
static ble_opt_t m_static_pin_option;

static void gap_params_init(void)
{
uint32_terr_code;
ble_gap_conn_params_tgap_conn_params;
ble_gap_conn_sec_mode_t sec_mode;
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
err_code = sd_ble_gap_device_name_set(&sec_mode,
(const uint8_t *)DEVICE_NAME,
strlen(DEVICE_NAME));
APP_ERROR_CHECK(err_code);
err_code = sd_ble_gap_appearance_set(BLE_APPEARANCE_HEART_RATE_SENSOR_HEART_RATE_BELT);
APP_ERROR_CHECK(err_code);
memset(&gap_conn_params, 0, sizeof(gap_conn_params));
gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
gap_conn_params.slave_latency= SLAVE_LATENCY;
gap_conn_params.conn_sup_timeout= CONN_SUP_TIMEOUT;
err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
APP_ERROR_CHECK(err_code);
uint8_t passkey[] = STATIC_PASSKEY;
m_static_pin_option.gap_opt.passkey.p_passkey = passkey;
err_code =sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &m_static_pin_option);
APP_ERROR_CHECK(err_code);

}
static void on_ble_evt(ble_evt_t * p_ble_evt)
{
uint32_terr_code;
switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_CONNECTED:
err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
APP_ERROR_CHECK(err_code);
m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
// 1连接一建立就发送安全请求,从而促使手机发送配对请求过来
ble_gap_sec_params_t params;
memset(¶ms,0,sizeof(params));
params.bond=SEC_PARAM_BOND;
params.io_caps=SEC_PARAM_IO_CAPABILITIES;
params.max_key_size=16;
params.min_key_size=7;
params.oob=SEC_PARAM_OOB;
params.mitm=SEC_PARAM_MITM;
sd_ble_gap_authenticate(m_conn_handle, ¶ms);
break;
case BLE_GAP_EVT_DISCONNECTED:
err_code = bsp_indication_set(BSP_INDICATE_IDLE);
APP_ERROR_CHECK(err_code);
m_conn_handle = BLE_CONN_HANDLE_INVALID;
break;
case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
// 2回复配对请求
printf("receive pair request\n");
resp_pair_request();
break;
case BLE_GAP_EVT_AUTH_STATUS:
// 3判断配对是否成功,如果不成功断开连接,从而阻止他人任意连接。
if(p_ble_evt->evt.gap_evt.params.auth_status.auth_status == BLE_GAP_SEC_STATUS_SUCCESS)
{
printf("pair success\r\n");
}
else
{
sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
}
break;
case BLE_GATTS_EVT_SYS_ATTR_MISSING:
// No system attributes have been stored.
err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
APP_ERROR_CHECK(err_code);
break;
default:
// No implementation needed.
break;
}
}

手机发来配对请求后,设备需要回复,实现配对回复函数如下:
void resp_pair_request(){
ble_gap_sec_params_t sec_params;
uint32_terr_code;


memset(&sec_params,0,sizeof(ble_gap_sec_params_t));


sec_params.bond = BOND;
sec_params.io_caps = IO_CAPS;
sec_params.max_key_size = 16;
sec_params.min_key_size = 7;
sec_params.oob = BOND;
sec_params.mitm = MITM;
err_code=sd_ble_gap_sec_params_reply(m_conn_handle,BLE_GAP_SEC_STATUS_SUCCESS,&sec_params,NULL);
APP_ERROR_CHECK(err_code);
}
以上代码都经过本人验证,但唯一有个缺点是输入密码错误 程序死掉,具体原因不知,需查找改正。



    推荐阅读