以太坊交易签名实战:token-core-android 中 RLP 编码与 EIP-155 全流程

发布时间:2026/8/19 19:51:30
以太坊交易签名实战:token-core-android 中 RLP 编码与 EIP-155 全流程 以太坊交易签名实战token-core-android 中 RLP 编码与 EIP-155 全流程【免费下载链接】token-core-androida blockchain private key management library on android项目地址: https://gitcode.com/gh_mirrors/to/token-core-android对于刚接触区块链开发的 Android 工程师来说以太坊交易签名往往是一道绕不开的门槛非对称加密、Keccak-256、RLP 编码、EIP-155……一系列名词扑面而来。而token-core-android正是一个专注于区块链私钥管理与离线签名的 Android 库它用不到两百行核心代码把构造交易 → 编码 → 签名 → 广播的完整链路封装得清晰易懂。本文将以源码为线索带你一步步拆解以太坊交易签名全流程彻底搞懂 RLP 编码与 EIP-155 重放保护背后的原理。一次以太坊交易签名到底经历了哪几步以太坊交易签名绝不是给字符串加个密这么简单。在 token-core-android 中一次完整的签名流程分为四个阶段RLP 编码把 nonce、gasPrice、gasLimit、to、value、data 六个字段按固定顺序编码为字节流哈希与 ECDSA 签名对编码结果做 Keccak-256 哈希再用私钥生成 (v, r, s) 签名EIP-155 二次编码把链 ID 折叠进 v 值重新 RLP 编码得到可广播的原始交易计算交易哈希对签名后的交易再做一次 Keccak-256得到可查询的 txHash。这四步分别对应四个核心类下面逐一深入。第一步交易字段的 RLP 编码规则RLPRecursive Length Prefix是以太坊底层通用的序列化格式它的规则很简单单个字节且值在 0x00~0x7f 之间直接原样输出长度不超过 55 字节的字符串前缀0x80 长度更长的字符串前缀标记长度字段本身的字节数列表List在拼接所有元素后前缀0xc0 总长度。token-core-android 把这三条规则完整实现在 RlpEncoder.java 中配合 RlpString.java 与 RlpList.java 两个数据类型构成一套简洁的 RLP 工具箱。// RlpEncoder.java 核心逻辑 public static byte[] encode(RlpType value) { if (value instanceof RlpString) { return encodeString((RlpString) value); } else { return encodeList((RlpList) value); } }第二步六个字段如何按顺序入列以太坊规定交易的 RLP 结构必须严格按nonce → gasPrice → gasLimit → to → value → data排列。在 EthereumTransaction.java 的asRlpValues()方法中你可以看到几个非常讲究的细节to 地址为空时合约创建交易编码为空字符串而不是数字 0to 地址带前导零时必须按字节原样编码防止被当作数值截断data 字段需要先从十六进制字符串还原成字节数组再编码非负数、零值都有专门的处理分支避免出现多余的前导零。这些细节正是看着简单、做起来容易出错的地方token-core-android 已经帮你全部处理妥当。第三步Keccak-256 哈希与 ECDSA 可恢复签名RLP 编码完成后签名正式开始。核心逻辑在 EthereumSign.java 中static SignatureData signMessage(byte[] message, byte[] prvKeyBytes) { ECKey ecKey ECKey.fromPrivate(prvKeyBytes); byte[] messageHash Hash.keccak256(message); return signAsRecoverable(messageHash, ecKey); }这里有两个关键点Keccak-256与常见的 SHA-256 并不相同项目在 Hash.java 中提供了原生实现可恢复签名recoverable signature签名结果会额外携带 recovery ID用于反推公钥这也是后续ecRecover验签、恢复地址的基础。signAsRecoverable()会遍历 0~3 四个候选 ID找到能恢复出当前公钥的那一个最终得到 (v, r, s) 三件套封装在 SignatureData.java 中。第四步EIP-155 如何防止跨链重放攻击早期以太坊交易只有 v 27/28 两种取值同一笔签名交易可以原封不动地在其他链比如 ETC上重放。EIP-155 提案的解决方案是把链 ID 编码进 v 值。在createEip155SignatureData()方法中可以看到那条经典的公式private static SignatureData createEip155SignatureData(SignatureData signatureData, int chainId) { int v signatureData.getV() (chainId * 2) 8; return new SignatureData(v, signatureData.getR(), signatureData.getS()); }即v 35 chainId * 2 recoveryId其中 recoveryId 范围为 0~1。这样一来为以太坊主网签名的交易其 v 值天然与以太坊经典ETC不兼容重放攻击被从数学上杜绝。项目在 ChainId.java 中预置了常用链 ID以太坊主网 1、Ropsten 3、Kovan 42、ETC 主网 61 等直接引用即可。 冷知识EIP-155 签名要求先带链 ID 编码一次此时 v 占位为链 ID、r/s 为空哈希签名后再把真实 v 值代入重新编码。这个过程在signTransaction(int chainId, byte[] privateKey)中完整呈现两轮编码一步不差。第五步得到可广播的 signedTx 与 txHash签名与二次编码完成后signTransaction()返回一个 TxSignResult.java 对象包含两个关键字段signedTx十六进制编码的原始交易Raw Transaction直接交给节点或钱包广播txHash对 signedTx 再做一次 Keccak-256 得到的交易哈希用于在区块浏览器中查询交易状态。String calcTxHash(String signedTx) { return NumericUtil.prependHexPrefix(Hash.keccak256(signedTx)); }项目在 EthereumTransactionTest.java 中保留了 EIP-155 官方测试向量可以用固定私钥0x4646...4646验证你的实现输出是否与预期完全一致非常适合作为自测基准。在 Android 项目中如何快速落地在真实 App 中私钥通常保存在加密 keystore 中因此对外暴露的 API 是密码 钱包而非裸私钥EthereumTransaction tx new EthereumTransaction( nonce, gasPrice, gasLimit, toAddress, value, data); TxSignResult result tx.signTransaction( ChainId.ETHEREUM_MAINNET, password, ethereumWallet); String signedTx result.getSignedTx(); // 广播用 String txHash result.getTxHash(); // 查询用私钥的加解密在 Wallet.java 的decryptMainKey()中完成签名全程在本地设备离线进行私钥永不触网——这也是移动钱包安全性的根基。总结一条链路四个关键文件交易模型与 EIP-155 逻辑EthereumTransaction.javaKeccak-256 哈希与 ECDSA 签名EthereumSign.javaRLP 编码实现RlpEncoder.java签名结果载体SignatureData.java以太坊交易签名并不神秘它无非是固定字段顺序 RLP 序列化 Keccak-256 哈希 ECDSA 签名 链 ID 防重放的组合拳。借助 token-core-android 这份简洁的开源实现你不仅能快速在自己的 Android 项目中接入离线签名能力更能通过源码真正吃透底层原理为后续深入智能合约交互、多链钱包开发打下扎实基础。【免费下载链接】token-core-androida blockchain private key management library on android项目地址: https://gitcode.com/gh_mirrors/to/token-core-android创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考