PostgreSQL认证算法开发详解:从MD5到SM3的兼容性解决方案
PostgreSQL认证算法开发详解:从MD5到SM3的兼容性解决方案
PostgreSQL数据库支持MD5、SCRAM-SHA-256存储和认证算法,理所当然的我们要增加相对应的SM3、SCRAM-SM3存储和认证算法。那么问题来了,当设置的存储算法password_encryption与pg_hba.conf文件里设置的认证算法不一致时怎么办?
postgresql数据库支持MD5、SCRAM-SHA-256存储和认证算法,理所当然的我们要增加相对应的SM3、SCRAM-SM3存储和认证算法。那么问题来了,当设置的存储算法password_encryption与pg_hba.conf文件里设置的认证算法不一致时怎么办?
当前原生PG的存储和认证各两种算法,所以共有四种组合,针对这四种组合,PG的处理方式为:
认证算法 | 存储算法 | 实际采用的认证算法 |
---|---|---|
MD5 | MD5 | MD5 |
SCRAM-SHA-256 | SCRAM-SHA-256 | SCRAM-SHA-256 |
MD5 | SCRAM-SHA-256 | SCRAM-SHA-256 |
SCRAM-SHA-256 | MD5 | 认证失败 |
前两种不需要讨论;
第三种体现出PG的原则:如果要求的认证算法比实际可以使用的认证算法(取决于存储算法) 安全性较低,则自动更换为与存储算法对应的认证算法;
第四种必然认证失败。
当我们增加存储和认证算法SM3、SCRAM-SM3之后,存储和认证算法各有四种,则产生16种组合,依据上述原则,我们有如下选择:
序号 | 设置认证算法 | 设置存储算法 | 实际使用认证算法 |
---|---|---|---|
1 | MD5 | MD5 | MD5 |
2 | SM3 | SM3 | SM3 |
3 | SCRAM-SHA-256 | SCRAM-SHA-256 | SCRAM-SHA-256 |
4 | SCRAM-SM3 | SCRAM-SM3 | SCRAM-SM3 |
5 | MD5 | SCRAM-SHA-256 | SCRAM-SHA-256 |
6 | MD5 | SCRAM-SM3 | SCRAM-SM3 |
7 | SM3 | SCRAM-SHA-256 | SCRAM-SHA-256 |
8 | SM3 | SCRAM-SM3 | SCRAM-SM3 |
9 | SCRAM-SHA-256 | MD5 | 认证失败 |
10 | SCRAM-SHA-256 | SM3 | 认证失败 |
11 | SCRAM-SM3 | MD5 | 认证失败 |
12 | SCRAM-SM3 | SM3 | 认证失败 |
13 | MD5 | SM3 | 认证失败 |
14 | SM3 | MD5 | 认证失败 |
15 | SCRAM-SHA-256 | SCRAM-SM3 | 认证失败 |
16 | SCRAM-SM3 | SCRAM-SHA-256 | 认证失败 |
存在这么多不可能认证成功的情况,我们的使用体验肯定不好。
前8种我们不需要讨论;
第9-12种我们不需要讨论;
第13种我们可以使用SM3算法,这样还有7种不可能认证成功的情况;
当然我们可以针对第13-16种情况都选择使用存储算法相对应的认证算法,这样就只剩下9-12种四种情况的认证失败,体验会好很多。
但是我们还有另外的选择,既能认证通过又没有完全抛弃hba设置的认证算法:增加MD5-SM3、SM3-MD5、SCRAM-SHA256-SM3、SCRAM-SM3-SHA256这四种认证算法分别针对第13-16种情况,具体解释如下:
以MD5存储和认证算法为例分析其算法实现:
1、存储算法:stored_key=MD5(password||username)
2、认证算法:
服务端:auth_key=MD5(stroed_key||salt)
客户端:auth_key=MD5(MD5(password||username)||salt)
因为第1步存储的时候stored_key=MD5(password||username),所以服务端和客户端分别计算的auth_key肯定是一致的,所以认证通过。
那么想当然的,我们的MD5-SM3算法就应该是这样的:
1、存储算法:stored_key=MD5(password||username)
2、认证算法:
服务端:auth_key=SM3(stroed_key||salt)
客户端:auth_key=SM3(MD5(password||username)||salt)
因为第1步存储的时候stored_key=MD5(password||username),所以服务端和客户端分别计算的auth_key肯定是一致的,所以认证通过。
SM3-MD5认证算法同理。
SCRAM-SHA256-SM3和SCRAM-SM3-SHA256又如何呢?请看下图:
上面右侧红色的是服务端在存储密码时候进行的计算,当用户登录进行认证时我们是无法改变它使用的基于sha256或sm3的HMAC算法的,但是,客户端和服务端分别计算的ClientSignature是认证时候进行的,这个我们就可以根据需要选择不同的HMAC算法了,当存储为SCRAM-SHA-256时,我们可以使用SM3-HMAC计算ClientSignature,也就实现了认证算法SCRAM-SHA256-SM3,同理可实现SCRAM-SM3-SHA256认证算法。
那么,我们可得下表,使用体验应该好很多,又没有完全背离hba设置的认证要求:
序号 | 设置认证算法 | 设置存储算法 | 实际使用认证算法 |
---|---|---|---|
1 | MD5 | MD5 | MD5 |
2 | SM3 | SM3 | SM3 |
3 | SCRAM-SHA-256 | SCRAM-SHA-256 | SCRAM-SHA-256 |
4 | SCRAM-SM3 | SCRAM-SM3 | SCRAM-SM3 |
5 | MD5 | SCRAM-SHA-256 | SCRAM-SHA-256 |
6 | MD5 | SCRAM-SM3 | SCRAM-SM3 |
7 | SM3 | SCRAM-SHA-256 | SCRAM-SHA-256 |
8 | SM3 | SCRAM-SM3 | SCRAM-SM3 |
9 | SCRAM-SHA-256 | MD5 | 认证失败 |
10 | SCRAM-SHA-256 | SM3 | 认证失败 |
11 | SCRAM-SM3 | MD5 | 认证失败 |
12 | SCRAM-SM3 | SM3 | 认证失败 |
13 | MD5 | SM3 | MD5-SM3 |
14 | SM3 | MD5 | SM3-MD5 |
15 | SCRAM-SHA-256 | SCRAM-SM3 | SCRAM-SHA256-SM3 |
16 | SCRAM-SM3 | SCRAM-SHA-256 | SCRAM-SM3-SHA256 |