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

使用tpm2-pytss进行TPM2签名时报哈希算法不支持错误

问题:使用tpm2-pytss进行TPM2 ECDSA签名失败,错误码0x000002c3

问题背景

已通过终端命令创建并持久化ECC密钥(句柄0x81000000),终端签名流程可正常运行,但使用Python的tpm2-pytss库复现时,签名步骤报错:tpm:parameter(2):hash algorithm not supported or not appropriate,且密钥的签名方案显示为null。

终端工作流程

tpm2_createprimary -C e -g sha256 -G ecc -c primary.ctx -a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|sign"
tpm2_evictcontrol -C o -c primary.ctx 0x81000000 # 持久化密钥

echo "data to sign" > data.in.raw # 创建原始数据
sha256sum data.in.raw | awk '{ print "000000 " $1 }' | xxd -r -c 32 > data.in.digest # 生成摘要
tpm2_sign -Q -c 0x81000000 -g sha256 -d -f plain -o data.out.signed data.in.digest

出错的Python代码

import tpm2_pytss

# Initialize TPM
tpm = tpm2_pytss.ESAPI(tcti=None)
tpm.startup(tpm2_pytss.TPM2_SU.CLEAR)

# Handle for the persistent key
handle = tpm.tr_from_tpmpublic(0x81000000)

# Inspect public key data
public_data, _, _ = tpm.read_public(handle)
public_area = public_data.publicArea
ecc_params = public_area.parameters.eccDetail

print(f"Key Type: {public_area.type}")
print(f"Name Algorithm: {public_area.nameAlg}")
print(f"Attributes: {public_area.objectAttributes}")
print(f"ECC Curve: {ecc_params.curveID}")
print(f"ECC Scheme: {ecc_params.scheme.scheme}")

# Data to be signed
data = b"data to sign"

# Generate digest and validation ticket
digest, validation = tpm.hash(
    data,
    hash_alg=tpm2_pytss.TPM2_ALG.SHA256,
    hierarchy=tpm2_pytss.ESYS_TR.NULL
)

# Set up ECDSA signing scheme
signing_scheme = tpm2_pytss.TPMT_SIG_SCHEME(
    scheme=tpm2_pytss.TPM2_ALG.ECDSA,
    details=tpm2_pytss.TPMU_SIG_SCHEME()  # Empty scheme for ECDSA
)

# Attempt to sign the digest using TPM
try:
    signature = tpm.sign(
        handle,         # Key handle in TPM
        digest,         # Generated digest
        in_scheme=signing_scheme,  # ECDSA signing scheme
        validation=validation  # Validation ticket
    )
    print(f"Generated Signature: {signature}")
except tpm2_pytss.TSS2_Exception as e:
    print(f"Error while signing: {e}")

错误输出

Key Type: ecc
Name Algorithm: sha256
Attributes: fixedtpm|fixedparent|sensitivedataorigin|userwithauth|sign
ECC Curve: nist_p256
ECC Scheme: null
WARNING:esys:src/tss2-esys/api/Esys_Sign.c:314:Esys_Sign_Finish() Received TPM Error 
ERROR:esys:src/tss2-esys/api/Esys_Sign.c:108:Esys_Sign() Esys Finish ErrorCode (0x000002c3) 
Error while signing: tpm:parameter(2):hash algorithm not supported or not appropriate

错误原因分析

  1. 密钥创建时未指定绑定哈希算法的签名方案,导致密钥的scheme字段为null,TPM要求签名时必须明确指定哈希算法与签名方案的绑定关系。
  2. Python代码中创建的TPMT_SIG_SCHEME仅指定了ECDSA方案,但未配置对应的哈希算法细节,TPM无法识别有效的签名参数组合。
  3. 终端的tpm2_sign命令通过-g sha256参数自动补全了签名方案的哈希算法配置,而Python代码需要显式完成这一步。

解决方案

方案1:修正密钥创建命令(可选,固定签名方案)

如果希望密钥默认绑定SHA256的ECDSA方案,创建主密钥时显式指定签名方案:

tpm2_createprimary -C e -g sha256 -G ecc:ecdsa-sha256 -c primary.ctx -a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|sign"

重新持久化密钥后,密钥的scheme会显示为ecdsa,后续签名时可省略部分配置。

方案2:修正Python代码的签名方案配置

即使密钥scheme为null,只要签名时显式指定包含哈希算法的完整签名方案即可。修改签名方案的创建代码:

# 正确配置ECDSA签名方案,绑定SHA256哈希算法
signing_scheme = tpm2_pytss.TPMT_SIG_SCHEME(
    scheme=tpm2_pytss.TPM2_ALG.ECDSA,
    details=tpm2_pytss.TPMU_SIG_SCHEME(
        ecdsa=tpm2_pytss.TPMT_SIG_SCHEME_ECDSA(
            hashAlg=tpm2_pytss.TPM2_ALG.SHA256
        )
    )
)

方案3:验证摘要与验证票据的设置

当前代码中的tpm.hash调用是正确的:

  • 若使用预计算的外部摘要(类似终端的-d参数),可跳过tpm.hash直接传入32字节的SHA256摘要值,此时验证票据可设为None,但需在sign调用中指定hierarchy参数。
  • 当前生成的验证票据有效,无需修改。

完整修正后的Python代码

import tpm2_pytss

# Initialize TPM
tpm = tpm2_pytss.ESAPI(tcti=None)
tpm.startup(tpm2_pytss.TPM2_SU.CLEAR)

# Handle for the persistent key
handle = tpm.tr_from_tpmpublic(0x81000000)

# Inspect public key data
public_data, _, _ = tpm.read_public(handle)
public_area = public_data.publicArea
ecc_params = public_area.parameters.eccDetail

print(f"Key Type: {public_area.type}")
print(f"Name Algorithm: {public_area.nameAlg}")
print(f"Attributes: {public_area.objectAttributes}")
print(f"ECC Curve: {ecc_params.curveID}")
print(f"ECC Scheme: {ecc_params.scheme.scheme}")

# Data to be signed
data = b"data to sign"

# Generate digest and validation ticket
digest, validation = tpm.hash(
    data,
    hash_alg=tpm2_pytss.TPM2_ALG.SHA256,
    hierarchy=tpm2_pytss.ESYS_TR.NULL
)

# 正确配置ECDSA签名方案,绑定SHA256哈希算法
signing_scheme = tpm2_pytss.TPMT_SIG_SCHEME(
    scheme=tpm2_pytss.TPM2_ALG.ECDSA,
    details=tpm2_pytss.TPMU_SIG_SCHEME(
        ecdsa=tpm2_pytss.TPMT_SIG_SCHEME_ECDSA(
            hashAlg=tpm2_pytss.TPM2_ALG.SHA256
        )
    )
)

# Attempt to sign the digest using TPM
try:
    signature = tpm.sign(
        handle,         # Key handle in TPM
        digest,         # Generated digest
        in_scheme=signing_scheme,  # 完整的ECDSA签名方案
        validation=validation  # Validation ticket
    )
    print(f"Generated Signature: {signature}")
except tpm2_pytss.TSS2_Exception as e:
    print(f"Error while signing: {e}")

针对问题的解答

  1. 如何在tpm2-pytss中为TPM2_ALG.ECDSA密钥正确指定签名方案?
    需要创建包含哈希算法细节的TPMT_SIG_SCHEME对象:通过TPMU_SIG_SCHEME的ecdsa字段,指定TPMT_SIG_SCHEME_ECDSA并设置对应的哈希算法(如SHA256),不能使用空的TPMU_SIG_SCHEME。

  2. 摘要或验证票据的设置是否存在问题?
    当前的tpm.hash调用是正确的,生成的摘要和验证票据有效。若使用预计算的外部摘要,需确保摘要长度与哈希算法匹配(SHA256为32字节),此时验证票据可设为None,但需在sign调用中补充hierarchy参数。

  3. 创建密钥时是否需要显式设置方案以支持ECDSA?
    不是必须,但显式设置(如-G ecc:ecdsa-sha256)会让密钥默认绑定该签名方案,后续签名时可省略部分配置。如果密钥scheme为null,只要签名时显式指定完整的签名方案即可正常工作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 01:48:12