BLE-NRF51822教程13-连接时触发配对
最近答疑碰到幾次都提到 需要實現手機每次連接上設備后,立刻出發配對并要求輸入密鑰的功能。 這里就單獨寫一個教程供大家參考下。
?
配對的目的是為了對鏈路進行加密。以提高藍牙的傳輸安全。
關于配對的一些相關知識在 靜態密碼/動態隨機密碼教程中有一些介紹。對于使用來說,理解一下配對相關流程就行了。
?
這里額外說個問道比較多的配對和綁定區別的問題:
關于配對和綁定,一些人可能一直分不清楚他們的區別。配對是為了對提高藍牙鏈路傳輸的安全性。而綁定是配對發起時的一個可選配置。?綁定并不是一個獨立存在的過程。 可以理解成 配對有兩種方式,?沒有設置綁定表示的配對請求和設置綁定標志的配對請求。
?
對于沒有設置綁定標志的配對請求,配對的過程就是
1,鏈路信息的交換,主要就是兩邊設備的i/o能力,是否需要綁定,鏈路是否需要MITM保護,如果設置綁定分配哪些密鑰?等信息。
?
2,然后根據配對信息進行一種鏈路認證(以前的靜態密碼,動態密碼,這個輸入密碼的過程就是認證的一種方式),最后鏈路加密
?
3,最后就是鏈路加密。
?
?
對于設置了綁定位的配對:區別就是多了一個在加密鏈路上分發密鑰的過程。
?
1,鏈路信息的交換,主要就是兩邊設備的i/o能力,設置綁定標志,鏈路是否需要MITM保護,如果設置綁定分配哪些密鑰 等信息。
?
2,然后根據配對信息進行一種鏈路認證(以前的靜態密碼,動態密碼,這個輸入密碼的過程就是認證的一種方式),最后鏈路加密
?
3,進行鏈路加密。
?
4,最后進行主設備和從設備的密鑰分配。
?
?
因為配對的過程比較耗時,每次需要加密鏈路都去執行配對的話就比較麻煩。
所以就有了綁定這個過程,如果設置了綁定,配對后就存儲里一些加密密鑰。下次如果再需要加密鏈路時,就可以使用綁定過程中分發的密鑰了(對于鏈路加密來說,并不是直接使用分發的密鑰而是用分發密鑰生成會話密鑰然后再進行鏈路加密,了解下就行了,對于使用來說,底層細節不需要在意,就算在意你也看不到代碼,如果真想細究直接看藍牙規范)。而不要在執行耗時的配對過程。
?
?
回到這講的主要目的:實現手機每次連接上設備后,立刻出發配對并要求輸入密鑰的功能。
?
靜態密碼教程中提高過,對于配對其實有很多種觸發方式。
靜態密碼和動態隨機密碼教程中 使用的是?對某個特征值設置一個安全權限,當手機訪問它時,因為鏈路并未加密不符合安全要求,于是手機會收到 像是權限不足的錯誤返回,之后手機端就會執行配對請求從而使鏈路加密以符合安全要求。
?
不過對于這里的要求,上面的觸發方式就不符合要求了。因為這里要求的是每次連接后立刻進行配對和密鑰輸入。上面的情況卻是已經連接并發現服務并且執行某些操作后才行的。
?
這就需要其他觸發方式,配對的其他方式還有:
1?主機直接發起配對請求。
2?從機直接發安全請求,這時候如果曾經配對綁定過,那么手機會直接用之前配對綁定時保存的?長期密鑰(LTK)?來進行鏈路的加密工作。如果沒有那么手機就會執行配對過程。
?
對于這里要實現的 每次連接時都要觸發,第一種方式手機端直接發起配對請求,是最直接的。但是這里需要配對和密碼輸入無非是為了提高安全,例如防止別人可以隨便連接的情況。所以肯定不能靠手機端,本身就是為了防止被隨便連,所以肯定是需要在設備這邊做出限制。
?
所以采用第二種方式,即每次手機連接上設備后,設備發送安全請求,因為不使用綁定。所以手機端沒有保存過綁定信息,于是就會發送配對請求,從而啟動配對過程。
?
PS:這樣看似乎手機端直接發配對請求這個功能好像沒什么用。
但是考慮下面的情況,app自動掃描某些設備并連接連接(比如特定的設備名字,或者設備地址等),使用配對并且通過設置配對請求中的i/o能力讓手機端顯示配對碼,而設備端來輸入配對碼。這樣如果其他設備如果偽造設備名,或設備地址,即使連接上了。但是連接后手機端立刻直接發送配對請求,因為”別人”看不到你手機上的配對碼,所以配對也就失敗了,手機端就可以讓其斷開連接。
?
?
?
?
綜上所述,為實現 連接上后 立刻要求配對并輸入配對碼 的功能,我們要添加連接上后 發送 安全請求的代碼,以及判斷配對過程是否成功,如果不成功則斷開連接。 從而實現防止別人隨意連接的目的。所以我們需要做的步驟如下:
?
1:手機連接上后立刻 調用安全請求api??sd_ble_gap_authenticate。
這樣手機收到后就會發送配對請求
?
2:回復手機的配對請求,設置不綁定。(這樣手機每次收到設備的安全請求就會發配對請求過來從而啟動配對)
?
3:之后的配對過程會自動進行。我們只需要根據收到的?BLE_GAP_EVT_AUTH_STATUS? 事件,判斷其狀態是否是成功,來決定配對是不是成功了,從而決定斷不斷開鏈接。
?
?
為了方便我們在靜態密碼的基礎上,添加代碼。從而實現要求功能。這里為了方便沒看過靜態密碼教程的人來理解整體,依舊將靜態密碼需要的相關設置也寫出來。具體的細節看 靜態密碼教程。
?
首先定義一下相關參數
?
#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函數最后添加靜態密碼的設置代碼
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);?
}
?
?
手機發來配對請求后,設備需要回復,實現配對回復函數如下:
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);
}
?
?
?
最后 就是添加上面說的要做的三個步驟的代碼。
?
修改?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連接一建立就發送安全請求,從而促使手機發送配對請求過來
????????? 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回復配對請求
?????????case?BLE_GAP_EVT_SEC_PARAMS_REQUEST:
??????????? printf("receive pair request\n");
? ??????? ?resp_pair_request();
??????????? break;
?
??? ??? //?3判斷配對是否成功,如果不成功斷開連接,從而阻止他人任意連接。
????????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;
??? }
}
總結
以上是生活随笔為你收集整理的BLE-NRF51822教程13-连接时触发配对的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: nRF52832 — 连接指定name、
- 下一篇: nrf51822笔记之密码配对过程梳理