如何使用OpenSSL验证TPM生成的签名并提取有效原始签名
解决TPM certify签名的OpenSSL验证问题
问题原因
验证失败的核心原因有两个:
tpm2_certify用-f plain输出的certify.signature不是纯签名,而是包含TPM2B_ATTEST证明数据和TPMT_SIGNATURE签名值的复合二进制结构,OpenSSL无法直接识别。- 错误将
sk.pub作为待验证数据,但AIK实际签名的是SK的公钥、属性等信息组成的TPM2B_ATTEST结构,而非sk.pub文件本身。
正确步骤
1. 重新生成分离的证明数据和纯签名
修改tpm2_certify命令,分开输出待签名的证明数据和纯签名:
sudo tpm2_certify -C ak.ctx -c sk.ctx -g sha256 -o certify.attest --signature certify.signature_raw -f plain
certify.attest:AIK签名的原始证明数据(包含SK的公钥、属性等信息)certify.signature_raw:纯RSA签名值,可被OpenSSL直接识别
2. 将TPM格式的AIK公钥转换为OpenSSL兼容的PEM格式
TPM导出的ak.pub是专属格式,需要转成PEM格式:
tpm2_pubkey -u ak.pub -f pem -o ak.pub.pem
3. 用OpenSSL验证签名
使用AIK的PEM公钥验证签名与证明数据的一致性:
openssl dgst -sha256 -verify ak.pub.pem -signature certify.signature_raw certify.attest
验证通过会输出 Verification OK,失败则输出 Verification Failure。
可选:从已生成的复合签名文件中提取数据
如果不想重新生成certify.signature,可以用tpm2_print解析结构并提取:
- 先查看复合文件的结构:
tpm2_print certify.signature
输出中会显示TPM2B_ATTEST的size值(比如0x150,十进制336)。
2. 提取证明数据(前4字节是size字段,加上实际数据长度):
dd if=certify.signature of=certify.attest bs=1 count=$((4+336))
- 提取纯签名(跳过证明数据的长度):
dd if=certify.signature of=certify.signature_raw bs=1 skip=$((4+336))
之后按步骤2、3进行验证即可。
验证通过后的意义
验证成功后,无TPM的服务器可以解析certify.attest获取SK的公钥和属性,结合AIK的可信性(AIK绑定到你的TPM),即可确认SK是与AIK同属一个TPM生成的。
内容的提问来源于stack exchange,提问作者Rabia Hussain
相关产品推荐
相关产品推荐

