我有一个与 Postgres 对话的 rest api,现在在 api 的属性文件中我们正在硬编码数据库密码。 所以我们认为当在 postgres 中创建用户角色时,我们可以使用 Md5 哈希值(或任何其他应由 postgres 解密的加密值)作为密码......我们可以在 api 属性文件中使用该值(hased 值)而不是硬编码。
我的问题是我们可以在 api dev 属性文件中使用 Md5 哈希值吗?当密码通过网络发送并尝试连接到 postgres 时,它(postgres)是否会解密为实际密码并允许用户连接到数据库而无需认证失败?????
最佳答案
TL;DR:您不能将散列密码存储在属性文件中并使用它进行身份验证,除非客户端应用程序可以识别它是预先散列的并避免第二次散列传递。
如果客户端库确实识别预先散列的密码(libpq 不),散列密码可以用作真实密码的代理。如果您知道哈希值,则无需知道真实密码。这意味着将散列密码存储在属性文件中并不比存储原始密码更安全。
密码在通过网络发送之前会再次经过加盐和哈希处理,因此您无法嗅探您在网络上看到的内容并使用它来进行身份验证。
查看源码,src/backend/libpq/auth.c
中的sendAuthRequest
:
/* Add the salt for encrypted passwords. */
if (areq == AUTH_REQ_MD5)
pq_sendbytes(&buf, port->md5Salt, 4);
port
是src/include/libpq/libpq-be.h
中的struct Port
,它有:
char md5Salt[4]; /* Password salt */
这是由 src/backend/postmaster/postmaster.c
中的 ConnCreate
设置的:
/*
* Precompute password salt values to use for this connection. It's
* slightly annoying to do this long in advance of knowing whether we'll
* need 'em or not, but we must do the random() calls before we fork, not
* after. Else the postmaster's random sequence won't get advanced, and
* all backends would end up using the same salt...
*/
RandomSalt(port->md5Salt);
现在,密码在 src/backend/libpq/crypt.c
的 md5_crypt_verify
中验证。在那里我们看到已经存储为 md5 的密码再次使用 session 盐进行哈希处理:
if (isMD5(shadow_pass))
{
/* stored password already encrypted, only do salt */
if (!pg_md5_encrypt(shadow_pass + strlen("md5"),
port->md5Salt,
sizeof(port->md5Salt), crypt_pwd))
{
pfree(crypt_pwd);
return STATUS_ERROR;
}
}
因此,在线路上发送的散列密码受到保护,免受 session 盐的重放攻击。
客户端应用程序是否可以识别预散列密码及其期望密码的格式取决于客户端库。
根据 src/interfaces/libpq/fe-auth.c
中的 pg_password_sendauth
,libpq 前端似乎不检查预哈希密码输入。其他客户端可能会有所不同。
关于postgresql - api 属性文件中的 MD5 哈希数据库密码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33898502/