前段時間因爲應用須要對產品受權進行限制,因此研究了一下有關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不一樣因此信息徹底不符,程序就不會運行。從而實現了對程序權限的限制。
歡迎關注: