You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ESP-IDF中从ATECC608B获取64字节ECDSA签名

问题描述

尝试从buf中获取ATECC608B签名后的64字节ECDSA签名,但返回的大小为72字节,有时会根据hash的大小在70-72字节间变化。签名与验证功能可正常运行,但无法提取出64字节的签名。

相关签名生成代码:

ESP_LOGI(TAG, " Generating ECDSA Signature...");
ret = mbedtls_pk_sign(&pkey, MBEDTLS_MD_SHA256, hash, 0, buf, MBEDTLS_MPI_MAX_SIZE, &olen,
                          mbedtls_ctr_drbg_random, &ctr_drbg);
if (ret != 0)
{
  ESP_LOGI(TAG, " failed ! mbedtls_pk_sign returned -0x%04x", -ret);
  goto exit;
}
ESP_LOGI(TAG, " ok");

签名打印代码:

ESP_LOGI(TAG, "Signature:");
ESP_LOGW(TAG, "%i", olen);
ESP_LOG_BUFFER_HEX_LEVEL(TAG, buf, olen, ESP_LOG_WARN);

日志输出:

I (649) atecc_example: Signature:
W (649) atecc_example: 72
W (649) atecc_example: 30 46 02 21 00 f6 8b 21 9f 60 47 d3 f7 99 e0 a4
W (649) atecc_example: a1 0b df 4d d3 78 36 3e d1 0c 2c 34 4c 14 39 6d
W (659) atecc_example: 2f 5c cb 43 bc 02 21 00 bd 20 87 ed fa fa 81 db
W (669) atecc_example: 02 df 82 0e 3c 3d 5a 35 c3 6b c5 0d cb 35 d2 e1
W (679) atecc_example: 7b 3a 3a ca 21 59 6b cc

原因分析

mbedtls_pk_sign返回的是ASN.1 DER编码格式的ECDSA签名,不是原始的64字节(r,s)拼接格式。DER编码的结构如下:

  • 0x30:SEQUENCE类型标签
  • 后续字节:整个签名的总长度
  • 0x02:INTEGER类型标签(对应签名的r值)
  • 后续字节:r值的字节长度(31或33字节,当r最高位为1时,会添加0x00前缀避免被解析为负数)
  • r的实际字节数据
  • 0x02:INTEGER类型标签(对应签名的s值)
  • 后续字节:s值的字节长度
  • s的实际字节数据

这就是签名长度在70-72字节波动的原因:当r或s的最高位为0时,会省略前缀0x00,整体长度减少2字节。

解决方案

方案1:使用mbedtls API解析

通过mbedtls提供的接口直接提取r和s值,再拼接成64字节原始签名:

#include "mbedtls/ecdsa.h"

// 初始化上下文
mbedtls_ecdsa_context ecdsa_ctx;
mbedtls_ecdsa_init(&ecdsa_ctx);
mbedtls_mpi r, s;
mbedtls_mpi_init(&r);
mbedtls_mpi_init(&s);

// 从PK上下文导入密钥信息
if(mbedtls_ecdsa_from_pk(&ecdsa_ctx, &pkey) != 0) {
    // 处理错误逻辑
}

// 解析DER格式签名到r和s
if(mbedtls_ecdsa_read_signature(&ecdsa_ctx, buf, olen, &r, &s) != 0) {
    // 处理错误逻辑
}

uint8_t raw_signature[64] = {0};
// 将r转为32字节大端格式,填充到前32位
mbedtls_mpi_write_binary(&r, raw_signature, 32);
// 将s转为32字节大端格式,填充到后32位
mbedtls_mpi_write_binary(&s, raw_signature + 32, 32);

// 清理资源
mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s);
mbedtls_ecdsa_free(&ecdsa_ctx);

方案2:手动解析DER结构

根据ASN.1 DER规则手动提取r和s的有效数据:

  1. 跳过开头的0x30 xx(SEQUENCE标签和长度)
  2. 读取0x02 xx(r的INTEGER标签和长度):
    • 如果长度是33,跳过第一个字节(0x00前缀),取后面32字节作为r
    • 如果长度是31,直接取31字节,前面补1个0x00凑成32字节
  3. 读取0x02 xx(s的INTEGER标签和长度),按同样规则提取32字节的s
  4. 将r和s拼接得到64字节原始签名

内容的提问来源于stack exchange,提问作者damo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 04:25:16