BLE-NRF51822教程13-连接时触发配对
最近答疑碰到幾次都提到 需要實(shí)現(xiàn)手機(jī)每次連接上設(shè)備后,立刻出發(fā)配對(duì)并要求輸入密鑰的功能。 這里就單獨(dú)寫一個(gè)教程供大家參考下。
?
配對(duì)的目的是為了對(duì)鏈路進(jìn)行加密。以提高藍(lán)牙的傳輸安全。
關(guān)于配對(duì)的一些相關(guān)知識(shí)在 靜態(tài)密碼/動(dòng)態(tài)隨機(jī)密碼教程中有一些介紹。對(duì)于使用來說,理解一下配對(duì)相關(guān)流程就行了。
?
這里額外說個(gè)問道比較多的配對(duì)和綁定區(qū)別的問題:
關(guān)于配對(duì)和綁定,一些人可能一直分不清楚他們的區(qū)別。配對(duì)是為了對(duì)提高藍(lán)牙鏈路傳輸?shù)陌踩?/strong>。而綁定是配對(duì)發(fā)起時(shí)的一個(gè)可選配置。?綁定并不是一個(gè)獨(dú)立存在的過程。 可以理解成 配對(duì)有兩種方式,?沒有設(shè)置綁定表示的配對(duì)請(qǐng)求和設(shè)置綁定標(biāo)志的配對(duì)請(qǐng)求。
?
對(duì)于沒有設(shè)置綁定標(biāo)志的配對(duì)請(qǐng)求,配對(duì)的過程就是
1,鏈路信息的交換,主要就是兩邊設(shè)備的i/o能力,是否需要綁定,鏈路是否需要MITM保護(hù),如果設(shè)置綁定分配哪些密鑰?等信息。
?
2,然后根據(jù)配對(duì)信息進(jìn)行一種鏈路認(rèn)證(以前的靜態(tài)密碼,動(dòng)態(tài)密碼,這個(gè)輸入密碼的過程就是認(rèn)證的一種方式),最后鏈路加密
?
3,最后就是鏈路加密。
?
?
對(duì)于設(shè)置了綁定位的配對(duì):區(qū)別就是多了一個(gè)在加密鏈路上分發(fā)密鑰的過程。
?
1,鏈路信息的交換,主要就是兩邊設(shè)備的i/o能力,設(shè)置綁定標(biāo)志,鏈路是否需要MITM保護(hù),如果設(shè)置綁定分配哪些密鑰 等信息。
?
2,然后根據(jù)配對(duì)信息進(jìn)行一種鏈路認(rèn)證(以前的靜態(tài)密碼,動(dòng)態(tài)密碼,這個(gè)輸入密碼的過程就是認(rèn)證的一種方式),最后鏈路加密
?
3,進(jìn)行鏈路加密。
?
4,最后進(jìn)行主設(shè)備和從設(shè)備的密鑰分配。
?
?
因?yàn)榕鋵?duì)的過程比較耗時(shí),每次需要加密鏈路都去執(zhí)行配對(duì)的話就比較麻煩。
所以就有了綁定這個(gè)過程,如果設(shè)置了綁定,配對(duì)后就存儲(chǔ)里一些加密密鑰。下次如果再需要加密鏈路時(shí),就可以使用綁定過程中分發(fā)的密鑰了(對(duì)于鏈路加密來說,并不是直接使用分發(fā)的密鑰而是用分發(fā)密鑰生成會(huì)話密鑰然后再進(jìn)行鏈路加密,了解下就行了,對(duì)于使用來說,底層細(xì)節(jié)不需要在意,就算在意你也看不到代碼,如果真想細(xì)究直接看藍(lán)牙規(guī)范)。而不要在執(zhí)行耗時(shí)的配對(duì)過程。
?
?
回到這講的主要目的:實(shí)現(xiàn)手機(jī)每次連接上設(shè)備后,立刻出發(fā)配對(duì)并要求輸入密鑰的功能。
?
靜態(tài)密碼教程中提高過,對(duì)于配對(duì)其實(shí)有很多種觸發(fā)方式。
靜態(tài)密碼和動(dòng)態(tài)隨機(jī)密碼教程中 使用的是?對(duì)某個(gè)特征值設(shè)置一個(gè)安全權(quán)限,當(dāng)手機(jī)訪問它時(shí),因?yàn)殒溌凡⑽醇用懿环习踩?#xff0c;于是手機(jī)會(huì)收到 像是權(quán)限不足的錯(cuò)誤返回,之后手機(jī)端就會(huì)執(zhí)行配對(duì)請(qǐng)求從而使鏈路加密以符合安全要求。
?
不過對(duì)于這里的要求,上面的觸發(fā)方式就不符合要求了。因?yàn)檫@里要求的是每次連接后立刻進(jìn)行配對(duì)和密鑰輸入。上面的情況卻是已經(jīng)連接并發(fā)現(xiàn)服務(wù)并且執(zhí)行某些操作后才行的。
?
這就需要其他觸發(fā)方式,配對(duì)的其他方式還有:
1?主機(jī)直接發(fā)起配對(duì)請(qǐng)求。
2?從機(jī)直接發(fā)安全請(qǐng)求,這時(shí)候如果曾經(jīng)配對(duì)綁定過,那么手機(jī)會(huì)直接用之前配對(duì)綁定時(shí)保存的?長(zhǎng)期密鑰(LTK)?來進(jìn)行鏈路的加密工作。如果沒有那么手機(jī)就會(huì)執(zhí)行配對(duì)過程。
?
對(duì)于這里要實(shí)現(xiàn)的 每次連接時(shí)都要觸發(fā),第一種方式手機(jī)端直接發(fā)起配對(duì)請(qǐng)求,是最直接的。但是這里需要配對(duì)和密碼輸入無非是為了提高安全,例如防止別人可以隨便連接的情況。所以肯定不能靠手機(jī)端,本身就是為了防止被隨便連,所以肯定是需要在設(shè)備這邊做出限制。
?
所以采用第二種方式,即每次手機(jī)連接上設(shè)備后,設(shè)備發(fā)送安全請(qǐng)求,因?yàn)椴皇褂媒壎ā?strong>所以手機(jī)端沒有保存過綁定信息,于是就會(huì)發(fā)送配對(duì)請(qǐng)求,從而啟動(dòng)配對(duì)過程。
?
PS:這樣看似乎手機(jī)端直接發(fā)配對(duì)請(qǐng)求這個(gè)功能好像沒什么用。
但是考慮下面的情況,app自動(dòng)掃描某些設(shè)備并連接連接(比如特定的設(shè)備名字,或者設(shè)備地址等),使用配對(duì)并且通過設(shè)置配對(duì)請(qǐng)求中的i/o能力讓手機(jī)端顯示配對(duì)碼,而設(shè)備端來輸入配對(duì)碼。這樣如果其他設(shè)備如果偽造設(shè)備名,或設(shè)備地址,即使連接上了。但是連接后手機(jī)端立刻直接發(fā)送配對(duì)請(qǐng)求,因?yàn)椤眲e人”看不到你手機(jī)上的配對(duì)碼,所以配對(duì)也就失敗了,手機(jī)端就可以讓其斷開連接。
?
?
?
?
綜上所述,為實(shí)現(xiàn) 連接上后 立刻要求配對(duì)并輸入配對(duì)碼 的功能,我們要添加連接上后 發(fā)送 安全請(qǐng)求的代碼,以及判斷配對(duì)過程是否成功,如果不成功則斷開連接。 從而實(shí)現(xiàn)防止別人隨意連接的目的。所以我們需要做的步驟如下:
?
1:手機(jī)連接上后立刻 調(diào)用安全請(qǐng)求api??sd_ble_gap_authenticate。
這樣手機(jī)收到后就會(huì)發(fā)送配對(duì)請(qǐng)求
?
2:回復(fù)手機(jī)的配對(duì)請(qǐng)求,設(shè)置不綁定。(這樣手機(jī)每次收到設(shè)備的安全請(qǐng)求就會(huì)發(fā)配對(duì)請(qǐng)求過來從而啟動(dòng)配對(duì))
?
3:之后的配對(duì)過程會(huì)自動(dòng)進(jìn)行。我們只需要根據(jù)收到的?BLE_GAP_EVT_AUTH_STATUS? 事件,判斷其狀態(tài)是否是成功,來決定配對(duì)是不是成功了,從而決定斷不斷開鏈接。
?
?
為了方便我們?cè)陟o態(tài)密碼的基礎(chǔ)上,添加代碼。從而實(shí)現(xiàn)要求功能。這里為了方便沒看過靜態(tài)密碼教程的人來理解整體,依舊將靜態(tài)密碼需要的相關(guān)設(shè)置也寫出來。具體的細(xì)節(jié)看 靜態(tài)密碼教程。
?
首先定義一下相關(guān)參數(shù)
?
#define STATIC_PASSKEY "123456"
static ble_opt_t? m_static_pin_option;
?
#define IO_CAPS????? BLE_GAP_IO_CAPS_DISPLAY_ONLY? //只有顯示裝置
#define BOND???????? 0?????????????????????????????? //不綁定
#define OOB????????? 0??????????????????????????
#define MITM???????? 1
?
在gap_params_init函數(shù)最后添加靜態(tài)密碼的設(shè)置代碼
static void?gap_params_init(void)
{
??? uint32_t? ? ? ? ? ? err_code;
??? ble_gap_conn_params_t?? gap_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);
?
??? 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);?
}
?
?
手機(jī)發(fā)來配對(duì)請(qǐng)求后,設(shè)備需要回復(fù),實(shí)現(xiàn)配對(duì)回復(fù)函數(shù)如下:
void?resp_pair_request(){
??? ble_gap_sec_params_t sec_params;
??? uint32_t??????????????????? err_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);
}
?
?
?
最后 就是添加上面說的要做的三個(gè)步驟的代碼。
?
修改?main.c中on_ble_evt,添加紅色代碼部分
static void?on_ble_evt(ble_evt_t * p_ble_evt)
{
??? uint32_t???????????????????????? err_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連接一建立就發(fā)送安全請(qǐng)求,從而促使手機(jī)發(fā)送配對(duì)請(qǐng)求過來
????????? ble_gap_sec_params_t params;
???????? params.bond = 0;
???????? params.mitm = 1;
????????
?????????sd_ble_gap_authenticate(m_conn_handle, params);
??????????? 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;
?????????? //?2回復(fù)配對(duì)請(qǐng)求
?????????case?BLE_GAP_EVT_SEC_PARAMS_REQUEST:
??????????? printf("receive pair request\n");
? ??????? ?resp_pair_request();
??????????? break;
?
??? ??? //?3判斷配對(duì)是否成功,如果不成功斷開連接,從而阻止他人任意連接。
????????case?BLE_GAP_EVT_AUTH_STATUS:
???????? ?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);
???????? ?}
?
??????? 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;
??? }
}
總結(jié)
以上是生活随笔為你收集整理的BLE-NRF51822教程13-连接时触发配对的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: nRF52832 — 连接指定name、
- 下一篇: nrf51822笔记之密码配对过程梳理