一、PostgreSQL用户密码以MD5方式加密
PostgreSQL里用户创建密码后,是把密码按照SCRAM-SHA-256或MD5等算法处理后的值写入数据库,等到用户登陆的时候,再把输入的密码进行相应的算法处理,把两个值进行比较来判断是否密码输入正确,具体如下:
客户端收到输入的密码后,会使用密码和用户做拼接,把用户作为salt,然后对拼接好的字符串做md5。即md5(密码+用户(salt))。然后把这个值加上md5前缀与存储在pg_authid里的rolpassword做比较,如果一致,则通过认证,如果不一致,则报密码错误。
MD5算法属于单向散列算法,无法通过反推获得原始输入数据,但是MD5不算严格意义上的加密算法,可用暴力穷举法破解。SCRAM-SHA-256生成的密文长度为256位,MD5生成的密文长度为128位。SCRAM-SHA-256算法的碰撞概率比MD5更小,因为SCRAM-SHA-256使用了更复杂的哈希算法和更长的输出长度。
二、测试验证使用md5认证时密码和pg_authid里rolpassword的关系
//session1
postgres=# show password_encryption ;
password_encryption
---------------------
md5
(1 row)
一个session用gdb来Attach这个进程,然后在encrypt_password函数这里打上断点。
//session2
(gdb) b encrypt_password
Breakpoint 1 at 0xaaaabc4f7a40: file crypt.c, line 118.
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000aaaabc4f7a40 in encrypt_password at crypt.c:118
然后原本的这个数据库连接里执行创建用户的操作
//session1
执行后处于一直卡着的状态
postgres=# create user ysla with password '1qaz!QAZ';
然后去gdb端查看堆栈
(gdb) c
Continuing.
Breakpoint 1, encrypt_password (target_type=PASSWORD_TYPE_MD5, role=0xaaaacccef658 "ysla", password=password@entry=0xaaaacccef670 "1qaz!QAZ") at crypt.c:118
118 {
(gdb) bt
#0 encrypt_password (target_type=PASSWORD_TYPE_MD5, role=0xaaaacccef658 "ysla", password=password@entry=0xaaaacccef670 "1qaz!QAZ") at crypt.c:118
#1 0x0000aaaabc48d160 in CreateRole (pstate=pstate@entry=0xaaaaccdd3038, stmt=stmt@entry=0xaaaacccef750) at user.c:446
#2 0x0000aaaabc68c420 in standard_ProcessUtility (pstmt=0xaaaacccef800, queryString=0xaaaaccceec28 "create user ysla with password '1qaz!QAZ';",
readOnlyTree=<optimized out>, context=PROCESS_UTILITY_TOPLEVEL, params=0x0, queryEnv=0x0, dest=0xaaaacccf0030, qc=0xffffc7625318) at utility.c:911
#3 0x0000ffffab246270 in pgss_ProcessUtility (pstmt=0xaaaacccef800, queryString=0xaaaaccceec28 "create user ysla with password '1qaz!QAZ';",
readOnlyTree=false, context=PROCESS_UTILITY_TOPLEVEL, params=0x0, queryEnv=0x0, dest=0xaaaacccf0030, qc=0xffffc7625318) at pg_stat_statements.c:1145
#4 0x0000aaaabc68a6cc in PortalRunUtility (portal=portal@entry=0xaaaaccd71f18, pstmt=pstmt@entry=0xaaaacccef800, isTopLevel=isTopLeve