---
title: "让应用的交易密钥和 Secret 不落在服务器的磁盘上"
description: "erpc worker 将应用的交易密钥和 Secret 保存在 1Password、操作系统钥匙串或加密的密钥库中，并在内存中交给应用。"
canonical: "https://erpc.global/zh/doc/erpc-cli/worker-secrets/"
locale: "zh"
---

# 让应用的交易密钥和 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 结束时不知道转账是否已上链，请在再次发送之前查询其签名：第二次发送就是第二笔转账。
