Logo
新用户订阅 RPC,首月享 6.5 折优惠查看优惠
OnFinality Learn
基础设施与运维阅读约 11 分钟

非托管硬件钱包:架构、签名工作流与验证

一份技术指南,说明非托管硬件钱包如何隔离密钥、签名交易并连接 RPC 基础设施,并提供可复现的验证流程。

TL;DR

非托管硬件钱包是一种专用签名设备,它将私钥存储在隔离元件中,并且每笔交易都需要物理确认,而主机电脑或手机只负责广播已签名的载荷。本文解释密钥隔离模型、签名与广播工作流、设备如何与 RPC 端点交互,以及如何验证交易是在本地签名并正确传输的。文章还涵盖故障排查、权衡取舍和可复现的测量流程,让你能够验证自己的设置,而不是依赖厂商声明。

直接答案与范围

非托管硬件钱包是一种物理设备,它在安全元件或隔离微控制器中生成并存储私钥,绝不将助记词暴露给主机操作系统。主机(桌面应用、浏览器扩展或移动应用)构建未签名交易,将其发送到设备进行审核,并接收回已签名的载荷。然后主机通过 RPC 端点将该已签名载荷广播到区块链节点。

本文涵盖架构、签名工作流、如何验证签名发生在设备上、设备的主机软件如何与 RPC 基础设施通信,以及如何排查常见故障。它不推荐特定的硬件厂商或特定的 RPC 提供商;如需具体的端点选择,请使用 RPC Assistant。

  • 假设你已拥有或正在评估支持你所关注链的硬件钱包。
  • 假设你基本熟悉公钥/私钥对和交易广播。
  • 所有代码均使用 RPC_URL 和 PRIVATE_KEY 等占位符;切勿将真实助记词粘贴到任何脚本中。

前提条件与假设

在运行任何验证流程之前,请确认设备固件为最新版本、厂商配套应用是从官方来源安装的,并且你在测试网或小额主网账户上有一个有资金的测试账户。你还需要目标链的可用的 RPC 端点;你可以在 OnFinality 网络页面 查看支持的网络,并通过 RPC API 服务 比较端点选项。

以下流程假设主机装有 Python 3.10+ 或 Node.js 18+,并且你可以安装软件包。它们不假设任何特定的硬件型号,因为签名接口因厂商而异。在需要厂商特定步骤的地方,流程描述的是要查找什么,而不是硬编码的命令。

密钥隔离模型:设备实际保护什么

非托管硬件钱包的安全价值来自将密钥材料与通用计算机分离。设备在内部生成熵、派生助记词,并将其存储在受保护的内存中。在正常操作期间,主机永远不会看到助记词。当需要签名交易时,主机将未签名交易和派生路径发送到设备;设备在自己的屏幕上显示目标地址、金额和费用,用户进行物理确认。

该模型可防止主机上试图窃取密钥的恶意软件,但不能防止用户批准恶意交易。它也不能防止对设备本身的供应链攻击,这就是固件验证和从官方渠道购买很重要的原因。设备是签名边界,而不是完整的安全系统。

  • 私钥保留在安全元件或隔离 MCU 内。
  • 主机仅接收签名和公钥。
  • 物理确认将已签名载荷与用户在设备屏幕上看到的内容绑定。
  • 助记词备份仍是用户的责任,并且是唯一的恢复点。

端到端签名与广播工作流

典型流程有六个阶段。首先,主机应用向 RPC 端点查询账户 nonce、余额和当前 gas 参数。其次,主机构建未签名交易对象。第三,主机序列化该对象,并通过 USB、蓝牙或二维码通道发送到硬件钱包。第四,设备显示解码后的交易并等待物理批准。第五,设备返回签名。第六,主机附加签名,并通过 RPC 端点广播原始已签名交易。

关键特性是 RPC 端点只能看到已签名交易。它看不到私钥或助记词。这意味着 RPC 提供商的信任仅限于可用性和正确的链数据,而不涉及资金托管。这一区别正是自托管硬件钱包可以与第三方 RPC 基础设施配对而不放弃密钥控制的原因。

curl -s -X POST RPC_URL \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionCount","params":["0xYOUR_ADDRESS","pending"]}'

构建供设备审核的未签名交易

主机必须构建一笔设备能够明确解码和显示的交易。使用显式字段而非默认值,并验证链 ID 与你打算使用的网络匹配。下面的示例使用占位符 RPC_URL 和占位符地址;它只读取链数据,不签名任何内容。

交易准备好后,将其传递给你所用厂商的签名库或 CLI。具体调用因厂商而异,但输入始终相同:未签名交易对象加上派生路径。输出是签名或已签名的原始交易。在此步骤中,切勿记录助记词或私钥。

import json, urllib.request

RPC_URL = "RPC_URL"
ADDRESS = "0xYOUR_ADDRESS"

def rpc(method, params):
    payload = json.dumps({"jsonrpc":"2.0","id":1,"method":method,"params":params}).encode()
    req = urllib.request.Request(RPC_URL, data=payload, headers={"Content-Type":"application/json"})
    with urllib.request.urlopen(req, timeout=15) as resp:
        return json.loads(resp.read())["result"]

nonce = rpc("eth_getTransactionCount", [ADDRESS, "pending"])
chain_id = rpc("eth_chainId", [])
gas_price = rpc("eth_gasPrice", [])
print({"nonce": nonce, "chain_id": chain_id, "gas_price": gas_price})

验证签名发生在设备上

验证是一个测量过程,而不是信任练习。目标是确认三件事:签名由设备生成、已签名载荷与设备显示的内容匹配、广播被网络接受。你可以通过从签名中恢复签名者地址并将其与设备的公开地址进行比较,来在不广播的情况下验证前两项。

对测试网交易运行以下流程。记录恢复的地址、设备显示的地址和广播交易哈希。正确的设置会产生与设备地址完全匹配的恢复地址,以及出现在正确链区块浏览器上的交易哈希。

  • 恢复的签名者地址等于设备的公开地址。
  • 设备屏幕显示与主机交易相同的目标地址、金额和费用。
  • 广播返回交易哈希,而不是错误。
  • 该哈希在包含后可在正确链的浏览器上看到。

你自己的验证运行结果表

使用下表记录你自己的测量结果。不要填写本文中的值;该表是一个模板。每一行都应来自你自己的测试网或小额主网运行,并且列出了通过标准,以便你在没有外部基准的情况下判断结果。

检查项记录内容通过标准
设备地址设备显示的地址与主机派生的地址匹配
恢复的签名者从签名中恢复的地址等于设备地址
显示的目标地址设备屏幕上显示的目标地址等于主机交易的目标地址
显示的金额设备屏幕上显示的金额等于主机交易的金额
广播结果交易哈希或错误返回哈希并在浏览器上可见
RPC 延迟eth_getTransactionCount 的往返时间在重复调用中保持稳定

主机软件如何与 RPC 基础设施通信

硬件钱包本身通常不发起网络请求。配套应用或浏览器扩展才会。这意味着 RPC 可靠性、速率限制和链正确性是主机软件配置的属性,而不是设备的属性。如果你的钱包应用允许自定义 RPC URL,你可以将其指向专用端点以获得更好的一致性;有关容量规划,请参阅 专用节点选项 和 RPC 定价页面。

对于多链投资组合,主机可能会按链切换 RPC 端点。在签名前验证每条链的端点返回预期的链 ID。链 ID 不匹配是交易失败或误发的最常见原因之一,并且可以在签名前通过一次 RPC 调用检测到。

const RPC_URL = "RPC_URL";

async function checkChain(expectedChainId) {
  const res = await fetch(RPC_URL, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_chainId", params: [] })
  });
  const { result } = await res.json();
  const actual = parseInt(result, 16);
  if (actual !== expectedChainId) {
    throw new Error(`Chain mismatch: expected ${expectedChainId}, got ${actual}`);
  }
  return actual;
}

checkChain(1).then(console.log).catch(console.error);

排查常见故障

大多数硬件钱包故障分为四类:连接、链不匹配、nonce 或费用问题以及显示不匹配。连接故障通常意味着设备已锁定、线缆或蓝牙配对已过期,或者配套应用缺少权限。链不匹配意味着 RPC 端点与设备预期的网络不一致;在签名前检查链 ID。Nonce 问题会产生替换或卡住的交易;查询待处理 nonce 并将其与最后确认的 nonce 进行比较。显示不匹配意味着主机交易与设备屏幕不一致,这是一个停止条件:拒绝交易并进行调查。

如果签名后广播失败,已签名载荷仍然有效。只要 nonce 尚未被消耗,你可以通过不同的端点重新广播它而无需重新签名。将原始已签名交易保存在安全的地方,直到它被确认或替换。

  • 未检测到设备:解锁设备,重新打开配套应用,并尝试不同的线缆或端口。
  • 链不匹配:在签名前验证 eth_chainId 与预期网络一致。
  • 交易卡住:查询待处理 nonce,并重新广播或使用更高费用替换。
  • 显示不匹配:在设备上拒绝,并检查主机交易构建。

局限性与权衡

非托管硬件钱包以便利性换取密钥隔离。每笔交易都需要物理确认,这对于高频操作来说很慢。助记词备份是单点故障:丢失助记词和设备,资金将无法恢复。固件和供应链信任仍然是残余风险,无论 RPC 可靠性多高都无法消除。

在基础设施方面,设备并不能解决 RPC 可用性问题。将正确的签名广播到不可用的端点仍然无法到达网络。将硬件钱包与可靠的 RPC 提供商配对可以解决可用性问题,但不会改变托管模型。对于运行许多签名设备的团队,考虑记录派生路径、链 ID 和端点配置,以便恢复和审计流程可复现。

后续步骤

完成验证运行后,为你管理的每个账户记录设备地址、派生路径、链 ID 和 RPC 端点。在依赖主网资金之前,先在测试网上测试恢复流程。如果你需要为主机软件选择端点,请使用 RPC Assistant 获取具体建议,并查阅 多链 RPC 端点指南 了解配置模式。对于标准化使用托管基础设施的团队,区块链节点托管指南 涵盖了与自托管签名互补的运维考虑。

永远不用担心基础设施

OnFinality 消除了 DevOps 的繁重工作,让您能够更聪明、更快地构建。

开始