从HSM获取签名:Hedera自定义签名交易执行报错问题
问题排查:自定义HSM签名Hedera交易失败的原因
核心问题:签名对象错误
你当前代码对交易哈希(transaction.getTransactionHash())进行签名,但Hedera网络要求签名的是冻结后的完整交易字节流,而非交易哈希。这就是SDK自带sign()方法能成功的原因——它内部是对正确的交易字节做签名。
具体修正步骤
- 替换签名输入数据:把
transaction.getTransactionHash()换成transaction.toBytes() - 你的Ed25519签名算法实现本身是正确的,仅需调整签名对象即可
修改后的关键代码片段
// 替换获取交易哈希的逻辑,改为获取冻结后的交易字节流 byte[] transactionBytes = transaction.toBytes(); // 使用交易字节流执行签名 transaction.addSignature(fundedPrivateKey.getPublicKey(), this.sign(transactionBytes, fundedPrivateKey));
补充说明
- Hedera节点的验证逻辑要求签名必须对应完整的交易序列化字节,这样节点才能重新序列化交易并验证签名匹配性。
- 你代码里的本地签名验证能通过,是因为确实正确签名了交易哈希,但这和Hedera节点的验证要求不匹配,所以提交后会报错。
完整修正后的testSigner方法
public void testSigner() throws PrecheckStatusException, TimeoutException, CryptoException, ReceiptStatusException { PrivateKey fundedPrivateKey = PrivateKey.fromStringED25519(MY_PRIVATE_KEY); Client client = Client.forTestnet(); AccountId fundedAccountId = AccountId.fromString("0.0.3672483"); client.setOperator(fundedAccountId, fundedPrivateKey); PrivateKey emptyPrivateKey = PrivateKey.generateED25519(); PublicKey publicKey = emptyPrivateKey.getPublicKey(); TransactionResponse newAccountCreateTX = new AccountCreateTransaction() .setKey(publicKey) .setInitialBalance(Hbar.from(0)) .execute(client); client.setOperator(newAccountCreateTX.getReceipt(client).accountId, emptyPrivateKey); // Create a transaction that needs to be signed with the fundedPrivateKey assert client.getOperatorAccountId() != null; TransferTransaction transaction = new TransferTransaction() .addHbarTransfer(client.getOperatorAccountId(), Hbar.from(10)) .addHbarTransfer(fundedAccountId, Hbar.from(-10)) .setTransactionId(TransactionId.generate(fundedAccountId)) .freezeWith(client) // .sign(fundedPrivateKey) .sign(emptyPrivateKey); // 替换为获取冻结后的交易字节流 byte[] transactionBytes = transaction.toBytes(); // Add the signature to the transaction transaction.addSignature(fundedPrivateKey.getPublicKey(), this.sign(transactionBytes, fundedPrivateKey)); // Execute the transaction TransactionResponse response = transaction.execute(client); TransactionId transactionId = response.transactionId; System.out.println("Transaction ID: " + transactionId); }
内容的提问来源于stack exchange,提问作者Micha Roon
相关产品推荐
相关产品推荐

