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

Solidity中字符串转Keccak256及ECC公钥转地址问题求助

Solidity ECC公钥转地址:差异原因与批量修复方案

结果差异的核心原因

问题出在字符串转字节数组的逻辑错误:

  • PubtoAddr接收的是已正确解析的ECC公钥原始字节数组(比如去掉0x前缀后,十六进制字符串对应的真实字节数据),后续通过keccak256哈希取后20字节生成地址,逻辑完全符合以太坊地址生成规范,结果正确。
  • PubtoAddr2直接用bytes(string)转换字符串公钥,会把整个字符串(包括常见的0x前缀)当成ASCII字符序列转成字节。例如字符串"0x04abc..."转成bytes后,前两个字节是0x30(对应字符'0')和0x78(对应字符'x'),这完全不是真实的公钥字节数据,后续哈希计算自然得到错误地址。

批量处理的代码修复

要实现字符串公钥批量转地址,必须先将十六进制字符串解析为正确的字节数组,再执行地址转换逻辑。以下是具体实现:

1. 实现十六进制字符串转字节数组的工具函数

这个函数自动兼容带/不带0x前缀的字符串:

function hexStringToBytes(string memory hexStr) internal pure returns (bytes memory) {
    bytes memory hexBytes = bytes(hexStr);
    require(hexBytes.length % 2 == 0 || (hexBytes.length >= 2 && hexBytes[0] == '0' && hexBytes[1] == 'x'), "Invalid hex string");
    
    uint256 startIndex = 0;
    if (hexBytes.length >= 2 && hexBytes[0] == '0' && hexBytes[1] == 'x') {
        startIndex = 2;
        require((hexBytes.length - startIndex) % 2 == 0, "Invalid hex length after 0x");
    }
    
    bytes memory result = new bytes((hexBytes.length - startIndex) / 2);
    for (uint256 i = 0; i < result.length; i++) {
        uint256 pos = startIndex + i * 2;
        uint8 high = hexCharToByte(hexBytes[pos]);
        uint8 low = hexCharToByte(hexBytes[pos + 1]);
        result[i] = bytes1((high << 4) | low);
    }
    return result;
}

function hexCharToByte(bytes1 c) internal pure returns (uint8) {
    if (c >= '0' && c <= '9') return uint8(c) - uint8('0');
    if (c >= 'a' && c <= 'f') return uint8(c) - uint8('a') + 10;
    if (c >= 'A' && c <= 'F') return uint8(c) - uint8('A') + 10;
    revert("Invalid hex character");
}

2. 修复字符串转地址函数及批量处理函数

基于上述工具函数,修改后的转换逻辑和批量处理函数如下:

function pubToAddrFromStr(string memory pubKeyStr) public pure returns (address) {
    bytes memory pubKeyBytes = hexStringToBytes(pubKeyStr);
    // 验证ECC公钥长度(标准非压缩公钥为65字节:0x04开头+32字节X坐标+32字节Y坐标)
    require(pubKeyBytes.length == 65, "Invalid ECC public key length");
    
    bytes32 hash = keccak256(abi.encodePacked(pubKeyBytes));
    return address(uint160(uint256(hash)));
}

function batchPubToAddr(string[] memory pubKeyStrs) public pure returns (address[] memory) {
    address[] memory results = new address[](pubKeyStrs.length);
    for (uint256 i = 0; i < pubKeyStrs.length; i++) {
        results[i] = pubToAddrFromStr(pubKeyStrs[i]);
    }
    return results;
}

关键说明

  • 工具函数hexStringToBytes会先判断字符串是否带0x前缀,再将每两个十六进制字符解析为一个字节,还原出真实的公钥字节数组。
  • 地址生成逻辑严格遵循以太坊规范:对完整公钥字节数组做keccak256哈希,再通过uint160截断哈希值的后20字节,转换为最终地址。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 16:33:23