前段时间因为应用须要对产品受权进行限制,因此研究了一下有关STM32 MCU的惟一ID的资料,并最终利用它实现了咱们的目标。算法
1、基本描述编程
在STM32的全系列MCU中均有一个96位的惟一设备标识符。在ST的相关资料中,对其功能的描述有3各方面:安全
在资料中对其特性的描述是:96 位的惟一设备标识符提供了一个对于任何设备和任何上下文都惟一的参考号码。用户永远不能改变这些位。96 位的惟一设备标识符也能够以单字节/半字/字等不一样方式读取,而后使用自定义算法链接起来。工具
想要读取惟一ID,就须要知道它的存储地址,在不一样系列的MCU中地址是有差异的,咱们查询了部分MCU的资料并将其总结以下:ui
2、获取惟一ID加密
前面咱们对惟一ID作了简单的描述,而且获得了其存储地址,接下来咱们说以说如何获得这个ID。spa
前面已经描述过惟一ID能够按字节、半字、字等方式读取。惟一ID是一个96位的信息串,因此按字读取就是3个字,按半字读取就是6个,按字节读取就是12个。本质上没有区别,在这里咱们按字读取。code
1 /*定义STM32 MCU的类型*/ 2 typedef enum { 3 STM32F0, 4 STM32F1, 5 STM32F2, 6 STM32F3, 7 STM32F4, 8 STM32F7, 9 STM32L0, 10 STM32L1, 11 STM32L4, 12 STM32H7, 13 }MCUTypedef; 14 15 16 uint32_t idAddr[]={0x1FFFF7AC, /*STM32F0惟一ID起始地址*/ 17 0x1FFFF7E8, /*STM32F1惟一ID起始地址*/ 18 0x1FFF7A10, /*STM32F2惟一ID起始地址*/ 19 0x1FFFF7AC, /*STM32F3惟一ID起始地址*/ 20 0x1FFF7A10, /*STM32F4惟一ID起始地址*/ 21 0x1FF0F420, /*STM32F7惟一ID起始地址*/ 22 0x1FF80050, /*STM32L0惟一ID起始地址*/ 23 0x1FF80050, /*STM32L1惟一ID起始地址*/ 24 0x1FFF7590, /*STM32L4惟一ID起始地址*/ 25 0x1FF0F420}; /*STM32H7惟一ID起始地址*/ 26 27 /*获取MCU的惟一ID*/ 28 void GetSTM32MCUID(uint32_t *id,MCUTypedef type) 29 { 30 if(id!=NULL) 31 { 32 id[0]=*(uint32_t*)(idAddr[type]); 33 id[1]=*(uint32_t*)(idAddr[type]+4); 34 id[2]=*(uint32_t*)(idAddr[type]+8); 35 } 36 }
3、使用惟一ID blog
咱们获得惟一ID固然是为了使用它,前面在ST资料中描述了三个使用方式。咱们在这里来使用它实现软件权限的限制。那么如何用惟一ID来实现软件运行权限的限制呢?咱们说一说思路:字符串
首先,咱们须要指定一个Flash地址,至于于地址空间的大小则与咱们须要存储的信息有关,通常都不会太长。例如,咱们使用MD5来生成加密信息,则最多须要16个字节的存储空间;若是咱们使用SHA1来做为生成算法,则最多须要20个字节的空间。固然,咱们也能够选取其中的一段或几段。无论选用多大的空间都须要将其清零,即初始化为0xFFFFFFFF。
接下来在程序运行前读取前面指定的地址并读取其值,并判断是否所有为0xFFFFFFFF,即判断程序是否第一次运行。若是是,那么就获取惟一ID并做相应的处理,而后将信息写入前面指定的地址中。
若是不是第一次运行,则读取指定地址的值,并用一样的算法处理惟一ID。而后比较存储的信息与计算的信息是否一致,一致则启动程序运行,不一致则终止运行。
若是有人使用工具读出FLASH内容时,由于该指定的地址已经被写入了信息,因此若是把读出的文件再烧到其它MCU芯片,因惟一ID不一样因此信息彻底不符,程序就不会运行。从而实现了对程序权限的限制。
欢迎关注: