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

热钱包与冷钱包:密钥托管中真正重要的区别

理解热钱包与冷钱包的真正区别、签名流程的差异,以及如何通过可复现的检查验证你自己的托管设置。

TL;DR

热钱包与冷钱包的区别不在于你手持的设备,而在于私钥存放的位置,以及它是否能在暴露于联网环境时进行签名。热钱包将密钥保存在可被互联网连接进程访问的软件中;冷钱包将密钥保存在使用期间离线的环境中,交易通过气隙或硬件签名边界进行传输。本文解释签名机制,提供可对你自己的设置运行的可执行检查,并将有文档记录的行为与你必须自行运行的测量区分开来。最后讨论决定热加冷混合架构是否适合你的运营的权衡取舍。

直接答案与范围

热钱包是指私钥保存在连接到互联网的设备上的软件中的钱包,因此签名可以在与网络通信的同一环境中进行。冷钱包是指私钥保存在签名时离线的环境中的钱包,因此交易必须传输到该环境、签名后再传输回来。区别在于签名期间的密钥暴露,而不是品牌名称、应用商店或设备是否看起来像 USB 盘。

本文涵盖机制、可复现的验证程序以及操作权衡。它不推荐特定的硬件供应商或特定端点。当你需要具体的 RPC 端点或提供商选择来广播已签名交易时,请使用 OnFinality RPC Assistant,而不是将本页视为提供商列表。

  • 热钱包:密钥在联网软件中;签名和广播可以在同一进程中发生。
  • 冷钱包:签名时密钥离线;已签名的负载在广播前跨越边界。
  • 温钱包或混合设置:密钥可能在线但受策略、MPC 或审批控制;根据实际密钥暴露来分类,而不是营销标签。

假设与前提条件

以下程序假设你控制 EVM 兼容网络上的钱包,并且可以运行命令行工具。你需要一个测试网上有资金的测试账户、一个你有权使用的 JSON-RPC 端点,以及安装 curl 和 Node.js 或 Python 的能力。切勿使用主网密钥或生产种子短语运行这些检查。

你还应该知道正在测试哪个地址,以及你的钱包软件是否暴露原始签名或仅暴露高级发送功能。如果你的钱包不暴露签名边界,你仍然可以通过观察密钥材料是否加载到具有出站网络访问的进程中来对其进行分类。

心智模型:密钥、签名和广播是独立的步骤

钱包不存储币。它存储或派生私钥,这些私钥授权区块链上的状态变更。交易由链上数据(如 nonce、gas 参数、接收者和价值)构建;然后用私钥签名;然后将签名字节广播到节点。热与冷的问题完全在于第二步:私钥在签名时存在于哪里?

在热钱包中,获取 nonce 和 gas 价格的同一进程也持有密钥并生成签名。在冷钱包中,未签名交易被导出、移动到离线签名器、在那里签名,然后已签名交易被移回在线广播器。该边界就是安全属性。这也解释了为什么永久插入在线计算机并自动批准交易的硬件设备在功能上更接近热钱包而非真正的气隙签名器。

  • 构建:在线,需要链上状态,如 nonce 和费用。
  • 签名:唯一需要私钥的步骤。
  • 广播:在线,只需要已签名的负载。

可运行检查:签名前检查 nonce 和链状态

在比较钱包类型之前,确认你的端点返回签名器将使用的链状态。此 curl 调用读取地址的交易计数。将 RPC_URL 和 ADDRESS 替换为你自己的值。签名器使用的 nonce 与网络期望的 nonce 不匹配是交易失败或卡住的常见原因,并且与钱包是热还是冷无关。

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

可运行检查:在不暴露密钥的情况下验证签名

冷签名工作流应允许你在广播前验证已签名负载恢复为预期地址。下面的 JavaScript 示例使用 ethers 从消息签名中恢复签名者。如果签名来自冷签名器,请在离线或隔离环境中运行它。重点是确认边界有效:密钥保持离线,但生成的签名仍可在线验证。

此检查不能证明你的密钥从未暴露。它证明签名对应于你期望的地址。将其与密钥材料加载位置的流程审计配对。

const { ethers } = require('ethers');

async function verify() {
  const message = 'cold-signing-check';
  const signature = process.env.SIGNATURE; // produced by your offline signer
  const expected = process.env.EXPECTED_ADDRESS;
  const recovered = ethers.verifyMessage(message, signature);
  console.log('recovered:', recovered);
  console.log('matches expected:', recovered.toLowerCase() === expected.toLowerCase());
}

verify().catch(console.error);

用于你自己的托管比较的结果表程序

不要依赖供应商的安全态势声明。根据你自己的观察构建结果表。对于你操作的每个钱包,记录以下列并通过检查和运行上述检查来填写。留空单元格而不是猜测;空白单元格是诚实的测量缺口。

钱包标签密钥加载到联网进程?签名需要手动边界?签名验证到预期地址?Nonce 源匹配端点?备注
热测试钱包是/否是/否是/否是/否记录工具和版本
冷测试钱包是/否是/否是/否是/否记录气隙方法

该表仅在你对测试密钥运行时有用。显示手动边界的热钱包可能是混合型;为方便而将密钥导入在线热进程的冷钱包在实践中是热的。根据观察到的密钥暴露分类,而不是产品类别。

预期验证结果

对于正确配置的冷签名流程,你应该看到恢复的地址与预期地址匹配,并且你应该能够确认私钥从未出现在广播交易的进程中。对于热钱包,恢复的地址也应匹配,但密钥将加载在构建和发送交易的同一联网进程中。

如果恢复的地址不匹配,在广播前停止。不匹配通常意味着错误的密钥、错误的消息编码,或签名生成的字节与你验证的不同。如果来自你端点的 nonce 与签名器使用的 nonce 不同,重建交易而不是强制广播。

常见错误分类的故障排除

最常见的错误是将任何硬件设备称为冷钱包。保持连接并自动签名的设备是硬件支持的热签名器。另一个常见错误是假设移动应用总是热的;一些应用支持仅观察模式或外部签名器,这改变了密钥暴露,即使应用在线。

如果交易因 nonce 错误被拒绝,检查是否有另一个进程同时使用了相同的密钥。热钱包特别容易发生这种情况,因为多个在线进程可以共享密钥文件。如果签名验证通过但交易在链上失败,问题可能是 gas、链 ID 或合约逻辑,而不是热与冷的边界。

  • Nonce 冲突:按密钥序列化签名或使用单一签名服务。
  • 链 ID 不匹配:确认签名器使用与广播器相同的网络。
  • 密钥导入捷径:将冷种子导入热应用会破坏边界。

权衡与限制

冷存储减少远程入侵的暴露,但不能消除网络钓鱼、物理盗窃或签名期间用户错误造成的损失。它还增加延迟和操作摩擦,这对高频操作很重要。热钱包更快且更容易自动化,但每个能访问密钥的在线进程都是你的攻击面的一部分。

实际架构通常分离角色:热钱包仅持有运营余额,而冷或策略控制的签名器持有储备。边界必须通过流程强制执行,而不仅仅是标签。对于运行自己的节点或专用基础设施的团队,广播器侧可以与签名器侧隔离;请参阅专用节点和 RPC 定价指南以适当确定该分离的规模。

后续步骤

首先使用测试密钥通过上述结果表对当前钱包进行分类。然后决定你的运营是否需要严格的气隙、带手动批准的硬件支持签名器,或余额有限的热钱包。如果你需要选择端点来广播已签名交易,请使用 RPC Assistant 获取直接推荐,并查看网络指南以了解链特定细节。

有关节点操作和端点可靠性的更广泛背景,请阅读区块链节点托管指南和多链 RPC 端点指南。这些资源帮助你保持热加冷架构的在线部分可观察和可复现。

  • 根据观察到的密钥暴露对钱包分类,而不是产品类别。
  • 始终将测试密钥与生产密钥分开。
  • 记录签名边界并在任何工具升级后重新验证。

永远不用担心基础设施

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

开始