在Arduino(SAMD21)中使用strcpy等函数复制unsigned char失败求助
解决Adafruit Feather M0(SAMD21)上AES加密结果无法保存的问题
我之前在SAMD21平台上也碰到过类似的问题,结合你的描述,大概率是两个常见坑导致的:局部变量生命周期失效或者用字符串函数处理二进制加密数据,下面给你具体的解决思路和代码示例:
问题根源分析
- 局部数组的生命周期问题:如果你的
encrypt()函数里是在栈上创建局部char数组存储加密结果,函数执行完毕后栈内存会被系统回收覆盖,这时候你再去复制这个数组,拿到的已经是无效的垃圾数据了。 - 字符串函数不适合处理二进制数据:AES加密输出的是二进制字节流,其中很可能包含
\0(字符串结束符),strcpy/strncpy这类函数会在遇到\0时停止复制,导致你只能拿到部分加密结果。
具体解决步骤
1. 让加密函数直接写入外部数组(最优方案)
不要在encrypt()内部创建局部数组存储结果,而是把要保存结果的数组作为参数传入函数,让加密逻辑直接写入这个外部数组——这样数组的生命周期由调用方控制,不会出现函数返回后数据失效的问题。
示例代码:
// AES加密函数:直接将结果写入传入的output数组 void aes_encrypt(uint8_t* plaintext, uint8_t* output, size_t data_len, const uint8_t* key) { // 这里替换成你的AES-128/256加密逻辑 // 比如使用Crypto库的话: AES aes; aes.setKey(key, 16); // 16是AES-128的key长度,256的话传32 aes.encryptBlock(output, plaintext); } void loop() { // 定义生命周期覆盖整个loop的加密结果数组 uint8_t encrypted_result[16]; // AES块大小固定为16字节,不管128还是256 uint8_t plaintext[16] = "TestData12345678"; uint8_t aes_key[16] = "MySecretKey12345"; // AES-128的key // 直接加密到外部数组 aes_encrypt(plaintext, encrypted_result, sizeof(plaintext), aes_key); // 现在encrypted_result里就是有效的加密结果,可以正常存储或使用 // 比如打印验证: for(int i=0; i<16; i++){ Serial.print(encrypted_result[i], HEX); Serial.print(" "); } Serial.println(); }
2. 用memcpy代替字符串复制函数
如果因为某些原因必须在encrypt()内部使用局部数组,一定要:
- 把局部数组声明为
static,让它存储在全局内存(而非栈),函数返回后不会被释放; - 用
memcpy复制所有字节,不要用字符串函数。
示例代码:
void aes_encrypt(uint8_t* plaintext, uint8_t* output, size_t data_len, const uint8_t* key) { static uint8_t temp_encrypted[16]; // 静态数组,生命周期永久 AES aes; aes.setKey(key, 16); aes.encryptBlock(temp_encrypted, plaintext); // 用memcpy复制所有字节,不受\0影响 memcpy(output, temp_encrypted, data_len); }
3. 注意数组大小匹配
确保存储加密结果的目标数组大小足够:
- AES-128/256的块大小都是16字节,如果是ECB模式,加密后的数据长度和明文的块对齐长度一致;
- 如果用CBC/GCM等模式,还要预留IV(初始化向量)和校验值的空间,比如CBC模式需要额外16字节存储IV。
额外提醒(针对SAMD21)
Feather M0的栈空间有限(默认一般是2KB左右),如果在函数里创建大的局部数组很容易导致栈溢出,破坏其他变量的数据。所以尽量避免在函数内定义大数组,优先用全局数组或者传入外部数组的方式。
内容的提问来源于stack exchange,提问作者user5156141
相关产品推荐
相关产品推荐

