PostgreSQL md5 auth method introduce, with random salt protect

本文涉及的产品
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
简介:
在上一篇BLOG中介绍了不要在pg_hba.conf中使用password认证方法, 除非你的客户端和数据库服务器之间的网络是绝对安全的.

MD5方法,认证过程 :
Encrypting Passwords Across A Network
The MD5 authentication method double-encrypts the password on the client before sending it to the server. It first MD5-encrypts it based on the user name, and then encrypts it based on a random salt sent by the server when the database connection was made. It is this double-encrypted value that is sent over the network to the server. Double-encryption not only prevents the password from being discovered, it also prevents another connection from using the same encrypted password to connect to the database server at a later time.


数据库服务器给客户端连接进程发送认证请求包 : 
src/backend/libpq/auth.c
/*
 * Send an authentication request packet to the frontend.
 */
static void
sendAuthRequest(Port *port, AuthRequest areq)
{
        StringInfoData buf;

        pq_beginmessage(&buf, 'R');
        pq_sendint(&buf, (int32) areq, sizeof(int32));

        /* Add the salt for encrypted passwords. */
        if (areq == AUTH_REQ_MD5)
                pq_sendbytes(&buf, port->md5Salt, 4);

#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)

        /*
         * Add the authentication data for the next step of the GSSAPI or SSPI
         * negotiation.
         */
        else if (areq == AUTH_REQ_GSS_CONT)
        {
                if (port->gss->outbuf.length > 0)
                {
                        elog(DEBUG4, "sending GSS token of length %u",
                                 (unsigned int) port->gss->outbuf.length);

                        pq_sendbytes(&buf, port->gss->outbuf.value, port->gss->outbuf.length);
                }
        }
#endif

        pq_endmessage(&buf);

        /*
         * Flush message so client will see it, except for AUTH_REQ_OK, which need
         * not be sent until we are ready for queries.
         */
        if (areq != AUTH_REQ_OK)
                pq_flush();
}


服务端接收到客户端发过来的经过salt和原密码md5合成后的md5, 校验是否正确.
src/backend/libpq/crypt.c
 * crypt.c
 *        Look into the password file and check the encrypted password with
 *        the one passed in from the frontend.
int
md5_crypt_verify(const Port *port, const char *role, char *client_pass)
{
        int                     retval = STATUS_ERROR;
        char       *shadow_pass,
                           *crypt_pwd;
... 略.
        /*
         * Compare with the encrypted or plain password depending on the
         * authentication method being used for this connection.
         */
        switch (port->hba->auth_method)
        {
                case uaMD5:
                        crypt_pwd = palloc(MD5_PASSWD_LEN + 1);
                        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;
                                }
                        }
                        else
                        {
                                /* stored password is plain, double-encrypt */
                                char       *crypt_pwd2 = palloc(MD5_PASSWD_LEN + 1);

                                if (!pg_md5_encrypt(shadow_pass,
                                                                        port->user_name,
                                                                        strlen(port->user_name),
                                                                        crypt_pwd2))
                                {
                                        pfree(crypt_pwd);
                                        pfree(crypt_pwd2);
                                        return STATUS_ERROR;
                                }
                                if (!pg_md5_encrypt(crypt_pwd2 + strlen("md5"),
                                                                        port->md5Salt,
                                                                        sizeof(port->md5Salt),
                                                                        crypt_pwd))
                                {
                                        pfree(crypt_pwd);
                                        pfree(crypt_pwd2);
                                        return STATUS_ERROR;
                                }
                                pfree(crypt_pwd2);
                        }
                        break;
... 略.

[参考]
1. src/backend/libpq/auth.c
2. src/backend/libpq/crypt.c
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
关系型数据库 PostgreSQL
PostgreSQL 随机记录返回 - 300倍提速实践 (随机数组下标代替order by random())
标签 PostgreSQL , 数组 , 随机 , order by random() 背景 在业务系统中,有些场景会用到随机返回的功能,例如论坛,有很多帖子(比如有100万贴),有些是精华帖(比如有5万贴),为了让精华帖可以均衡的被访问,需要将5万贴随机的分页返回给用户。
1688 0
|
关系型数据库 PostgreSQL 存储
|
关系型数据库 数据库 数据安全/隐私保护
|
关系型数据库 数据库 数据安全/隐私保护
|
关系型数据库 数据库 数据安全/隐私保护
|
关系型数据库 数据安全/隐私保护 PostgreSQL
|
关系型数据库 分布式数据库 PolarDB
《阿里云产品手册2022-2023 版》——PolarDB for PostgreSQL
《阿里云产品手册2022-2023 版》——PolarDB for PostgreSQL
368 0