---
id: 031
title: epsilon + alpha 生产 CERT_ID_SALT 未配（v0.6.0 身份证 hash 跑默认 dev-salt）
status: closed
labels: [security, prod, epsilon, alpha, realname]
assignee: team-lead
created_at: 2026-04-23
closed_at: 2026-04-23
---

# #031 CERT_ID_SALT 未配 —— #003 的同类漏洞

## 发现

继续推进时顺手查 epsilon live env（2026-04-23 #030 归档后）：

```
$ systemctl show xiangqin -p Environment | tr ' ' '\n' | grep SALT
XIANGQIN_PHONE_SALT=aec1842...
（没 CERT_ID_SALT）
```

alpha 同样漏配。两机都跑 `src/xiangqin/db.py` 的默认值：

```python
CERT_ID_SALT = os.environ.get("XIANGQIN_CERT_ID_SALT", "dev-cert-salt-not-for-prod").encode()
```

## 根因

v0.6.0 实名认证（PRD-001）给身份证号加了独立 HMAC salt，代码 ship 了但 provision
脚本 + alpha/epsilon 的 systemd override 都没跟进配置。#003 当初只修了
`XIANGQIN_PHONE_SALT`，没把"所有 SALT 类 env"作为清单化项。

是一个**"代码引入新敏感字段 → 部署层漏加 salt"的部署-代码同步 gap**。

## 影响

- 身份证 hash 入库用公开字符串 `dev-cert-salt-not-for-prod`，防撞库失效
- **生产库 users 表 0 行**（`sqlite3 xiangqin.db "SELECT COUNT(*) FROM users"` = 0）
  → 切 salt **零用户影响**，最好时机
- alpha 同理，E2E 测试号里实名测试账号也是 dev salt（不影响隐私但失去代码正确性假设）

## 修法（已做）

两机各生成独立 `openssl rand -hex 32`，写 `/etc/systemd/system/xiangqin.service.d/override.conf`：

```
[Service]
Environment=XIANGQIN_PHONE_SALT=<existing value>
Environment=XIANGQIN_CERT_ID_SALT=<new value>
```

`systemctl daemon-reload && systemctl restart xiangqin`，验证：

- epsilon `systemctl show` 回显两个 SALT + `is-active` → active；`/health` → version 0.6.5 ok
- alpha 同上，`curl http://127.0.0.1/health` → ok

## 遗留事项（另开 issue）

1. **salt 入 vault** —— 当前 salt 只存 systemd override.conf 在单机上，**机器消亡则全库 phone_hash + cert_id_hash 全报废**。应入 vault 作为 credential（类型 misc，slug `xiangqin-alpha` / `xiangqin-epsilon`，包含两种 salt），未来 vault install 铺到生产机
2. **provision 脚本模板化** —— `systemd/xiangqin.service` 里加注释提醒 "每新增一个 `*_SALT` env，必须同步写 override.conf + vault credential"
3. **pytest 防回归** —— 加一条 test 扫 `src/xiangqin/**/*.py` 里所有 `os.environ.get("XIANGQIN_*_SALT", "...")` 的默认值，在部署 doctor 里对每一条 assert 环境变量已配（非空 != 默认值）

## 相关

- 前置：#003（PHONE_SALT 未配，已 closed task #42）—— 修法模板来自这里
- 代码：v0.6.0 `src/xiangqin/db.py` 加 `hash_cert_id()` + CERT_ID_SALT env
- 时机：生产尚未对外开放，users 表 0 行，所以 salt 切换无需数据迁移
