nRF52832——唯一 ID 与加密解密

nRF52832——唯一 ID 与加密解密

  • 唯一 ID 概念
    • 唯一 ID 作用
    • 读取唯一 ID
  • 唯一 ID 用于加密
    • TEA 加密算法
    • 唯一 ID 的加密和解密


唯一 ID 概念

唯一 ID 作用

nRF52xx 微控制器提供一组 64 位的唯一 ID 号,这个唯一身份标识所提供的 ID 值对任意一个 nRF52xx 微控制器,在任何情况下都是唯一的。用户在何种情况下,都不能修改这个身份标识。按照用户不同的用法,可以以字节(8 位)为单位读取,也可以以半字(16 位)或者全字(32 位)读取。对应唯一ID 号,常见的应用场合如下面几种:

  • 用来作为序列号;
  • 用来作为密码,在编写闪存时,将此唯一标识与软件加解密算法结合使用,提高代码在闪 存存储器内的安全性;
  • 用来激活带安全机制的自举过程;

读取唯一 ID

设备唯一 ID 保存存在寄存器 FICR 中:工厂信息配置寄存器(FICR)是在工厂预先编程的,用户不能删除。这些寄存器包含特定于芯片的信息和配置。

寄存器名称偏移地址描述
DEVICE ID[0]0x060设备 identifier
DEVICE ID[1]0x064设备 identitier

因此识别芯片中的唯一 ID 的方式就是读取寄存器 DEVICEID 内的值,因为这个参数值是不能修改的,出厂的时候由厂家固化的。因此寄存器 DEVICEID 为只读寄存器,我们在串口例子基础上就行修改,因此工程结构不就行修改。读取了唯一 ID 的寄存器值后,通过串口打印输出,来进行演示。编写程序如下所示:


#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "app_uart.h"
#include "app_error.h"
#include "nrf_delay.h"
#include "nrf.h"
#include "bsp.h"
#if defined (UART_PRESENT)
#include "nrf_uart.h"
#endif
#if defined (UARTE_PRESENT)
#include "nrf_uarte.h"
#endif//#define ENABLE_LOOPBACK_TEST  /**< if defined, then this example will be a loopback test, which means that TX should be connected to RX to get data loopback. */#define MAX_TEST_DATA_BYTES     (15U)                /**< max number of test bytes to be used for tx and rx. */
#define UART_TX_BUF_SIZE 256                         /**< UART TX buffer size. */
#define UART_RX_BUF_SIZE 256                         /**< UART RX buffer size. */void uart_error_handle(app_uart_evt_t * p_event)
{if (p_event->evt_type == APP_UART_COMMUNICATION_ERROR){APP_ERROR_HANDLER(p_event->data.error_communication);}else if (p_event->evt_type == APP_UART_FIFO_ERROR){APP_ERROR_HANDLER(p_event->data.error_code);}
}#define UART_HWFC APP_UART_FLOW_CONTROL_DISABLED/*** @brief Function for main application entry.*/
int main(void)
{uint32_t err_code;uint32_t id1,id2;id1=NRF_FICR->DEVICEID[0]; //读取id低31位id2=NRF_FICR->DEVICEID[1];//读取id高31位const app_uart_comm_params_t comm_params ={RX_PIN_NUMBER,TX_PIN_NUMBER,RTS_PIN_NUMBER,CTS_PIN_NUMBER,UART_HWFC,false,
#if defined (UART_PRESENT)NRF_UART_BAUDRATE_115200
#elseNRF_UARTE_BAUDRATE_115200
#endif};APP_UART_FIFO_INIT(&comm_params,UART_RX_BUF_SIZE,UART_TX_BUF_SIZE,uart_error_handle,APP_IRQ_PRIORITY_LOWEST,err_code);APP_ERROR_CHECK(err_code);while (1){printf("打印id:%lx%lx\r\n",id1,id2);nrf_delay_ms(1000);}}

唯一 ID 用于加密

TEA 加密算法

唯一 ID 常用的场合就是加密,我们可以采用一个简单的加密算法对 ID 号进行加密。那么如果要正确运行程序就需要对唯一 ID 进行正确解密。

常用的代码加密方案一般有两种。

  • 通过某种硬件手段防止单片机 FLASH 中的代码被读出,比如禁止读取、或者关闭下载接口;
  • 就算代码能被读出来,把它烧到另一个芯片中,也无法正常运行(与特定芯片紧紧绑定)。

以目前的技术水平来说,不论如何禁止,似乎都有人可以把程序从芯片内部读取出来。那么就算被窃取者读取了程序的二进制文件,烧到另一个同型号的处理器芯片里,也必须无法运行。要实现这一目的,首先要有一个与单片机唯一绑定的东西,那么这就需要唯一 ID 号了,每一片芯片 ID 都不相同,并且全世界保存唯一。

研发者由唯一 ID 号通过加密算法计算得到检验码,然后向使用者下发。使用者可将此码通过专用编写的上位机把效验码烧写器写入到芯片的 EEPROM 中。 在代码中,可以在多个位置对 EEPROM 中的校验码进行比对,一致则正常运行,否则宕机。 比如在程序有最前面,一开始就进行鉴权,如果失败则向用户显示“无权限”等信息,停止程序运行;或是在程序中比较关键的条件分支中,这样如果程序被人破译,比如反汇编,通过修改一些条件判断,强行使其正常运行。因为程序中鉴权的地方越多,这势必让破解者费一些周折,但是也不能过多的地方出现检验码,避免被统计识别。 对于唯一 ID 的加密原理如下图

在这里插入图片描述
本节讲采用在安全学领域中常见的 TEA 加密算法进行加密和解密。所谓的 TEA(Tiny Encryption Algorithm)是一种分组加密算法,它的实现非常简单,通常只需要很精短的几行代码就可以实现,因此非常适合用单片机的加密中。

TEA 算法最初是由剑桥计算机实验室的 David Wheeler 和 Roger Needham 在 1994 年设计 的。TEA 算法使用 64 位的明文分组和 128 位的密钥,它使用 Feistel 分组加密框架,需要进行 64 轮 迭代。该算法使用了一个神秘常数δ作为倍数,它来源于黄金比率,以保证每一轮加密都不相同。但 δ的精确值似乎并不重要,这里 TEA 把它定义为 δ=「(√5 - 1)231」(也就是程序中的 0×9E3779B9)。

Tea 算法秘钥为 16 字节,每次分块处理的数据是 8 个字节,两个 32 位数据。加密过程中,加法运算和减法运算用作可逆的操作,算法轮流使用异或运算提供非线性特性,双移位操作使秘钥和数据的所有比特重复地混合,最多 16 轮循环就能使数据或密钥的单个比特的变化扩展到接近 32 比特. 因此 ,当循环轮数达到 16 轮以上时 ,该算法具有很强的抗差分攻击能力 ,128 比特密钥长度可以抗击穷举搜索攻击,该算法设计者推荐算法迭代次数为 32 轮。

唯一 ID 的加密和解密

下面简单的演示如何对唯一 ID 进行加密,搭建加密工程如下图
在这里插入图片描述

tea.c 代码如下:

#include "tea.h"void encrypt (uint32_t* v, uint32_t* k) 
{uint32_t v0=v[0], v1=v[1], sum=0, i;           /* set up */uint32_t delta=0x9e3779b9;                     /* a key schedule constant */uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];   /* cache key */for (i=0; i < 32; i++) {                       /* basic cycle start */sum += delta;v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);  }                                              /* end cycle */v[0]=v0; v[1]=v1;
}void decrypt (uint32_t* v, uint32_t* k) 
{uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i;  /* set up */uint32_t delta=0x9e3779b9;                     /* a key schedule constant */uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];   /* cache key */for (i=0; i<32; i++) {                         /* basic cycle start */v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);sum -= delta;                                   }                                              /* end cycle */v[0]=v0; v[1]=v1;
}

主函数中,设置一组加密密码 key,本例简单的设置为 0x1234 作为密码。然后读取设备的唯一 ID 号,对唯一 ID 号进行 tea 加密。加密完成后的 ID 号可以作为程序加密的效验码。为了验证加密是否成功,再对加密后的唯一 ID 号进行解密。对比读取的唯一 ID 号和解密后的唯一 ID 号,如果两者相同,则证明加密算法正确。具体代码如下所示:


#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "app_uart.h"
#include "app_error.h"
#include "nrf_delay.h"
#include "nrf.h"
#include "bsp.h"
#if defined (UART_PRESENT)
#include "nrf_uart.h"
#endif
#if defined (UARTE_PRESENT)
#include "nrf_uarte.h"
#endif
#include "tea.h"//#define ENABLE_LOOPBACK_TEST  /**< if defined, then this example will be a loopback test, which means that TX should be connected to RX to get data loopback. */#define MAX_TEST_DATA_BYTES     (15U)                /**< max number of test bytes to be used for tx and rx. */
#define UART_TX_BUF_SIZE 256                         /**< UART TX buffer size. */
#define UART_RX_BUF_SIZE 256                         /**< UART RX buffer size. */void uart_error_handle(app_uart_evt_t * p_event)
{if (p_event->evt_type == APP_UART_COMMUNICATION_ERROR){APP_ERROR_HANDLER(p_event->data.error_communication);}else if (p_event->evt_type == APP_UART_FIFO_ERROR){APP_ERROR_HANDLER(p_event->data.error_code);}
}#define UART_HWFC APP_UART_FLOW_CONTROL_DISABLED/*** @brief Function for main application entry.*/
int main(void)
{uint32_t err_code;uint32_t id[2];uint32_t key[]={0x1234,0x1234,0x1234,0x1234};  //密码id[0]=NRF_FICR->DEVICEID[0]; //读取id低31位id[1]=NRF_FICR->DEVICEID[1];//读取id高31位const app_uart_comm_params_t comm_params ={RX_PIN_NUMBER,TX_PIN_NUMBER,RTS_PIN_NUMBER,CTS_PIN_NUMBER,UART_HWFC,false,
#if defined (UART_PRESENT)NRF_UART_BAUDRATE_115200
#elseNRF_UARTE_BAUDRATE_115200
#endif};APP_UART_FIFO_INIT(&comm_params,UART_RX_BUF_SIZE,UART_TX_BUF_SIZE,uart_error_handle,APP_IRQ_PRIORITY_LOWEST,err_code);APP_ERROR_CHECK(err_code);while (1){printf("打印id:%lx%lx\r\n",id[0],id[1]);encrypt(id,key);//加密,工程的验证码printf("加密id:%lx%lx\r\n",id[0],id[1]);decrypt(id,key);//解密printf("解密id:%lx%lx\r\n",id[0],id[1]);printf("-------------------\r\n");nrf_delay_ms(1000); }}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/535802.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端之用html做一个用户登陆界面

用户登陆界面 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>用户注册页面</title></head> <body><form action"https://www.baidu.com" method"post">…

瑞熙贝通实验室物联网管理平台新升级|支持远程开门视频监控与电源控制以及环境监测

瑞熙贝通实验室智能物联网管控平台&#xff1a;利用“互联网与物联网技术”有机融合&#xff0c;对实验室的用电安全监测、实验室环境异常监测&#xff08;颗粒物监测、明火监测、可燃气体、烟雾监测、温湿度传感器、红外人体感应&#xff09;、实验室人员安全准入、万物互联等…

科普编程中 宿主环境(host environment) 基础概念

我们来说说 宿主环境 首先 什么是宿主环境&#xff1f; 宿主环境 (host environment) 意思就是 程序运行所必须的依赖环境 安卓和IOS 系统 就是两种完全不同的宿主环境 总所周知 微信版的安卓App 在苹果中是无法运行的 所以说 Android 是安卓软件的宿主环境 离开了这个宿主环…

MySQL基础-----多表查询之内外连接与自连接

目录 前言 一、内连接 1.隐式内连接 2.显式内连接 二、外连接 1.左外连接 2.右外连接 三、自连接 1.自连接查询 2.联合查询 前言 本期我们学习MySQL中多表查询的内连接、外连接和自连接。这里我会通过相关的案例去讲解多表查询中的内外连接与自连接的查询方式&#xff…

经验分享:专业知识库的搭建秘诀都在这里啦!

我想必每个人都有过被一堆纷繁复杂的信息搞得头疼不已的时候&#xff0c;对吧&#xff1f;那么你是否想过&#xff0c;如果我们有一个专门收藏整理这些信息的地方&#xff0c;会变得多么方便呢&#xff1f;这就是知识库的作用。所以&#xff0c;接下来我就要向大家分享如何搭建…

promise,async →await,then→catch,try→catch 使用简介

提示&#xff1a;promise&#xff0c;async →await&#xff0c;then→catch&#xff0c;try→catch 使用简介 文章目录 前言一、Promise二、promise then/catch三、promise async/await try/catch总结 前言 需求&#xff1a;promise&#xff0c;async →await&#xff0c;then…

小米公司研发岗的年终奖。。

小米 好的公司有年终且在年前发放&#xff0c;一般的公司有&#xff08;可能打折的&#xff09;年终且年后分批发放&#xff0c;不好的公司各有操作。 3 月已来&#xff0c;小米的年终也开始热议起来。 最近&#xff0c;一则「传小米年终打折&#xff0c;14薪能保住吗」冲上热搜…

怎么使用视频号下载助手下载视频号视频!自救一下

曾经的视频号下载助手&#xff0c;在互联网浪潮中面临的考验&#xff0c;现在轮到去水印提取下载了&#xff0c; 为什么要写 最近大家有没有发现&#xff0c;我写内容不仅仅是教程还和大家唠嗑了。 对&#xff01;我改写作方式了&#xff0c;但是我头疼&#xff0c;不知道和大…

多线程锁.

公平锁与非公平锁 公平锁是指多个线程按照申请锁的顺序来获取锁,这里类似排队买票,先来的人先买后来的人在队尾排着,这是公平的Lock lock new Reentrantlock(true);/true表示公平锁,先来先得非公平锁指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请…

pytorch诗词生成3--创建模型

先上代码&#xff1a; import tensorflow as tf from dataset import tokenizer# 构建模型 model tf.keras.Sequential([# 不定长度的输入tf.keras.layers.Input((None,)),# 词嵌入层tf.keras.layers.Embedding(input_dimtokenizer.vocab_size, output_dim128),# 第一个LSTM层…

2024年游戏投影仪评测:当贝D5X Pro大屏玩游戏,沉浸感十足

对于年轻人来说&#xff0c;投影仪是打造家居氛围感的神器&#xff0c;它不仅可以替代电视作为主要的观影设备&#xff0c;更能从尺寸、画面效果上模拟电影院的效果&#xff0c;从而在家实现超大屏观影。 但如果你只是把投影仪当做电视来用的话&#xff0c;那多少有点浪费了&a…

GDPU 竞赛技能实践 天码行空3

1. 五星填数 &#x1f496; 源代码 public class Main {static int[] nums new int[11];static boolean[] used new boolean[13];static long ans 0;static{used[7] true;used[11] true;}public static void main(String[] args){dfs(1);System.out.println(ans / 10);//…