首页 / 资讯中心 / 文章详情

ATSHA204加密芯片STM32驱动与认证例程实战

ATSHA204加密芯片STM32驱动与认证例程实战 ★ FEATURED ARTICLE
简介这份资源面向需要在嵌入式项目中集成安全加密功能的开发者尤其是使用STM32平台进行物联网、电子支付或身份验证设备开发的工程师。内容以Microchip ATSHA204加密芯片为核心提供完整的中文技术手册涵盖芯片工作原理、技术规格、I2C与SPI通信协议、硬件接口要求以及内置加密引擎和密钥管理系统的安全机制说明。同时附带基于STM32F103微控制器的例程demo演示如何在该平台上与ATSHA204通信并调用密钥存储、数据加密和哈希算法等功能。压缩包共550个文件约14.95MB以c与h源码、o目标文件、crf编译记录、pdf手册、uvprojx与uvoptx工程文件及map、hex、axf等构建产物为主另含少量sdk与测试脚本便于直接编译验证。目前已有612人学习下载适合希望降低安全芯片上手门槛、快速完成集成实践的开发者参考。1. 从一颗被忽视的加密芯片说起ATSHA204 到底能解决什么问题很多做嵌入式产品的开发者第一次接触 ATSHA204 都是在项目被抄怕了之后。产品出货半年市面上出现一模一样的功能板子固件被人读出来直接烧到山寨硬件上跑你辛辛苦苦写的标定参数、授权逻辑、密钥全部裸奔。这时候才想起来加一颗加密芯片翻遍资料发现官方文档是英文的例程是零散的STM32 的驱动还得自己从头写。ATSHA204 就是在这种场景下被大量使用的经典器件——它是一颗基于 I2C 接口的加密认证芯片内部带有一块无法被外部直接读取的 EEPROM 密钥区配合 SHA-256 做挑战应答认证用来做产品防克隆、配件防伪、固件授权绑定。这份资源把中文手册和 STM32 例程 demo 放在一起对正在做硬件加密方案选型的嵌入式开发者来说省掉了啃英文 datasheet 和从零搭 I2C 时序的时间。它适合谁适合手里已经有 STM32 工程、需要在现有固件里嵌入一颗认证芯片、又不想被英文手册卡住的开发者。2. 芯片能力与工程定位ATSHA204 在系统里扮演什么角色2.1 它不是加密狗是密钥保险箱很多人第一次听到“加密芯片”会误以为它负责加密数据流其实 ATSHA204 的定位完全不同。它内部有 16 个槽位Slot每个槽位可以配置成存放密钥、数据或者做特定用途。密钥写进去之后外部通过 I2C 只能读到“是否匹配”的结果读不出密钥本身。主机 MCU 发一个随机数挑战芯片用内部密钥做 SHA-256 运算后返回摘要应答主机侧用同样的密钥和算法验证摘要是否一致。整个过程中密钥不出芯片这就是它防克隆的核心逻辑。在工程里它通常承担三个角色一是产品授权主机固件启动时先跟芯片做一次认证认证不过就不进入正常工作模式二是配件识别比如打印机墨盒、设备电池这类耗材主机通过认证判断是不是原厂配件三是数据保护把一些关键标定参数存进芯片的加密槽位只有通过认证后才能读出使用。2.2 硬件连接与 I2C 地址ATSHA204 的硬件接口非常简洁SDA、SCL 两根线加上电源和地就能工作典型电路里还会在 SDA/SCL 上各挂一个 4.7k 的上拉电阻。它的 I2C 从机地址是固定的 0xC87 位地址形式为 0x64这一点在写驱动时要注意不能像普通 EEPROM 那样通过地址引脚改地址。如果一条 I2C 总线上挂多颗 ATSHA204需要额外加 I2C 多路复用器或者用 GPIO 控制电源分时上电这是实际项目里常见的做法。供电范围方面芯片支持 2.0V 到 5.5V可以跟 3.3V 的 STM32 直接对接不需要电平转换。但要注意 I2C 总线的上拉电压必须跟主机 IO 电平一致否则会出现通信不稳定。我在一个项目里遇到过 5V 上拉配 3.3V IO 的情况读出来的数据偶尔错位排查了半天才发现是电平不匹配。2.3 与 STM32 的配合方式STM32 侧一般用硬件 I2C 外设来驱动 ATSHA204也可以用 GPIO 模拟 I2C。硬件 I2C 的优点是时序稳定、CPU 占用低缺点是 STM32 的硬件 I2C 在某些系列上有已知的锁死问题需要加超时复位逻辑。GPIO 模拟 I2C 的优点是移植方便、不受外设限制缺点是时序精度依赖延时函数在高主频下需要仔细调延时。例程 demo 里通常会把这两种方式都提供出来方便开发者根据自己用的 STM32 系列选择。如果你用的是 STM32F1 或者 F4 系列硬件 I2C 基本可用但建议加上总线恢复逻辑如果是 STM32G0 或者 L4 系列硬件 I2C 的稳定性好很多可以直接用。3. 例程拆解从 I2C 时序到认证流程的完整链路3.1 目录结构与文件职责拿到这份资源后先别急着编译花五分钟把目录结构看清楚后面改代码会顺很多。典型的例程目录大致长这样ATSHA204_STM32_Demo/ ├── Doc/ │ ├── ATSHA204_中文手册.pdf │ └── ATSHA204_命令集说明.md ├── Drivers/ │ ├── STM32F10x_StdPeriph_Driver/ │ └── CMSIS/ ├── Hardware/ │ ├── atsha204.c │ ├── atsha204.h │ ├── i2c_soft.c │ └── i2c_soft.h ├── User/ │ ├── main.c │ ├── stm32f10x_it.c │ └── system_stm32f10x.c └── Project/ └── ATSHA204_Demo.uvprojxHardware/目录是核心atsha204.c里封装了芯片的所有操作函数i2c_soft.c是 GPIO 模拟 I2C 的底层实现。User/main.c里是认证流程的演示代码。Doc/目录里的中文手册是这份资源最有价值的部分命令集说明把每个命令的字节格式都列出来了不用再去翻英文原文。3.2 底层 I2C 读写函数先看底层通信这是所有上层功能的基础。ATSHA204 的 I2C 时序跟普通 EEPROM 略有不同它支持两种模式标准模式和低功耗模式。标准模式下发送命令后需要等待一段时间典型值 4ms 左右才能读响应这个等待时间在手册里叫tWHI如果不等直接读会读到 0xFF 或者错误数据。// i2c_soft.c - GPIO 模拟 I2C 写一个字节 static void I2C_WriteByte(uint8_t data) { uint8_t i; SDA_OUT(); // 切换 SDA 为输出模式 SCL_LOW(); // 拉低时钟准备数据 for (i 0; i 8; i) { if (data 0x80) SDA_HIGH(); else SDA_LOW(); data 1; delay_us(2); // 数据建立时间根据主频调整 SCL_HIGH(); // 拉高时钟从机采样 delay_us(2); SCL_LOW(); delay_us(2); } SDA_IN(); // 释放 SDA准备读 ACK delay_us(2); SCL_HIGH(); delay_us(2); // 这里读 ACK实际项目中要判断返回值 SCL_LOW(); }这段代码的关键在延时参数。delay_us(2)是经验值对应 100kHz 左右的 I2C 速率。如果你的 STM32 主频是 72MHzdelay_us的实现要保证精度否则时序会偏。我一般会在示波器上抓一下 SCL 波形确认高电平时间和低电平时间都在手册要求的范围内。ATSHA204 支持最高 1MHz 的 I2C 速率但实际用 100kHz 到 400kHz 就足够了太快反而容易受干扰。3.3 命令发送与响应解析ATSHA204 的通信协议是“命令包 响应包”的结构。命令包格式是Word Address1 字节 Count1 字节 DataN 字节 CRC2 字节。响应包格式是Count1 字节 DataN 字节 CRC2 字节。CRC 校验用的是 CRC-16 多项式 0x8005初值 0x0000。// atsha204.c - 发送命令并读取响应 uint8_t ATSHA204_SendCommand(uint8_t *cmd, uint8_t cmd_len, uint8_t *resp, uint8_t *resp_len) { uint8_t status; uint16_t crc; // 1. 发送 Word Address (0x00) 和 Count I2C_Start(); I2C_WriteByte(0xC8); // 从机地址 写 if (I2C_WaitAck()) return 1; I2C_WriteByte(0x00); // Word Address 固定为 0x00 I2C_WaitAck(); I2C_WriteByte(cmd_len); // 命令长度 I2C_WaitAck(); // 2. 发送命令数据 for (uint8_t i 0; i cmd_len; i) { I2C_WriteByte(cmd[i]); if (I2C_WaitAck()) return 2; } // 3. 发送 CRC crc CRC16(cmd, cmd_len); I2C_WriteByte(crc 0xFF); I2C_WaitAck(); I2C_WriteByte((crc 8) 0xFF); I2C_WaitAck(); I2C_Stop(); // 4. 等待芯片处理这个延时不能省 delay_ms(5); // 手册里 tWHI 典型值 4ms留余量 // 5. 读取响应 I2C_Start(); I2C_WriteByte(0xC9); // 从机地址 读 if (I2C_WaitAck()) return 3; *resp_len I2C_ReadByte(); // 第一个字节是响应长度 I2C_SendAck(); for (uint8_t i 0; i *resp_len; i) { resp[i] I2C_ReadByte(); if (i *resp_len - 1) I2C_SendAck(); else I2C_SendNack(); } I2C_Stop(); // 6. 校验响应 CRC crc CRC16(resp, *resp_len); // 实际项目中这里要比较接收到的 CRC 和计算值 return 0; }这段代码里有几个容易翻车的点。第一delay_ms(5)这个等待时间不能省我见过有人为了提速改成 1ms结果读出来的响应全是 0xFF排查了一整天。第二CRC 的计算范围要搞清楚命令包的 CRC 只算 Data 部分不包括 Word Address 和 Count响应包的 CRC 算 Count Data。第三读响应时的 ACK/NACK 时序要对最后一个字节读完要发 NACK否则从机不会释放总线。3.4 挑战应答认证流程认证流程是这份例程的核心演示内容。主机生成一个 32 字节随机数作为挑战发给 ATSHA204芯片用指定槽位里的密钥做 SHA-256 运算返回 32 字节摘要。主机侧用同样的密钥和挑战值做一次 SHA-256比较两个摘要是否一致。// main.c - 挑战应答认证演示 uint8_t challenge[32]; uint8_t response[32]; uint8_t expected[32]; // 1. 生成随机数挑战实际项目中用硬件 RNG 或软件 PRNG for (int i 0; i 32; i) { challenge[i] rand() 0xFF; } // 2. 发送 Nonce 命令把挑战值写入芯片 uint8_t nonce_cmd[] {0x01, 0x00, 0x00}; // 命令码 参数 // ... 拼接 challenge 到命令包调用 ATSHA204_SendCommand // 3. 发送 MAC 命令让芯片用 Slot 0 的密钥做运算 uint8_t mac_cmd[] {0x08, 0x00, 0x00, 0x00}; // 命令码 模式 Slot 号 // ... 发送命令读取 32 字节响应到 response // 4. 主机侧用相同密钥和挑战计算期望值 // 这里需要主机也有一份密钥通常放在 MCU 的 Flash 里 // 或者通过其他安全方式派生 hmac_sha256(master_key, 32, challenge, 32, expected); // 5. 比较 if (memcmp(response, expected, 32) 0) { // 认证通过进入正常工作模式 auth_ok 1; } else { // 认证失败限制功能或进入保护模式 auth_ok 0; }这里有个设计上的取舍主机侧要不要存密钥如果主机 Flash 里的密钥被读出来整个认证体系就失效了。常见的做法是主机侧不存完整密钥而是存一个派生值或者用芯片的另一个槽位做二次验证。更安全的方案是用 ATSHA204 的CheckMac命令让芯片自己比较 MAC 值主机只读“通过/不通过”的结果这样主机侧完全不需要知道密钥。例程里演示的是前一种方式方便理解原理实际产品中建议用后一种。4. 避坑与常见问题那些手册上不会写但一定会遇到的坑4.1 读出来的数据全是 0xFF现象I2C 通信看起来正常ACK 也有但读响应时第一个字节就是 0xFF后面全是 0xFF。原因最常见的是等待时间不够。ATSHA204 收到命令后需要时间做 SHA-256 运算标准模式下典型 4ms最坏情况可能到 10ms 以上。如果主机在芯片还没处理完就去读芯片不会响应读到的就是总线空闲时的 0xFF。解决把delay_ms(5)改成delay_ms(10)试试如果好了就是这个问题。更稳妥的做法是轮询等待但 ATSHA204 不支持状态查询只能靠固定延时。另外检查一下 I2C 上拉电阻阻值太大比如 10k会导致上升沿变缓高速通信时数据出错。4.2 CRC 校验一直不过现象命令发出去有响应但 CRC 校验失败数据看起来“差不多对”但就是差几个字节。原因CRC 计算范围搞错了。命令包的 CRC 只算 Data 字段不包括 Word Address 和 Count响应包的 CRC 算 Count Data。另外 CRC-16 的多项式和初值也要确认ATSHA204 用的是 0x8005 多项式初值 0x0000跟常见的 Modbus CRC 不一样。解决拿手册里的示例数据手动算一遍 CRC跟代码算出来的对比。如果对不上检查多项式、初值、输入反转、输出反转这四个参数。我一般会写一个独立的 CRC 测试函数用已知数据验证通过后再集成到通信代码里。4.3 认证偶尔通过偶尔失败现象同一块板子有时候认证通过有时候失败没有规律。原因电源噪声或者 I2C 总线干扰。ATSHA204 在做 SHA-256 运算时电流会瞬间增大如果电源去耦电容不够电压会跌落导致芯片复位或运算出错。另外 I2C 走线太长、跟高频信号平行走线也会引入干扰。解决在芯片的 VCC 和 GND 之间加一个 0.1uF 的陶瓷电容尽量靠近芯片引脚。I2C 走线尽量短远离晶振、DCDC 电感这些干扰源。如果条件允许用示波器抓一下认证失败时的电源波形看有没有明显的跌落。4.4 密钥写进去读不出来以为芯片坏了现象用 Write 命令写密钥到 Slot返回成功但用 Read 命令读出来全是 0x00 或者 0xFF。原因这是正常行为。ATSHA204 的密钥槽位可以配置成“只写不读”模式写进去之后外部无法读出。这是芯片的安全特性不是故障。如果你需要验证密钥是否写对只能用认证命令间接验证不能直接读。解决写密钥之前先确认槽位的配置字确保你知道这个槽位是“可读”还是“不可读”。如果配成不可读写之前一定要确认密钥值正确因为写错了就改不了了除非用芯片的锁定功能但锁定后整个槽位就废了。我一般会在写密钥之前先用一个测试密钥走一遍完整认证流程确认无误后再写正式密钥。4.5 多颗芯片挂在同一总线上的地址冲突现象一条 I2C 总线上挂了两颗 ATSHA204通信时好时坏有时候读到的是另一颗的响应。原因ATSHA204 的 I2C 地址是固定的 0xC8不能通过硬件引脚修改。两颗芯片挂在一起必然冲突。解决用 I2C 多路复用器比如 PCA9548分时切换或者用 GPIO 控制每颗芯片的电源分时上电。如果成本敏感可以用一颗芯片的多个槽位来替代多颗芯片ATSHA204 有 16 个槽位大部分场景够用了。5. 二次开发与改造把例程变成产品代码的几个关键动作5.1 从裸机延时到 RTOS 任务封装例程里的delay_ms是裸机阻塞延时放在产品代码里会拖慢整个系统。如果项目用了 FreeRTOS 或者 RT-Thread应该把认证流程封装成一个独立任务用信号量或者事件标志来同步结果。// 认证任务在 RTOS 环境下运行 void AuthTask(void *pvParameters) { uint8_t retry 0; while (1) { if (ATSHA204_Authenticate() AUTH_OK) { xEventGroupSetBits(auth_event, AUTH_PASS_BIT); vTaskDelete(NULL); // 认证通过任务退出 } else { retry; if (retry 3) { // 连续失败进入保护模式 xEventGroupSetBits(auth_event, AUTH_FAIL_BIT); vTaskDelete(NULL); } vTaskDelay(pdMS_TO_TICKS(100)); // 重试间隔 } } }这样主线程可以继续做其他初始化认证结果通过事件组通知。注意 I2C 总线要加互斥锁如果其他任务也在用同一条 I2C 总线不加锁会出现数据错乱。5.2 密钥管理策略产品代码里最忌讳把密钥硬编码在源码里。我一般会这样做生产阶段用一个独立的烧录工具通过串口或者 SWD 接口把密钥传给 MCUMCU 再通过 I2C 写入 ATSHA204。密钥不落在源码和 Git 仓库里只在生产工装里临时存在。如果产品有多个型号可以用芯片的 Slot 配置来区分。比如 Slot 0 存主密钥Slot 1 存型号标识Slot 2 存生产日期。主机认证时先读 Slot 1 判断型号是否匹配再用 Slot 0 做认证。这样一套固件可以适配多个型号只需要在生产时写入不同的槽位数据。5.3 认证失败的降级策略认证失败不一定要直接“变砖”。根据产品形态可以设计分级降级第一次失败限制高级功能但保留基础功能连续失败三次进入安全模式只保留恢复接口如果检测到暴力破解尝试可以触发芯片的锁定功能永久禁用某些槽位。这里有个血泪经验降级策略一定要在开发阶段就设计好不要等到量产了再补。我见过一个项目认证失败后直接死循环结果产线上有一批芯片没焊好整批板子全变砖只能返工。后来改成失败后进入一个低功耗等待模式通过串口可以重新触发认证产线效率高了很多。5.4 用 CheckMac 命令替代主机侧计算前面提到主机侧存密钥有风险更安全的做法是用CheckMac命令。这个命令让 ATSHA204 自己比较主机发来的 MAC 值返回一个字节的结果0x00 表示匹配其他值表示不匹配。主机侧只需要生成挑战和期望的 MAC不需要在本地做 SHA-256 运算也就不需要在 Flash 里存密钥。// 使用 CheckMac 命令的认证流程 uint8_t checkmac_cmd[64]; checkmac_cmd[0] 0x28; // CheckMac 命令码 checkmac_cmd[1] 0x00; // 模式 checkmac_cmd[2] 0x00; // Slot 0 // ... 拼接 challenge、response、其他参数 // 发送命令后读 1 字节结果 if (resp[0] 0x00) { // 认证通过 }这个方案的代价是主机侧需要预先知道正确的 MAC 值通常是在生产阶段由上位机计算好写入 MCU 的配置区。虽然多了一道工序但安全性提升明显适合对防克隆要求高的产品。5.5 验证方法与调试技巧改完代码后怎么验证我一般分三步走。第一步用逻辑分析仪抓 I2C 波形确认命令包和响应包的字节流跟手册一致。第二步用已知密钥和挑战值做一次完整认证确认结果正确。第三步故意改错密钥或者挑战值确认认证失败路径也能正常走通。调试时如果遇到问题先把 I2C 速率降到 100kHz排除时序问题。然后用示波器看电源纹波排除电源问题。最后再检查代码逻辑。这个顺序能帮你快速定位问题出在硬件还是软件。从那以后我每次做加密芯片的集成都会先在开发板上把认证流程跑通再用逻辑分析仪抓一遍完整波形存档最后才移植到产品板上。这个习惯帮我省了很多返工时间。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站