如何在 tron 中使用 ecrecover 获取正确的地址

how to get correct address using ecrecover in tron

solidity 合约代码中通过 ecrecover 获取签名者地址的代码块在以太坊上运行良好,但在 TRON 中它返回错误地址 我的合约方代码是

    function validate(string memory strTest,uint8 v, bytes32 r, bytes32 s) public view returns(address){
      bytes32 prefixedHash = keccak256(strTest);
      return ecrecover(keccak256(prefixedHash),v,r,s);
      // return ecrecover(prefixedHash,v,r,s):
   }

dapp 端代码是

    msg = tronWeb.sha3("this is test string");
    var signature = await tronWeb.trx.sign(msg);
    var r=signature.substr(0,66);
    var s= "0x" + signature.substr(66,64);
    var v="0x" + signature.substr(signature.length-2);
    retValue = await thisContractInstance.validate("this is test string",v,r,s).call();

但在这两种情况下(一种情况在合同端代码中被注释)在 TRON shasta 网络中得到错误的签名者地址

您是要签署字符串还是签署交易? @阿什温

我在对字符串进行签名时遇到了同样的问题,下面的内容帮助了我。 Tronweb 使用不同的方法来签署交易和签署字符串。

1) 交易可以参考这个:https://github.com/TRON-US/tronweb/blob/master/src/lib/trx.js#L651,

2) 关于签名字符串,它使用

ethers.utils.SigningKey.signDigest ()

of Ethereum:https://docs.ethers.io/ethers.js/html/api-advanced.html?highlight=signingkey#id8,请注意最后的 v 字节将始终为 Solidity 标准化(27 或28)

如果您尝试签署此处提到的 msg

var signature = await tronWeb.trx.sign(msg);

你可以关注第二个。

您可以参考文章https://medium.com/@coredevs/verifying-elliptic-curve-digital-signature-with-tron-smart-contract-5d11347e7b5b。 这将有助于完成对字符串的签名, 连同@Aldo 提供的上述答案。 编码愉快。

摘自:

智能合约代码:

contract Verifier {
    function recoverAddr(bytes32 msgHash, uint8 v, bytes32 r, bytes32 s) returns (address) {
        return ecrecover(msgHash, v, r, s);
    }

    function isSigned(address _addr, bytes32 msgHash, uint8 v, bytes32 r, bytes32 s) returns (bool) {
        return ecrecover(msgHash, v, r, s) == _addr;
    }
}

客户代码:

const ethers = tronWeb.utils.ethersUtils;
let contract = await tronWeb.contract().at(contract_address);
let signingKey = new ethers.SigningKey(tronWeb.defaultPrivateKey);

let message = "This is some message";
let messageBytes = ethers.toUtf8Bytes(message);
let messageDigest = ethers.keccak256(messageBytes);

let signature = signingKey.signDigest(messageDigest);
let hexAddress = await contract.recoverAddr(messageDigest, signature.v, signature.r, signature.s).call();

根据https://github.com/tronprotocol/tronweb/blob/1435436f83b910f19e9205998e348ea093732ce5/src/lib/trx.js#L629

tronWeb.trx.sign() 执行以下操作

  1. 传入32个字节的hash
  2. 需要先添加前缀"\x19TRON Signed Message:\n32"
  3. 使用 keccak256 算法生成新的哈希值
  4. 签名(TronLink 或私钥)

因此,在使用solidity的ecrecover时,将第3步的hash传入

function getHash(hash) {

    hash = hash.replace(/^0x/, '')

    if (!tronWeb.utils.isHex(hash)) {
        return
    }

    if (hash.length !== 64) {
        return
    }

    const {
        keccak256,
        toUtf8Bytes
    } = tronWeb.utils.ethersUtils

    const hashArray = tronWeb.utils.code.hexStr2byteArray(hash)

    const TRX_MESSAGE_PREFIX = toUtf8Bytes('\x19TRON Signed Message:\n32')

    return keccak256([
        ...TRX_MESSAGE_PREFIX,
        ...hashArray
    ])
}