唯一ID进行程序加密实现
一 背景说明
项目程序需要进行加密处理。
考虑利用嵌入式芯片的唯一UID,结合Flash读写来实现。
加密后的程序,可以使得从芯片Flash中读取出来的文件(一般为HEX格式)不能用于其他的芯片。
二 原理介绍
【1】芯片唯一ID
芯片提供了器件电子签名,即唯一身份标识。该信息存储在产品唯一身份标识寄存器中:
UID寄存器描述如下:
其中,UID1、UID2均为16位,UID3为32位,UID4为32位。
这样就可以从0x0x1FFFF7E8地址读取3个32bit的数据,获取它的唯一ID。
【2】程序加密逻辑说明
在讲解简单的程序加密方法之前,先了解一下通常的MCU程序复制方法。
通过烧写器(或者其他手段),将MCU内部程序存储区中的内容全部读出,就获取了烧写文件。如果烧写文件没有被加密,则可以直接将它烧写到别的MCU中运行,就完成了复制。
有没有办法可以使得对方即使获取了烧写文件,也不能直接烧写到别的MCU中运行呢?
我们可以利用芯片的唯一ID来实现一种简单的程序加密方法。由于每个芯片的唯一ID是不同的,我们只要在程序中检查ID的合法性即可,主要的步骤如下:
(i)程序首次运行时,读出芯片的唯一ID;
(ii)将ID使用加密算法,计算出一个特殊值,写入到非易失存储区中(需要掉电能保存);
(iii)以后每次运行时,读出芯片唯一ID,通过算法计算后,与非易失存储区中保存的值比对,如果一致,则正常运行;如果不对,停止运行。
由于每个芯片中的ID是不同的,由加密算法算出的值也是不同的,所以,即使有人获取了我们的烧写文件,烧写到另一片MCU中,由于ID不同,最后也会比对出错,无法执行。
三 设计实现
【1】编写获取并加密ID的接口:
1 |
|
【2】编写判断加密ID的接口:
1 | const u32 uid_save = 0xFFFFFFFF; //CPUID保存 |
【3】主函数初始化中执行上面的判断:
1 | void main(void) |
【注意点】:
(i)注意 const u32 uid_save 的类型定义,我使用的 keil 环境中不能加 volatile 修饰,如果加了会被定义到RAM区,而非Flash区,这样起不到加密的效果。
如果用的是IAR环境,可能必须加 volatile 修饰,同时工程选项Options->Debugger->Download中选择: use flash loader。不这样做的后果是按速度优化编译,再判断加密值,不会重新读取加密值,导致判断出错;
(ii)注意 const u32 uid_save 的初始化值定义为全F,和擦除后的状态一致,所以程序中省略了擦除的操作,可以直接写入;
(iii)唯一ID存储地址 0x1FFFF7E8 应该尽量隐蔽,尽量避免在程序中直接出现该值:
更好的做法可以参考下面的方案:
1 | /************************************************************************** |
四 参考资料
【1】STM32 的加密实现_stn32加密-CSDN博客
【2】【STM32+cubemx】0025 HAL库开发:唯一ID获取和简单的程序加密_mcu唯一uid加密-CSDN博客
相关链接(侵删)
欢迎到公众号来唠嗑: