将 PostgreSQL 密码哈希从旧版 MD5 算法迁移到 SCRAM-SHA-256 是一项关键的安全升级。本指南将进行影响分析,并提供分步骤的迁移计划,包括检测脚本、密码重置策略和回滚注意事项。

为什么从 MD5 迁移到 SCRAM-SHA-256?
MD5 密码哈希存在已知漏洞(快速哈希、碰撞攻击)。SCRAM-SHA-256(基于 SHA-256 的加盐挑战响应认证机制)是 PostgreSQL 10+ 的现代标准。它使用加盐、迭代哈希,能够抵抗暴力破解和彩虹表攻击。合规框架(如等级保护)通常要求使用 SCRAM-SHA-256。
了解影响
关键概念
password_encryption(在postgresql.conf中):控制通过CREATE USER或ALTER USER设置的新密码所使用的算法。更改它不会重新哈希现有密码。pg_hba.conf认证方法:PostgreSQL 10+ 中的md5实际上接受同时接受 MD5 和 SCRAM-SHA-256 哈希。scram-sha-256只接受 SCRAM-SHA-256。- 密码存储:哈希存储在
pg_authid.rolpassword中。MD5 哈希以md5开头,SCRAM-SHA-256 哈希以SCRAM-SHA-256$开头。
影响矩阵
| 变更 | 效果 |
|---|---|
将 password_encryption 改为 scram-sha-256 |
新密码使用 SCRAM-SHA-256;如果 pg_hba.conf 使用 md5,现有 MD5 密码仍然有效 |
将 pg_hba.conf 改为 scram-sha-256 |
只有 SCRAM-SHA-256 哈希可以认证;MD5 用户将被锁定 |
| 不重置密码 | 切换 pg_hba.conf 为 scram-sha-256 后,拥有 MD5 哈希的用户无法登录 |
分步骤迁移计划
阶段 1:清查与准备
- 识别所有具有 MD5 哈希的登录角色:
SELECT rolname, rolpassword
FROM pg_authid
WHERE rolpassword LIKE 'md5%'
AND rolcanlogin = true;
检查客户端驱动兼容性:确保所有客户端库(psql、JDBC、Npgsql 等)支持 SCRAM-SHA-256。PostgreSQL 10+ 客户端兼容。
备份
pg_authid:
COPY pg_authid TO '/tmp/pg_authid_backup.csv' WITH CSV HEADER;
阶段 2:密码迁移(pg_hba.conf 仍使用 md5)
- 在
postgresql.conf中设置password_encryption为scram-sha-256:
password_encryption = scram-sha-256
- 重新加载配置:
pg_ctl reload
# 或 SQL: SELECT pg_reload_conf();
- 重置所有 MD5 用户的密码。对于已知密码的系统用户:
ALTER USER postgres PASSWORD 'admin_password';
ALTER USER replicator PASSWORD 'replication_password';
对于应用用户,从配置文件中收集密码并重置:
# Python 示例
users = {
'app_user1': 'pwd_from_config',
'app_user2': 'pwd_from_config',
}
for user, pwd in users.items():
execute_sql(f"ALTER USER {user} PASSWORD '{pwd}';")
- 验证没有 MD5 哈希残留:
SELECT rolname, rolpassword FROM pg_authid
WHERE rolpassword LIKE 'md5%' AND rolcanlogin = true;
-- 应返回空行
阶段 3:切换认证方法
编辑
pg_hba.conf:将所有相关行中的md5改为scram-sha-256。重新加载配置:
pg_ctl reload
- 测试登录:
psql -U postgres -d postgres
阶段 4:验证
- 验证所有应用程序连接正常工作。
- 对于复制用户,如有必要更新
primary_conninfo。 - 确认没有残留的 MD5 哈希:
SELECT rolname FROM pg_authid WHERE rolpassword LIKE 'md5%' AND rolcanlogin = true;
常见陷阱
- 忘记复制用户:复制角色(例如
replicator)也需要重置密码;否则复制会中断。 - 跳过客户端兼容性:较旧的驱动(PG10 之前)可能不支持 SCRAM-SHA-256。先升级它们。
- 认为
password_encryption会追溯更改现有哈希:它不会。你必须显式重置密码。 - 没有回滚计划:MD5 哈希无法从 SCRAM-SHA-256 转换回 MD5。保留
pg_authid的备份。 - 在所有密码迁移完成之前,在
pg_hba.conf中使用scram-sha-256:拥有 MD5 哈希的用户将立即被锁定。
回滚策略
如果需要回退:
- 从备份恢复
pg_authid。 - 将
password_encryption设置为md5,pg_hba.conf改回md5。 - 重新加载配置。
- 再次重置密码(因为 SCRAM-SHA-256 哈希不向后兼容)。
常见问题
如果我更改了 password_encryption 但没有更改 pg_hba.conf,会发生什么?
新密码将使用 SCRAM-SHA-256 哈希,但现有 MD5 密码仍然可用,因为 pg_hba.conf 中的 md5 接受两者。这是一个安全的中间步骤。
我可以在不知道明文密码的情况下将 MD5 哈希转换为 SCRAM-SHA-256 吗?
不能。MD5 哈希是单向的。你必须知道原始密码才能用 SCRAM-SHA-256 重新哈希。
如何处理我不知道密码的应用用户?
选项:
- 在迁移后强制用户在首次登录时更改密码。
- 临时为这些用户在
pg_hba.conf中保留md5(不合规)。 - 在迁移前从应用程序配置文件中收集密码(推荐)。
SCRAM-SHA-256 会影响性能吗?
SCRAM-SHA-256 在认证时比 MD5 更耗费 CPU,但对于典型登录率来说,开销可以忽略不计。安全收益远远超过成本。
PostgreSQL 10 之前的版本呢?
SCRAM-SHA-256 从 PostgreSQL 10 开始支持。对于旧版本,请先升级 PostgreSQL。
尝试我们的 Bcrypt 哈希生成器 来了解现代哈希原理。