Sehrope Sarkuni:Postgres密码加密而不泄露凭据

💡 原文英文,约1500词,阅读约需6分钟。
📝

内容提要

本文介绍了在PostgreSQL数据库中创建用户和加密密码的方法,包括使用哈希函数和HMAC操作进行加密。在PostgreSQL v10之前,只有md5加密选项可用,而在v10之后,新增了SCRAM-SHA-256加密选项。使用ALTER USER命令可以更新用户密码。还介绍了相关的库和工具,如libpq、PGJDBC和pg-password-util,可以帮助加密密码并更新用户密码。强调了生成强密码的重要性。

🔎

延伸解读

明文密码的风险不止于日志

文章指出,使用CREATE USER或ALTER USER直接传递明文密码时,SQL语句会发送到数据库服务器。如果启用了语句日志,密码将出现在服务器日志中;若中间有连接池或代理,也可能被记录。即使服务器立即加密存储,明文仍可能泄露在传输或日志环节。因此,避免明文传递是安全实践的关键一步。

从MD5到SCRAM:安全性的实质提升

PostgreSQL v10之前仅支持MD5加密,其盐值仅4字节,在无TLS时攻击者可通过收集足够多的认证响应来穷举。v10引入的SCRAM-SHA-256使用SHA-256哈希、16字节盐和4096轮密钥拉伸,还能让客户端验证服务器身份。文章明确表示,在现代PostgreSQL服务器上没有理由再使用MD5认证。

利用库函数避免明文暴露

文章介绍了多种客户端工具:libpq的PQencryptPasswordConn、PGJDBC的PasswordUtil和alterUserPassword方法、以及node.js的pg-password-util。这些工具在客户端完成密码加密,生成可直接用于SQL的哈希值,从而避免明文密码经过网络或写入日志。对于Java用户,推荐先创建无密码用户,再调用alterUserPassword更新密码。

强密码与安全存储同样重要

文章强调,即使加密传输,弱密码如'abcd'仍不安全。建议使用长且密码学随机的密码,例如通过/dev/urandom生成43字符的随机字符串,提供约256位熵。同时,应将生成的密码保存到安全的秘密存储中,再使用上述工具更新数据库用户凭据,确保明文密码不在任何环节持久化。

❓

Q&A

PostgreSQL 中创建用户时直接使用明文密码有什么风险?

使用 CREATE USER app PASSWORD 't0pSecret!' 这样的语句时,密码明文会发送到数据库服务器。如果启用了语句日志,密码会出现在服务器日志中;如果中间有连接池或代理,也可能记录在它们的日志里。

PostgreSQL 的密码加密具体是什么操作?

PostgreSQL 文档称之为“密码加密”,实际执行的是哈希和 HMAC 操作。服务器不需要知道密码明文,只需存储单向哈希结果,并在连接时验证提供的凭据哈希是否匹配。

PostgreSQL v10 之前和之后分别支持哪些密码加密方式?

v10 之前只有 md5 加密,服务器存储 MD5(password || username) 在 pg_shadow 中。v10 开始新增 SCRAM-SHA-256 并成为默认,它使用 SHA-256、更大的盐(默认16字节)和密钥拉伸(默认4096轮),安全性更高。

如何使用 ALTER USER 命令安全地更新用户密码?

建议使用 SCRAM-SHA-256 加密后的密码值,例如 ALTER USER alice PASSWORD 'SCRAM-SHA-256$4096:...',避免使用明文或 md5 加密。这样密码不会以明文形式暴露在日志中。

有哪些库或工具可以帮助在不泄露明文密码的情况下更新 PostgreSQL 用户密码?

libpq 提供 PQencryptPasswordConn 函数;PGJDBC 新增 PasswordUtil 类和 PGConnection.alterUserPassword 方法;node.js 有 pg-password-util 模块。这些工具在客户端加密密码,避免明文传输。

如何生成强密码用于 PostgreSQL 服务账户?

在 *nix 环境可以使用命令 tr -d -c a-zA-Z0-9 </dev/urandom | head -c 43 生成一个43字符的随机密码,每个字符有62种选择,总熵约256位,适合服务账户。

🏷️

标签

➡️

继续阅读