这一讲介绍配对的一些相关理论知识,并且介绍如何实现”静态密码”的设定

程序是基于sdk9.0 下的 uart demo

另外 测试使用的手机app是 iOS下的lightblue。

这里准确的说法应该是叫配对码,而不是密码。输入这个这个配对码是配对过程中可选的一部分

介绍如何设置静态密码前先介绍一下配对的相关知识(后面都直接叫密码,而不是配对码)

起初未提供安全性的两个设备如果希望做一些需要安全性的工作,就必须先配对。配对涉及两个设备的身份认证,链路加密。如果配对时设置了绑定位,随后还会有一个秘钥分配。分配的秘钥用户可以存储在flash中这样两个设备再第二次重连时的安全启动会更快。而不需要像第一次一样需要再启动整个配对过程。

配对的第一个过程首先是配对信息的交换,这些信息用于确定认证方式,以及后续是否需要分配密钥以及分配哪些密钥。

交换的信息包括:

两端设备的输入输出能力如:是否有显示屏,键盘等。

是否需要绑定(如果设置了绑定位配对的)。

是否需要MITM,是否使用OOB等

这些信息会让BLE协议栈确定一种认证方式:

比如:

1:如果两端设备的输入输出能力有限,比如都没有键盘和显示器,认证方式就是just work,这其实就是没有认证,

2:如果两端设备一个有显示频,而另一个有键盘,而配对中设置了MITM保护。那么认证方式就是passkey entery。
      一端会显示一个配对码,另一需要输入这个配对码。之后的配对才能正确进行下去。

3:如果设置了OOB,那么这个配对码就是通过另外的通信方式(如NFC)来发送的,而不是像上面一样一端显示一端输入。

这一讲的密码设置就是第二种情况。显示的密码是可以随机的也可以是静态的。由于设备并没有显示器。但是我们仍然可以设置输入输出能力为有显示器,因为我们使用的是静态密码。

配对的过程不仅只是输入配对码这样,后续还会根据输入的配对码,以及两端设备交换的随机数来生成链路密钥来加密链路以及分配后续的长期密钥,身份解析密钥等需要的密钥

配对相关的理论比较多,上面的描述只是一个大概的过程。配对过程的详细介绍在蓝牙规范的 安全 章节中。

根据上面的理论描述,我们来总结一下:

我们需要的输入“密码”这个功能,其实是配对过程中的一部分。而配对过程又是需要首先交换配对信息,然后协议栈会根据交换的信息才决定是否有输入密码这一过程。

那么我们要做的有如下几步:

1: 首先设置要输入的静态密码
  2: 设置配对时会交换的信息:根据上面的介绍如果我们需要手机输入密码,那么配对时就要设置只具有显示器(这样就会是一端显示,一端输入,虽然我们真的没显示器,但是设置的是静态密码所以也是可以的),设置需要MITM攻击保护。

3:触发配对。

下面先介绍如何设置静态密码:

//首先定义一下静态密码,配对密码只能是 6-digit ASCII string

#define STATIC_PASSKEY        "123456"       /**< Static pin. */

//改结构体中可以设置静态密码

static ble_opt_t   m_static_pin_option;

定义了这两个参数后,我们需要设置一下静态密码,设置的操作需要在协议栈初始化之后 所以我们将设置密码操作放在    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,

(constuint8_t*DEVICE_NAME,trlen(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_IO_CAPABILITIES      BLE_GAP_IO_CAPS_DISPLAY_ONLY

//不使用带外数据

#define SEC_PARAM_OOB                 0

//链路加密密钥的长度

#define SEC_PARAM_MIN_KEY_SIZE           7

#define SEC_PARAM_MAX_KEY_SIZE           16

定义了宏之后我们需要在设置参数,写一个如下的函数。

m_sec_params 是一个全局变量

ble_gap_sec_params_t m_sec_params;

static void sec_params_init(void)

{

m_sec_params.bond         = SEC_PARAM_BOND;

m_sec_params.mitm         = SEC_PARAM_MITM;

m_sec_params.io_caps      = SEC_PARAM_IO_CAPABILITIES;

m_sec_params.oob          = SEC_PARAM_OOB;

m_sec_params.min_key_size = SEC_PARAM_MIN_KEY_SIZE;

m_sec_params.max_key_size = SEC_PARAM_MAX_KEY_SIZE;

}

将该函数放在 main函数的初始化流程中的conn_params_init(); 函数之后。

设置的这个全局变量会在配对启动后的信息交换中使用(因为其内部值就是要交换的信息)。

到这里我们设置完了配对启动后会交换的信息。但是怎么把这个信息给对端设备呢? 先看完最后一步的触发配对的问题,再来解决将配对信息发给对端设备的问题。

最后一步触发配对:

配对的触发有以下几种情况:

1:主机直接发起。

2:从机发起安全请求,如果之前绑定过,那么主机会直接用用保存的LTK加密链路,如果没有那么主机会发起配对请求。

3:BLE中的有一个安全模式的概念。当某个属性被设置为需要认证的加密链路访问时,那么当在主机访问从机的属**器时,如果链路是不安全的就会返回错误,然后主机会发起配对请求从而实现安全要求。

我们采用的就是第三种 被动等待主机触发的方式,那么首先要做的就是将一些属性设置为需要安全的链路才能访问,那么手机在访问时就会触发配对过程了。

因为我们是基于 9.0SDK 下的uart demo,所以我们将具有notify 性质RX 特征值的 cccd(客户端配置描述符)设置为需要认证和加密的安全链路。

因为手机端使能notify是需要写CCCD的

那么当手连上板子后 点击rx特征值的notify 按钮后主机会发一个 写命令写板子上的rx特征值的cccd,因为初试链路是不完全的,那么这时手机就会返回写出错,然后启动配对过程。

设置如下:

在添加RX特征值的函数中做如下的简单就可以了。

这里只截取部分代码:

static uint32_t rx_char_add(ble_nus_t * p_nus, const ble_nus_init_t * p_nus_init)

{

/**@snippet [Adding proprietary characteristic to S110 SoftDevice] */

ble_gatts_char_md_t char_md;

ble_gatts_attr_md_t cccd_md;

ble_gatts_attr_t    attr_char_value;

ble_uuid_t          ble_uuid;

ble_gatts_attr_md_t attr_md;

memset(&cccd_md, 0, sizeof(cccd_md));

BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);

//BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);

//将上面的一行修改成下面这行

BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&cccd_md.write_perm);

cccd_md.vloc = BLE_GATTS_VLOC_STACK;

memset(&char_md, 0, sizeof(char_md));

··············

··············

············

}

这样当对端设备(如手机)使能开发板的上rx特征值的notify功能时,就会因为没有写权限而触发配对,手机会发来配对请求,然后板子回复配对信息,怎么回复? 这就是第二步中最后留下的问题。如何将配对信息交给对端设备(手机)。

当手机发来配对请求时,这对板子来说是一个事件,即配对事件。最终由dispatch派发函数交给各个服务或模块的事件处理函数。

那么我们要做的就是在收到这个配对请求事件后回复第二步中设置的配对信息就可以了。在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;

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:

//注释掉原本的不支持配对的函数,改为如下的配对回复函数

//err_code = sd_ble_gap_sec_params_reply(m_conn_handle,

//BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);

err_code=sd_ble_gap_sec_params_reply(m_conn_handle,

BLE_GAP_SEC_STATUS_SUCCESS,&m_sec_params,NULL);

APP_ERROR_CHECK(err_code);

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;

}

}

到这里所有需要配置的都设置完了。程序运行后。手机连接上板子,然后访问rx特征值。因为该特征值是用来将板子数据通过Notify方式传给手机的,那么首先要点击手机上的notify按钮去使能板子的notify功能。当我们点击该按钮时就会弹出输入密码的配对框。

BLE-NRF51822教程5-静态密码设置相关推荐

  1. 计算机开机密码有几成,电脑密码设置有哪些类型 电脑开机密码忘了怎么解锁...

    现在电脑以及逐渐大众化了,很多用户为了不让别人乱动自己的电脑往往会通过设置密码的方式,电脑上有多个密码可以设置,注意要记好密码,忘记密码就难受了,就在前几天,小编朋友的开机密码忘了,自己花了大半天的功 ...

  2. tl路由器搭建PHp,TP-Link TL-WR841N路由器密码设置教程

    TP-Link TL-WR841N怎么重新设置密码?TP-Link TL-WR841N路由器有2个密码,分别是登录密码(管理员密码).无线WiFi密码.下面小编就针对重新设置登录密码与重新设置WiFi ...

  3. 华为android10手机指纹,华为手机如何设置指纹解锁?华为手机锁屏密码设置教程...

    您可以为您的设备设置锁屏密码,保护您的隐私信息. 华为手机锁屏密码设置教程 设备默认使用杂志锁屏样式.您可以点击[设置] > [锁屏和密码] > [锁屏样式]选择锁屏样式. 设置锁屏密码 ...

  4. 金立android在哪里设置密码,金立s5.5手机怎么设置锁屏密码 金立s5.5屏幕密码设置教程...

    金立s5.5怎么设置屏幕密码?手机里有隐私,不想让别人看到如何设置屏幕密码呢?下面脚本之家小编为大家介绍下s5.5设置屏幕密码教程!不知道的赶快来看下吧! 1.在手机界面点击"设置" ...

  5. 大神f1修改服务器的密码,大神F1 Plus锁屏密码怎么设置 大神F1 Plus锁屏密码设置教程...

    现在的手机安全越来越受到重视,基本上每个人都会设置锁屏密码.不过手机的种类不同,设置的方法也不尽相同.那么,大神F1 Plus手机图案锁要怎么设置呢?下面就一起来看看大神F1 Plus锁屏密码设置教程 ...

  6. BLE-NRF51822教程10—动态密码(配对码)

    本讲教程也是在 sdk中的的uart例子 的基础上修改实现动态密码(其实是配对码)的功能.Uart例子在以下目录中 XXX\Keil_v5\ARM\Pack\NordicSemiconductor\n ...

  7. 腾达无线路由器网关和域名服务器,腾达(Tenda)FH329路由器固定(静态)IP设置上网...

    腾达(Tenda)FH329路由器固定(静态)IP上网的设置方法:适合办理的是固定(静态)IP上网宽带的用户.ADSL(PPPOE)拨号上网.自动获取IP上网,这两种宽带类型的用户,不适合本文介绍的方 ...

  8. 树莓派3 有线静态路由设置_配置树莓派为wifi热点(AP模式)

    该功能主要用于搭建一个小型的的网络,使得连接至热点的各个设备可以进行通信,用于构建物联网系统(如智能家居)或是无线控制指定设备.另外这一网络也是独立的,并未启用NAT连接至互联网,具有一定的安全性也为 ...

  9. wps的计算机在哪里设置密码,wps文件怎么设置和取消密码 wps文件密码设置和取消的步骤方法...

    在wps制作文件时,有时候我们需要中途离开,但是担心其他用户不小心操作导致文件丢失,那么我们可以设置wps文件密码,这样就可以避免了,那么怎么将wps文件设置密码呢?其实设置方法非常简单,下面教程之家 ...

最新文章

  1. java滥用接口_吐槽一下项目中的代码坏味道:滥用java常量
  2. XSKY发布两款存储产品 以Ceph为核心
  3. 测试电阻电容 二三极管的好帮手 晶体管测试显示模块
  4. 【TJOJI\HEOI2016】求和
  5. Excel 宏代码实现按相同值分组设置背景颜色
  6. 【剑指offer】_02替换空格
  7. 每个 Linux 用户都应该知道的命令行技巧
  8. 由两个问题引发的对GaussDB(DWS)负载均衡的思考
  9. django 1.8 官方文档翻译: 3-4-1 基于类的视图
  10. bzoj1854: [Scoi2010]游戏 贪心
  11. Nginx配置SSL报错 nginx: [emerg] unknown directive ssl
  12. curl: (48) An unknown option was passed in to libcurl
  13. 《挖掘管理价值:企业软件项目管理实战》一1.3 软件项目管理模型
  14. 无线通信设备安装工程概预算编制_安装工程定额与预算编制——安装工程概预算培训...
  15. 微信公共号token验证失败解决办法之一
  16. IPD解读——市场管理(MM)方法论
  17. LaTeX各种算法排版
  18. IR PC IP 之义
  19. Sphnix + Markdown 记笔记之一目了然的搭建过程
  20. WebSphere Message Broker(2)--WMB V8下载、安装

热门文章

  1. 深度好文:select与非阻塞IO
  2. 后台开发技术--接入层设计
  3. WARN [com.mchange.v2.async.ThreadPoolAsynchronousRunner] - com.mchange.v2.as
  4. 消防验收找问题,一般就是这些了!
  5. 数据中心柴油发电机组功率
  6. 谷歌数据中心采用机器人销毁硬盘驱动器
  7. 串行和并行的区别_入门参考:从Go中的协程理解串行和并行
  8. 成功解决TypeError: take() got an unexpected keyword argument ‘fill_value‘
  9. 成功解决torch.cuda.CudaError: CUDA driver version is insufficient for CUDA runtime version (35) [ WARN:0
  10. CSDN:荣幸获得国内第一大技术社区CSDN 2018博客之星名额!感谢!