1. UID

在嵌入式里一般指:芯片唯一 ID(Unique ID)

  • 每个 MCU / 芯片出厂时固化在片上,全球唯一、不可修改
  • 常见用途:
    • 设备身份识别、序列号
    • 加密密钥根密钥
    • 防抄板、产品授权绑定
  • 常见芯片:STM32、ESP32、GD32 等几乎都有 UID

2. MD5

嵌入式里是:MD5 哈希算法

  • 对一段数据(固件、密钥、文件)计算摘要
  • 嵌入式常用场景:
    • 固件完整性校验(防篡改、防损坏)
    • 数据签名、身份验证
    • 配合 UID 做设备唯一密钥
  • 特点:计算快、占用资源小,很多嵌入式库自带 MD5

3. RDP

嵌入式里极少直接用,一般是:

  • Remote Desktop Protocol 远程桌面协议
  • 嵌入式场景基本不用 RDP,更多用:
    • SSH / Telnet
    • VNC(带屏 Linux 设备)
    • 串口调试、ADB、网口调试工具
  • 只有跑完整 Linux 的高端嵌入式(工控机、树莓派)才可能开 RDP

嵌入式里最常见的组合用法

  1. 读芯片 UID
  2. MD5 对 UID 做哈希,生成设备唯一密钥
  3. 做固件加密、授权、防克隆


一、STM32 读取 UID + 计算 MD5(基于 HAL 库)

前置条件

  1. STM32CubeIDE/Keil 开发环境
  2. 已移植 MD5 基础库(代码中包含简化版 MD5 核心函数)
  3. STM32 任意型号(F1/F4/H7 等,UID 地址略有差异,代码中标注)

完整代码

#include "stm32f4xx_hal.h"
#include <string.h>
#include <stdio.h>

// ===================== MD5 核心函数(简化版)=====================
typedef struct {
    uint32_t total[2];          // 总字节数
    uint32_t state[4];          // 哈希状态
    uint8_t buffer[64];         // 数据缓冲区
    uint8_t digest[16];         // 最终MD5结果(16字节)
} MD5_CTX;

void MD5_Init(MD5_CTX *ctx);
void MD5_Update(MD5_CTX *ctx, const uint8_t *input, uint32_t input_len);
void MD5_Final(MD5_CTX *ctx, uint8_t *output);

// MD5核心实现(省略具体算法,可直接用)
void MD5_Init(MD5_CTX *ctx) {
    ctx->state[0] = 0x67452301;
    ctx->state[1] = 0xEFCDAB89;
    ctx->state[2] = 0x98BADCFE;
    ctx->state[3] = 0x10325476;
    ctx->total[0] = ctx->total[1] = 0;
}
// 注:完整MD5_Update/MD5_Final实现可从开源库(如mbedtls)移植,此处仅保留框架

// ===================== STM32 UID 读取 + MD5 计算 =====================
// STM32 UID 地址:
// F1/F4: 0x1FFF7A10 (96位,12字节)
// H7: 0x52002000 (128位,16字节)
#define STM32_UID_ADDR    ((uint32_t *)0x1FFF7A10)

// 读取STM32 UID
void STM32_Read_UID(uint8_t *uid_buf, uint32_t *uid_len) {
    uint32_t uid[3];
    // 读取96位UID(3个32位寄存器)
    uid[0] = STM32_UID_ADDR[0];
    uid[1] = STM32_UID_ADDR[1];
    uid[2] = STM32_UID_ADDR[2];
    
    // 转换为字节数组(12字节)
    memcpy(uid_buf, uid, 12);
    *uid_len = 12;
    
    // 打印UID(调试用)
    printf("STM32 UID: %08X%08X%08X\r\n", uid[0], uid[1], uid[2]);
}

// 对UID计算MD5
void UID_Calc_MD5(uint8_t *uid_buf, uint32_t uid_len, uint8_t *md5_result) {
    MD5_CTX md5_ctx;
    MD5_Init(&md5_ctx);
    MD5_Update(&md5_ctx, uid_buf, uid_len);
    MD5_Final(&md5_ctx, md5_result);
    
    // 打印MD5结果(32位16进制字符串)
    printf("UID MD5: ");
    for(int i=0; i<16; i++) {
        printf("%02X", md5_result[i]);
    }
    printf("\r\n");
}

// 主函数调用示例
int main(void) {
    HAL_Init();
    // 初始化串口(用于打印,需自行实现HAL_UART_Init)
    
    uint8_t uid_buf[12];
    uint32_t uid_len;
    uint8_t md5_result[16];
    
    // 1. 读取UID
    STM32_Read_UID(uid_buf, &uid_len);
    
    // 2. 计算UID的MD5
    UID_Calc_MD5(uid_buf, uid_len, md5_result);
    
    while (1) {
        // 主循环
    }
}

关键说明

  1. UID 读取:STM32 的 UID 是出厂固化的 96/128 位唯一值,地址需根据芯片型号调整(代码中标注)。
  2. MD5 适配:嵌入式 MD5 需精简资源,建议移植 mbedtls 的 MD5 模块(体积小、效率高)。
  3. 输出格式:MD5 结果为 16 字节,转成 32 位 16 进制字符串是嵌入式最常用的形式。

二、ESP32 读取 UID + 计算 MD5(基于 ESP-IDF)

前置条件

  1. ESP-IDF 4.4+ 开发环境
  2. 已启用 mbedtls 组件(ESP-IDF 默认自带)

完整代码

#include <stdio.h>
#include <string.h>
#include "esp_system.h"
#include "mbedtls/md5.h"

// 读取ESP32芯片UID(EFUSE BLK0,64位)
void ESP32_Read_UID(uint8_t *uid_buf, uint32_t *uid_len) {
    uint64_t chip_uid = esp_efuse_get_chip_id(); // 获取64位芯片唯一ID
    memcpy(uid_buf, &chip_uid, 8);
    *uid_len = 8;
    
    // 打印UID(16进制)
    printf("ESP32 UID: %016llX\r\n", chip_uid);
}

// 对UID计算MD5
void UID_Calc_MD5(uint8_t *uid_buf, uint32_t uid_len, uint8_t *md5_result) {
    mbedtls_md5_context md5_ctx;
    
    // 初始化MD5上下文
    mbedtls_md5_init(&md5_ctx);
    mbedtls_md5_starts(&md5_ctx);
    
    // 输入UID数据
    mbedtls_md5_update(&md5_ctx, uid_buf, uid_len);
    
    // 计算最终MD5
    mbedtls_md5_finish(&md5_ctx, md5_result);
    mbedtls_md5_free(&md5_ctx);
    
    // 打印MD5结果
    printf("UID MD5: ");
    for(int i=0; i<16; i++) {
        printf("%02X", md5_result[i]);
    }
    printf("\r\n");
}

void app_main(void) {
    uint8_t uid_buf[8];
    uint32_t uid_len;
    uint8_t md5_result[16];
    
    // 1. 读取ESP32 UID
    ESP32_Read_UID(uid_buf, &uid_len);
    
    // 2. 计算UID的MD5
    UID_Calc_MD5(uid_buf, uid_len, md5_result);
    
    while(1) {
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

关键说明

  1. UID 读取:ESP32 通过esp_efuse_get_chip_id()获取 64 位唯一 ID,无需手动读寄存器。
  2. MD5 实现:ESP-IDF 自带 mbedtls 库,直接调用即可,无需手动实现 MD5 算法。
  3. 编译配置:确保menuconfig中启用Component config -> mbedTLS -> Enable MD5

总结

  1. 嵌入式 UID:STM32/ESP32 均有出厂唯一 ID,是设备身份识别的核心,地址 / 读取方式因芯片而异。
  2. 嵌入式 MD5:优先使用成熟库(mbedtls),避免手动实现算法,重点用于 UID 加密、固件校验。
  3. 嵌入式 RDP:几乎不用,ESP32/STM32 远程调试优先用串口 / 网口 / SSH,仅工控级嵌入式设备可能支持 RDP。

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐