You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何生成SCRAM-SHA-256哈希值以通过.NET5创建PostgreSQL 13用户

核心问题解答

  • PostgreSQL 13+ 使用的SCRAM-SHA-256密码哈希方案不需要在计算前拼接用户名,这一点和旧版MD5哈希规则完全不同。
  • 你可以直接用.NET 5原生的密码学API生成符合PostgreSQL规范的哈希串,不需要依赖第三方组件。

实现逻辑说明

PostgreSQL的SCRAM-SHA-256哈希串遵循固定格式:
SCRAM-SHA-256$<迭代次数>:<Base64编码的盐>$<Base64编码的StoredKey>:<Base64编码的ServerKey>

生成步骤遵循RFC 7677规范:

  1. 用PBKDF2-HMAC-SHA256算法,以明文密码、随机盐、4096次迭代(PostgreSQL默认值)为参数,派生得到32字节的SaltedPassword
  2. 以SaltedPassword为密钥,对字符串Client Key做HMAC-SHA256运算得到Client Key,再对Client Key做SHA256哈希得到StoredKey
  3. 以SaltedPassword为密钥,对字符串Server Key做HMAC-SHA256运算得到Server Key
  4. 把各部分按上述格式拼接即可

.NET 5 实现代码

using System;
using System.Security.Cryptography;
using System.Text;

public static class PostgresPasswordHasher
{
    /// <summary>
    /// 生成PostgreSQL兼容的SCRAM-SHA-256密码哈希
    /// </summary>
    /// <param name="plainPassword">明文密码</param>
    /// <param name="iterations">迭代次数,PostgreSQL默认值为4096</param>
    /// <param name="salt">自定义盐,不传入则自动生成16字节加密安全随机盐</param>
    /// <returns>可直接用于CREATE USER语句的哈希字符串</returns>
    public static string GenerateScramSha256Hash(string plainPassword, int iterations = 4096, byte[] salt = null)
    {
        // 盐处理:未传入则生成16字节加密安全随机盐
        salt ??= new byte[16];
        if (salt.Length == 0)
        {
            RandomNumberGenerator.Fill(salt);
        }

        // 派生SaltedPassword
        using var pbkdf2 = new Rfc2898DeriveBytes(
            password: plainPassword,
            salt: salt,
            iterations: iterations,
            hashAlgorithm: HashAlgorithmName.SHA256);
        byte[] saltedPassword = pbkdf2.GetBytes(32);

        // 计算StoredKey
        byte[] clientKey;
        using (var hmacClient = new HMACSHA256(saltedPassword))
        {
            clientKey = hmacClient.ComputeHash(Encoding.UTF8.GetBytes("Client Key"));
        }
        byte[] storedKey = SHA256.HashData(clientKey);

        // 计算ServerKey
        byte[] serverKey;
        using (var hmacServer = new HMACSHA256(saltedPassword))
        {
            serverKey = hmacServer.ComputeHash(Encoding.UTF8.GetBytes("Server Key"));
        }

        // 拼接为PostgreSQL要求的格式
        return $"SCRAM-SHA-256${iterations}:{Convert.ToBase64String(salt)}${Convert.ToBase64String(storedKey)}:{Convert.ToBase64String(serverKey)}";
    }
}

使用示例

如果要生成明文为postgres的哈希,直接调用方法即可:

var hash = PostgresPasswordHasher.GenerateScramSha256Hash("postgres");

得到的哈希串可以直接填入CREATE USER语句的PASSWORD参数使用,和你示例中的效果完全一致。如果需要复现你给出的示例哈希,只需要把示例中的盐H45+UIZiJUcEXrB9SHlv5Q==转为字节数组传入方法的salt参数即可。

内容的提问来源于stack exchange,提问作者kuja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 12:54:03