NRF51822蓝牙服务(7)——静态密码配对

2023-10-28 15:58

本文主要是介绍NRF51822蓝牙服务(7)——静态密码配对,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

有时候我们希望能够在连接的时候进行密钥的验证,以保障连接的安全。为了保证低功耗蓝牙的绝大多数安全特征,必须完成两个事情。首先是设备必须互相配对;其次,设备必须分配用于加密、保障隐私并对消息进行验证的密钥。这里我们尝试使用静态密码的方式完成蓝牙配对。

实验分析

这里,我们仍然使用前面的串口实验例程。

配对连接过程:

  1. 手机连接上之后立刻调用安全请求API(sd_ble_gap_authenticate),这样手机收到后就会发送配对请求。
  2. 回复手机的配对请求,设置不绑定。这样手机每次收到设备的安全请求就会发送配对请求过去从而启动配对。
  3. 之后的配对过程会自动进行。我们只需要根据收到的BLE_GAP_EVT_AUTH_STATUS事件,判断其状态是否成功,来决定配对是不是成功了,从而决定断不断开连接。

首先,我们先定义静态密码。

#define STATIC_PASSKEY "654321"

注意:官方规定配对密码只能是6位ASCII字符串

#define BLE_GAP_AUTH_KEY_TYPE_PASSKEY     0x01   /**< 6-digit Passkey. *//**@brief Event structure for @ref BLE_GAP_EVT_PASSKEY_DISPLAY. */
typedef struct
{uint8_t passkey[BLE_GAP_PASSKEY_LEN];         /**< 6-digit passkey in ASCII ('0'-'9' digits only). */
} ble_gap_evt_passkey_display_t;

接着定义密码操作结构体。

static ble_opt_t m_static_pin_option;

完成以上操作之后,我们需要设置一下静态密码,设置的操作需要在协议栈初始化之后,所以我们将设置密码操作放在gap_params_init()函数的最后:

{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);
}

然后是设置配对时要交换的信息:

下面定义我们需要交换的信息的宏,也就是和安全参数相关的一些宏。

//不需要绑定
#define SEC_PARAM_BOND     0
//因为要输入密码,就是一种MITM攻击保护,所以这里设置MITM
#define SEC_PARAM_MITM     1

完成这些之后。手机将会发来配对请求,之后设备需要回复,因此需要是实现配对回复函数:

#define SEC_PARAM_MIN_KEY_SIZE 7
#define SEC_PARAM_MAX_KEY_SIZE 16
ble_gap_sec_params_t sec_params;static void resp_pair_request()
{uint32_t err_code;	sec_params.bond = SEC_PARAM_BOND;sec_params.mitm = SEC_PARAM_MITM;sec_params.io_caps = SEC_PARAM_IO_CAPABILITIES;sec_params.oob = SEC_PARAM_OOB;sec_params.min_key_size = SEC_PARAM_MIN_KEY_SIZE;sec_params.max_key_size = SEC_PARAM_MAX_KEY_SIZE;err_code= sd_ble_gap_sec_params_reply(m_conn_handle,BLE_GAP_SEC_STATUS_SUCCESS,&sec_params,NULL);APP_ERROR_CHECK(err_code);
}

最后,就是添加上面说的第三个步骤的代码。

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;//一建立连接就发送安全请求,从而促使手机发送配对请求过来ble_gap_sec_params_t params;params.bond = SEC_PARAM_BOND;params.mitm = SEC_PARAM_MITM;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;case BLE_GAP_EVT_SEC_PARAMS_REQUEST:resp_pair_request();break;case BLE_GAP_EVT_PASSKEY_DISPLAY:break;//判断配对是否成功,如果不成功就断开连接,从而阻止他人任意连接case BLE_GAP_EVT_AUTH_STATUS:if(p_ble_evt->evt.gap_evt.params.auth_status.auth_status == BLE_GAP_SEC_STATUS_SUCCESS){printf("Success!");}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;}
}

到这里,就完成了所有操作。

最后梳理下流程:手机连接设备后,设备会立即发送安全请求。因为手机和设备没有绑定,所以手机收到设备发送过来的安全请求后就会发送配对请求给设备。设备从而回复配对请求且不绑定,设备后续的配对过程由协议栈自动完成,并最终返回给上层配对完成事件。判断配对是否成功,如果失败就断开连接,从而阻止他人随意连接设备。

结果验证

  • 手机连接蓝牙,我们可以发现弹出密码输入窗口
  • 输入“654321”才能完成蓝牙配对
  • 断开蓝牙重连,发现仍然需要重新输入密码

总结

通过这个实验,我们学会了如何使用静态密码连接蓝牙。

这篇关于NRF51822蓝牙服务(7)——静态密码配对的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/294311

相关文章

关于DNS域名解析服务

《关于DNS域名解析服务》:本文主要介绍关于DNS域名解析服务,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录DNS系统的作用及类型DNS使用的协议及端口号DNS系统的分布式数据结构DNS的分布式互联网解析库域名体系结构两种查询方式DNS服务器类型统计构建DNS域

Spring Security中用户名和密码的验证完整流程

《SpringSecurity中用户名和密码的验证完整流程》本文给大家介绍SpringSecurity中用户名和密码的验证完整流程,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定... 首先创建了一个UsernamePasswordAuthenticationTChina编程oken对象,这是S

Linux中SSH服务配置的全面指南

《Linux中SSH服务配置的全面指南》作为网络安全工程师,SSH(SecureShell)服务的安全配置是我们日常工作中不可忽视的重要环节,本文将从基础配置到高级安全加固,全面解析SSH服务的各项参... 目录概述基础配置详解端口与监听设置主机密钥配置认证机制强化禁用密码认证禁止root直接登录实现双因素

java向微信服务号发送消息的完整步骤实例

《java向微信服务号发送消息的完整步骤实例》:本文主要介绍java向微信服务号发送消息的相关资料,包括申请测试号获取appID/appsecret、关注公众号获取openID、配置消息模板及代码... 目录步骤1. 申请测试系统2. 公众号账号信息3. 关注测试号二维码4. 消息模板接口5. Java测试

PostgreSQL数据库密码被遗忘时的操作步骤

《PostgreSQL数据库密码被遗忘时的操作步骤》密码遗忘是常见的用户问题,因此提供一种安全的遗忘密码找回机制是十分必要的,:本文主要介绍PostgreSQL数据库密码被遗忘时的操作步骤的相关资... 目录前言一、背景知识二、Windows环境下的解决步骤1. 找到PostgreSQL安装目录2. 修改p

SpringBoot服务获取Pod当前IP的两种方案

《SpringBoot服务获取Pod当前IP的两种方案》在Kubernetes集群中,SpringBoot服务获取Pod当前IP的方案主要有两种,通过环境变量注入或通过Java代码动态获取网络接口IP... 目录方案一:通过 Kubernetes Downward API 注入环境变量原理步骤方案二:通过

如何搭建并配置HTTPD文件服务及访问权限控制

《如何搭建并配置HTTPD文件服务及访问权限控制》:本文主要介绍如何搭建并配置HTTPD文件服务及访问权限控制的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、安装HTTPD服务二、HTTPD服务目录结构三、配置修改四、服务启动五、基于用户访问权限控制六、

Druid连接池实现自定义数据库密码加解密功能

《Druid连接池实现自定义数据库密码加解密功能》在现代应用开发中,数据安全是至关重要的,本文将介绍如何在​​Druid​​连接池中实现自定义的数据库密码加解密功能,有需要的小伙伴可以参考一下... 目录1. 环境准备2. 密码加密算法的选择3. 自定义 ​​DruidDataSource​​ 的密码解密3

电脑蓝牙连不上怎么办? 5 招教你轻松修复Mac蓝牙连接问题的技巧

《电脑蓝牙连不上怎么办?5招教你轻松修复Mac蓝牙连接问题的技巧》蓝牙连接问题是一些Mac用户经常遇到的常见问题之一,在本文章中,我们将提供一些有用的提示和技巧,帮助您解决可能出现的蓝牙连接问... 蓝牙作为一种流行的无线技术,已经成为我们连接各种设备的重要工具。在 MAC 上,你可以根据自己的需求,轻松地

SpringBoot如何对密码等敏感信息进行脱敏处理

《SpringBoot如何对密码等敏感信息进行脱敏处理》这篇文章主要为大家详细介绍了SpringBoot对密码等敏感信息进行脱敏处理的几个常用方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录​1. 配置文件敏感信息脱敏​​2. 日志脱敏​​3. API响应脱敏​​4. 其他注意事项​​总结