rpcauth 为什么存哈希不存密码:节点 RPC 凭据的正确姿势 图 1
rpcauth 为什么存哈希不存密码:节点 RPC 凭据的正确姿势 · 图 1

给自己的比特币节点开 RPC 之前,先要回答一个问题:谁来调这些命令。Bitcoin Core 提供两条鉴权路:一条是启动时随机生成的 cookie 文件,适合本机脚本自用;另一条是给多个用户签发凭据的 rpcauth 工具,适合把节点能力开放给团队成员或自己的其他设备。本文按仓库里那份 rpcauth.py 的源码讲清第二条路的设计:为什么配置文件里那行凭据没有你的密码,只有密码的影子。

一条凭据行的诞生

工具的使用方式是给出用户名运行 rpcauth.py 用户名。源码里三步一目了然:先调用随机源生成一段十六进制盐(官方实现用 16 字节的密码学安全随机),再为你生成或接受一个 32 字节的 base64 密码,最后把盐和明文密码喂进 HMAC-SHA256 得到一段摘要。输出一行形如 rpcauth=用户名:盐$摘要 的配置,你把它原样贴进 bitcoin.conf。从此配置文件、备份文件、版本库里流转的只有盐和摘要——明文密码除了你第一次使用的那一刻,从未在任何文件里安家。这挡住了内容最常见的死法:配置随备份泄露、误提交仓库、被截图进工单,密码本身都还有救。

匹配时发生了什么

RPC 请求走 HTTP Basic 认证:客户端把用户名密码用冒号拼接后 base64 编码放进请求头。节点收到后按用户名查出配置里对应的盐,对盐重算 HMAC 比对摘要——注意方向:节点拿盐重算摘要来验证,而不是还原密码;HMAC 的性质保证没有明文密码就无法造出能通过校验的摘要。两个诚实的设计细节常被忽略:每个用户的盐独立随机,同一个密码发两次凭据,两行摘要完全不同,配置泄露无法先比较再猜测;而认证头里的 base64 是可逆编码不是加密,这一层在 HTTP 明文下等于把密码裸奔——所以跨机访问的标准姿势是给 RPC 套 TLS 或走隧道,而不是换更花哨的密码格式。

和 rpcuser 加 rpcpassword 的旧路差别

老式配置 rpcuser 与 rpcpassword 直接把明文写进配置文件,改一次密码就要在几个文件里搬运明文,密码还天然成了单点共享。rpcauth 把共享明文的模型换成了逐用户签发:每人一行独立凭据,可以随时删行吊销单个用户而不惊动其他用户。需要说明适用边界:rpcauth 管的是 RPC 用户名口令这一种认证;cookie 文件路线仍是本机自用的默认选择,文件权限通常被收紧到只有属主可读,两者解决的是信任分布不同的问题,不存在通用优劣。

访问控制是三层的

把 rpcauth 当万能锁是常见误区。第一层是绑定地址:RPC 监听面默认只覆盖本机,rpcbind 与白名单参数才决定它是否伸手到别的网段;第二层才是凭据:rpcauth 或 cookie;第三层是命令面——wallet、zmq 等按模块划分权限,白名单选项可以授予 noban 等特权连接,这些设置各自都有独立的泄露后果。审计一个节点的暴露面,从绑定地址开始看,凭据强度排第二:真实世界里节点被撞库沦陷,多数败在第一层把门开得太大,而不是密码不够长。

快速问答

问:忘了某用户的密码怎么办?答:重新跑 rpcauth 生成新行替换旧行即可,旧凭据即刻作废,这正是逐用户签发的日常用法。

问:摘要能反推密码吗?答:HMAC-SHA256 不存在常规反推路径;但弱口令可被字典撞摘要,所以工具生成的随机密码不要手工替换成顺口溜。

问:多台机器能共用一行 rpcauth 吗?答:能但等于共享凭据,吊销时只能一起吊销,更稳的做法是每台一个用户。

风险提示:本文是节点运维科普。开放 RPC 前确认绑定地址、防火墙与命令权限三件事;凭据文件与 cookie 文件都按敏感信息管理,避免把含凭据的配置提交到任何版本库。