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

Python加载十六进制DER格式公钥报无法反序列化密钥数据问题

报错核心原因
  • 你从机读旅行证件NFC芯片读取到的原始数据不是标准DER编码的RSA公钥,而是ICAO 9303规范定义的BER-TLV格式封装的公钥容器结构,不能直接传入load_der_public_key解析。
  • 你对起始字节的判断有误:6F是BER-TLV中文件/应用模板的标签,不是RSA DER公钥的起始标识(标准RSA公钥DER编码以30即SEQUENCE标签开头)。
  • 末尾补0的操作完全无效:454位十六进制字符对应227字节,其中包含了多层TLV的标签、长度位、公钥算法标识、权限参数等主动认证相关的元数据,并非纯公钥内容,补0只会破坏原有结构,不可能被标准DER解析器识别。
正确加载方法

你需要先按BER-TLV规则逐层解析外层封装结构,提取出公钥核心参数后再构造公钥对象,步骤如下:

  1. 解析原始字节流的TLV结构:
    • 跳过最外层6F模板的标签、长度字段,遍历内部子节点
    • 定位到标签为7F49的公钥信息模板节点,继续向下解析子字段
    • 提取两个核心参数:标签81对应的值为RSA公钥模数n(大端字节序,若首字节为前导0需剔除),标签82对应的值为RSA公钥指数e(主动认证场景下通常为010001即65537)
  2. 使用提取到的参数直接构造RSA公钥对象,参考实现代码:
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization

# 替换为TLV解析得到的真实模数、指数十六进制串
modulus_hex = "解析得到的公钥模数字段内容"
exponent_hex = "解析得到的公钥指数字段内容"

n = int(modulus_hex, 16)
e = int(exponent_hex, 16)

# 生成可直接用于验签的公钥对象
public_key = rsa.RSAPublicNumbers(e, n).public_key(default_backend())

# 如需导出为标准DER/PEM格式,可调用序列化接口
# der_bytes = public_key.public_bytes(
#     encoding=serialization.Encoding.DER,
#     format=serialization.PublicFormat.SubjectPublicKeyInfo
# )

注意:解析TLV结构时不要手动补0,IC卡返回的长度字段是精确值,如果出现长度不匹配问题,请优先检查芯片读取流程是否漏读字节、是否正确处理BER编码的长格式长度标识。

内容的提问来源于stack exchange,提问作者Ege Yıldırım

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 08:27:24