暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PG 目前的两种数据库用户密码存储方法, 建议选择scram-sha-256.

digoal 2021-01-06
3610

作者

digoal

日期

2021-06-25

标签

PostgreSQL , md5 , scram-sha-256


背景

PG 目前的两种数据库用户密码存储方法, 建议选择scram-sha-256. 为什么呢?

1、PG md5密码加密方法

```
postgres=# set password_encryption ='md5';
SET
postgres=# alter role postgres encrypted password 'abc';
ALTER ROLE
postgres=# select rolname,rolpassword from pg_authid where rolname='postgres';
rolname | rolpassword
----------+-------------------------------------
postgres | md567429efea5606f58dff8f67e3e2ad490
(1 row)

MD5码 = md5(pwd+username)

postgres=# select md5('abcpostgres');
md5


67429efea5606f58dff8f67e3e2ad490
(1 row)
```

md5码的方法与pgcrytpo插件中的digest, hmac类似, 使用pwd加密出一个静态的hash, 使用时服务端存储hash如果要校验客户的密码是否正确必须拿hash去校验所以协议上无法防止泄漏hash后的认证. 参考如下:

MD5码泄漏有安全风险:
《PostgreSQL md5 对比 MySQL - 秘钥认证》

2、SCRAM-SHA-256 密码存储加密方法, 更加健壮

相关代码如下:
src/common/scram-common.c

存储格式:

SCRAM-SHA-256 $ <iteration count> : <salt> $ <StoredKey> : <ServerKey>

```
postgres=# set password_encryption ='scram-sha-256';
SET
postgres=# alter role postgres encrypted password 'abc';
ALTER ROLE
postgres=# select rolname,rolpassword from pg_authid where rolname='postgres';
rolname | rolpassword
----------+---------------------------------------------------------------------------------------------------------------------------------------
postgres | SCRAM-SHA-256$4096:N3V5yiPtZeUy8qeFzIN4Yw==$qzsIb2zahYWa0lkEQKlpKwN2rlx7rTTgKPzFS3vuBgg=:THe9oAyu7FVf7yIzvPSNA6bhUo++HBRE2s6ooKNd4Zg=
(1 row)

postgres=# alter role postgres encrypted password 'abc';
ALTER ROLE

同样的密码, 修改后存储内容也会变化.

postgres=# select rolname,rolpassword from pg_authid where rolname='postgres';
rolname | rolpassword
----------+---------------------------------------------------------------------------------------------------------------------------------------
postgres | SCRAM-SHA-256$4096:wlpFWX0mdrNHRcNFmF/mmA==$V3DLawFi9ElfE2+wqg1Kylz3UkB3R7i++AktU36V/PU=:lpxA8Cta59lq4dZCPcX2KVgaNMmKzaheJ9ZNva74hoE=
(1 row)
```

SCRAM-SHA-256 $ 4096 : HQ/MO4C1qFcdRonv2hiG0Q== $ Cgif0D/DtZQwwQNtOtvDs3LQtTZs6C2mPoKT9bcjbdw= : 2YD87hpH+x/FudOeFtLQAqVHlwYBo/iCR8nZdhhsP4c=

同样的密码, 它为什么能不一样? 因为有随机salt的加入

模拟加密过程:

```
crypt('pwd', '随机salt1') = res1;

crypt('pwd', '随机salt2') = res2;
```

模拟校验密码过程:

```
res1 = crypt('pwd', res1)

res2 = crypt('pwd', res2)

res1, res2 泄漏无安全风险.
```

例子:

```
postgres=# select crypt('hello 德哥', gen_salt('bf'));
crypt


$2a$06$LpqOUr49S58ooqzfjmTBRu6vI.D2Ann5lOTCzz/FLG7PHJNbVPqBC
(1 row)

postgres=# select crypt('hello 德哥', gen_salt('bf'));
crypt


$2a$06$lj0K8Jjcw3.uEWjito8FO.deLAad0CjLSBsYTO2nYABVnHDSz7YCS
(1 row)

postgres=# select crypt('hello 德哥', gen_salt('bf',10));
crypt


$2a$10$nPoQJv7lPZ5vCZGkX11qUuZ6t6tuR3HfVToT9uPS5/1cCyph3u0La
(1 row)

postgres=# select crypt('hello 德哥', gen_salt('bf',15));
crypt


$2a$15$IoSJ8tY1M0N4WJhQEZhz8uy/FD8o5dN6Muzr9BetMyyrsCN5UxNde
(1 row)

postgres=# select crypt('hello 德哥', gen_salt('bf',15));
crypt


$2a$15$rFB4Yfg4MQjlkAjUmHxyMuUCOigM8GhmSENjfy30uXK5X89zWdiXq
(1 row)

postgres=# select crypt('hello 德哥', '$2a$10$nPoQJv7lPZ5vCZGkX11qUuZ6t6tuR3HfVToT9uPS5/1cCyph3u0La');
crypt


$2a$10$nPoQJv7lPZ5vCZGkX11qUuZ6t6tuR3HfVToT9uPS5/1cCyph3u0La
(1 row)

postgres=# select crypt('hello 德哥', '$2a$15$rFB4Yfg4MQjlkAjUmHxyMuUCOigM8GhmSENjfy30uXK5X89zWdiXq');
crypt


$2a$15$rFB4Yfg4MQjlkAjUmHxyMuUCOigM8GhmSENjfy30uXK5X89zWdiXq
(1 row)
```

scram-sha-256的加密方法, 数据库存储res, 客户端必须提供pwd, 提供res无法校验密码正确性, 所以泄漏res不会影响安全性.

PostgreSQL 许愿链接

您的愿望将传达给PG kernel hacker、数据库厂商等, 帮助提高数据库产品质量和功能, 说不定下一个PG版本就有您提出的功能点. 针对非常好的提议,奖励限量版PG文化衫、纪念品、贴纸、PG热门书籍等,奖品丰富,快来许愿。开不开森.

9.9元购买3个月阿里云RDS PostgreSQL实例

PostgreSQL 解决方案集合

德哥 / digoal's github - 公益是一辈子的事.

digoal's wechat

文章转载自digoal,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论