让应用的交易密钥和 Secret 不落在服务器的磁盘上

erpc worker 将应用的交易密钥和 Secret 保存在 1Password、您的钥匙串或加密的密钥库中,并在内存中交给应用,从不写入服务器的磁盘。
本页介绍 ERPC CLI v0.1.0-rc.4,这是一个预发布版本。

交易密钥如何送达应用

带有钱包的应用在启动时经由管道获得其密钥。服务器上没有 wallet.json,没有 .env,也没有副本。erpc 不会以未加密的形式将密钥写入任何磁盘:它存放密钥的唯一文件属于密钥库,位于本机,并以您的密码短语加密。
  • 保存位置:erpc login 将会话保存在 1Password 中时,erpc worker key new 在 1Password 中创建密钥;否则在钥匙串中创建;再否则在密钥库中创建。erpc.toml 记录密钥的引用及其公钥。
  • 在服务器上:erpc worker agent 只在内存中持有密钥。它使自身无法被转储并锁定其内存,通过文件描述符将密钥交给应用;应用读取后将其擦除。
  • 重启之后,worker 恢复后处于锁定状态:在 erpc worker start 再次发送密钥之前,应用不会运行。失败或被终止的 agent 会由 systemd 再次启动,恢复后同样处于锁定状态。
  • 软件包更新不会重启 worker。deploy 让 needrestart 不要动 worker 单元:在自动模式下,它会推迟这些单元;在终端中被询问时,它对这些单元的默认回答为“否”,因此无人值守的安全更新不会重启应用。无法写入该规则时,部署会说明这一点并继续,此后 worker 在没有这项保护的情况下运行。
交易密钥只由 [wallet] 指定,不由其他任何内容指定,并且 erpc 只在有人在终端前操作时读取它:不为 AI 工具读取,也不通过 1Password 服务账户读取。指定 [wallet] 引用的 [secrets] 行,或以 .wallet 结尾的 keychain: 或 keystore: 账户,会被拒绝。在密钥库中,作为密钥保存的条目不会作为 Secret 打开。在 1Password 中,以及在其他名称的钥匙串账户下,没有任何东西标记密钥:没有 [wallet] 的 erpc.toml 若在 [secrets] 下指定了这样的条目,该条目会被当作 Secret 读取。

选择值的保存位置

1Password 是可选的。erpc worker key new 和 erpc worker secret put 会将收到的内容保存在以下各项中第一个适用的位置,除非 --store 指定了某一项(--store 1password --vault <id>、--store keychain、--store keystore):
  1. 1Password,当 erpc login 将会话保存在其中,或指定了 --vault 时。
  2. 操作系统钥匙串,在它能跨重启保存值的环境中:macOS、Windows,以及在已登录会话中带有桌面密钥环的 Linux。
  3. erpc 的密钥库,在没有这类密钥环的 Linux 机器上:无头服务器、WSL、SSH 登录。在这类机器上,--store keychain 会被拒绝。
在钥匙串或密钥库中,密钥只存在于那一台机器上,没有副本,也不同步,其他机器无法读取 keychain: 或 keystore: 引用。
机器丢失或被擦除,就意味着钱包丢失:请只在其中存放少量资金,或使用 1Password,凡是登录到该保险库的机器都能读取。请使用 erpc login --store 1password-desktop 登录 1Password;在没有桌面应用的地方,通过 op signin 登录。
1Password 服务账户可以保存应用的 Secret,但 erpc 不会通过它读取交易密钥。使用 1Password 时,每次读取都可能在应用中显示批准提示,erpc 在等待期间会显示加载指示。

保存 Secret

Secret(例如 API 令牌和 RPC 密钥)以同样的方式保存,但以环境变量的形式送达应用,而不是经由管道。erpc worker secret put <NAME> 保存值,erpc.toml 中的 [secrets] 只保存其引用。
bash
erpc worker secret put API_TOKEN --generate          # the bot's own API token, made for you and shown to nobody
erpc worker secret put ERPC_API_KEY --from-account   # the account's RPC key, read from your account (or SOLANA_RPC_ENDPOINT in [vars])
  • --generate 生成值:32 个随机字节,以 64 个十六进制字符表示。
  • --from-account 保存您账户中第一个被共享 RPC 接受的 RPC 密钥。密钥按顺序尝试,主要密钥优先,每个密钥发送一次 getHealth,等待应答 8 秒。应答为 401 或 403 的密钥会被拒绝并尝试下一个,只有被 RPC 接受的密钥才会被保存。命令会说明它是账户的主要密钥还是其他密钥(使用 --json 时为 account_key)。
  • 两种值都不会被打印,使用 --json 时也不会。首次使用密钥库,或密钥库处于锁定状态时,需要有人在终端前操作。
  • 密钥是从本机尝试的,因此仅限服务器地址使用的密钥在这里会被拒绝,尽管它在服务器上可用。所有密钥都被拒绝时,--from-account 不保存任何内容,由您手动保存您要用的密钥,可以不显示地输入或通过管道传入。无法询问 RPC 时,它不保存任何内容,erpc.toml 保持原样;请再次运行同一命令。
手动保存密钥:
bash
erpc worker secret put ERPC_API_KEY        # asks for the value, unseen
  • --replace 为已设置的名称保存新值。erpc worker secret list 按名称列出 Secret 设置及各自的保存位置。
  • 数据线路提供的设置(GRPC_ENDPOINT、SHREDS_ENDPOINT、SOLANA_SEND_RPC_ENDPOINT)绝不是 Secret:由 --grpc、--shreds 和 --unlimited 设置。
[secrets] 或 [wallet] 中的引用是以下之一:
引用值所在的位置
op://<vault-id>/<item-id>/<field>1Password,按保险库和条目 ID
keychain:<service>/<account>保存该值的机器上的操作系统钥匙串
keystore:<service>/<account>保存该值的机器上 erpc 的密钥库

密钥库

密钥库是目录 ~/.erpc/keystore(设置了 ERPC_HOME 时为其下的 keystore)。在 Linux 和 macOS 上,其目录权限为 0700,文件权限为 0600;在 Windows 上,erpc 不自行设置权限。
  • master.json 保存一个随机的 32 字节主密钥,该主密钥由 PBKDF2-HMAC-SHA256(600,000 次迭代)从您的密码短语派生的密钥封存。每个条目保存一个值,以其自己的密钥通过 ChaCha20-Poly1305 封存。
  • 密码短语:首次使用密钥库的 key new 或 secret put 会让您设定它,在终端中输入两次,长度为 12 个字符或以上。erpc 只从该隐藏输入提示获取它,从不从参数、环境变量或管道获取。
  • 在 Linux 上解锁:密码短语打开密钥库后,解锁状态会保存在内核的持久密钥环中(位于内存),直到机器重启、密钥环在其空闲过期时间内未被使用(三天,除非系统另有设置),或运行 erpc worker secret lock。erpc worker secret unlock 预先询问密码短语,并说明解锁持续到何时。在未经自身登录而启动的 shell 中(不带 - 的 su、sudo -E),不会保存解锁状态,每条命令都会询问。
  • 终端前无人操作时,需要密钥库的命令会在有解锁状态时使用它,否则失败,并提示 erpc worker secret unlock。已解锁的密钥库交出的是 Secret,而不是交易密钥。
  • 在 macOS 和 Windows 上(--store keystore),不会保存解锁状态:每条需要密钥库的命令都会询问一次密码短语,因此需要终端。

密钥库能保护什么,不能保护什么

  • 请备份 keystore 目录并记住密码短语。erpc 两者都无法恢复,缺少其中任何一个,密钥库保存的内容就会丢失。
  • 拥有密钥库文件和密码短语的人就拥有密钥。PBKDF2 让每次猜测都变慢,但不能让可被猜到的密码短语变得安全。
  • 密钥库处于解锁状态时,以您的身份运行的任何程序都能从内核密钥环读取主密钥(会话中没有您密钥环的程序也可以将其链接进来),并打开每个条目,包括密钥的条目。erpc 自己的规则([wallet] 指定的密钥只为终端前的人读取,绝不为 AI 工具读取;保存在密钥库中的密钥绝不作为 Secret 打开)是 erpc 的行为;它们不约束以您的身份运行的其他程序。用完后请运行 erpc worker secret lock。
  • 条目名称不会被隐藏,条目的大小会显示值的长度。
  • 被修改的文件无法打开;但放回原处的同一条目的旧副本可以打开。
  • erpc worker secret rm 删除 Secret 的密钥库条目及其在 erpc.toml 中的行(除非应用的其他设置指定了同一条目),而 1Password 或钥匙串中的值保留原处。它不会擦除磁盘,您备份中的副本也会保留。
  • erpc 从不删除或覆盖交易密钥的条目。要替换密钥,请先转移资金,然后自行删除其文件和 [wallet]。
  • 在密钥库或钥匙串中,设置不能命名为 WALLET(不区分大小写);--store 1password 可以使用该名称。

使用交易密钥

命令作用
erpc worker key new创建交易密钥,并打印需要转入资金的公钥
erpc worker key import <FILE>将密钥文件移入 1Password、钥匙串或密钥库,然后提议擦除该文件
erpc worker key show显示密钥的公钥及其保存位置
erpc worker key balance通过应用自己的 RPC 设置显示密钥的余额
erpc worker key send --to <ADDRESS> --sol <N>在终端中得到您的确认后,在内存中签署一笔转账。--all 发送除手续费以外的全部余额
如果 erpc 结束时不知道转账是否已上链,请在再次发送之前查询其签名:第二次发送就是第二笔转账。