当前位置: 首页 > 知识库问答 >
问题:

如何在C#/Bouncy Castle中创建PBKDF2-SHA256密码哈希

步联
2023-03-14

在这里找到了一些示例代码,但这只适用于SHA1。代码的关键位是:

/// <summary>
/// Computes the PBKDF2-SHA1 hash of a password.
/// </summary>
/// <param name="password">The password to hash.</param>
/// <param name="salt">The salt.</param>
/// <param name="iterations">The PBKDF2 iteration count.</param>
/// <param name="outputBytes">The length of the hash to generate, in bytes.</param>
/// <returns>A hash of the password.</returns>
private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes)
{
    var pdb = new Pkcs5S2ParametersGenerator();
    pdb.Init(PbeParametersGenerator.Pkcs5PasswordToBytes(password.ToCharArray()), salt,
                 iterations);
    var key = (KeyParameter)pdb.GenerateDerivedMacParameters(outputBytes * 8);
    return key.GetKey();
}

我需要把这个从SHA1改成SHA256。

从Java文档和这篇文章来看,下面的内容似乎是可能的,但是C#库中的构造函数没有重载。

var pdb = new Pkcs5S2ParametersGenerator(new Sha256Derived());
var bcparam = (KeyParameter)pdb.GenerateDerivedParameters("sha256", outputBytes * 8);

共有1个答案

楚修为
2023-03-14

编辑(为简洁起见,删除以前的答案历史记录)

现在有一个Bouncy Castle Crypto API NuGet包可以使用。或者,您可以直接从GitHub获取源代码,这将起作用。我从NuGet那里得到了标准的弹力城堡,在写这篇文章的时候,它还没有更新到1.8.1。

为了方便搜索者,这里有一个用于哈希的C#帮助器类。在多个线程上进行了测试,看起来很好。

/// <summary>
/// Contains the relevant Bouncy Castle Methods required to encrypt a password.
/// References NuGet Package BouncyCastle.Crypto.dll
/// </summary>
public class BouncyCastleHashing
{
    private SecureRandom _cryptoRandom;

    public BouncyCastleHashing()
    {
        _cryptoRandom = new SecureRandom();
    }

    /// <summary>
    /// Random Salt Creation
    /// </summary>
    /// <param name="size">The size of the salt in bytes</param>
    /// <returns>A random salt of the required size.</returns>
    public byte[] CreateSalt(int size)
    {
        byte[] salt = new byte[size];
        _cryptoRandom.NextBytes(salt);
        return salt;
    }

    /// <summary>
    /// Gets a PBKDF2_SHA256 Hash  (Overload)
    /// </summary>
    /// <param name="password">The password as a plain text string</param>
    /// <param name="saltAsBase64String">The salt for the password</param>
    /// <param name="iterations">The number of times to encrypt the password</param>
    /// <param name="hashByteSize">The byte size of the final hash</param>
    /// <returns>A base64 string of the hash.</returns>
    public string PBKDF2_SHA256_GetHash(string password, string saltAsBase64String, int iterations, int hashByteSize)
    {
        var saltBytes = Convert.FromBase64String(saltAsBase64String);

        var hash = PBKDF2_SHA256_GetHash(password, saltBytes, iterations, hashByteSize);

        return Convert.ToBase64String(hash);
    }

    /// <summary>
    /// Gets a PBKDF2_SHA256 Hash (CORE METHOD)
    /// </summary>
    /// <param name="password">The password as a plain text string</param>
    /// <param name="salt">The salt as a byte array</param>
    /// <param name="iterations">The number of times to encrypt the password</param>
    /// <param name="hashByteSize">The byte size of the final hash</param>
    /// <returns>A the hash as a byte array.</returns>
    public byte[] PBKDF2_SHA256_GetHash(string password, byte[] salt, int iterations, int hashByteSize)
    {
        var pdb = new Pkcs5S2ParametersGenerator(new Org.BouncyCastle.Crypto.Digests.Sha256Digest());
        pdb.Init(PbeParametersGenerator.Pkcs5PasswordToBytes(password.ToCharArray()), salt,
                     iterations);
        var key = (KeyParameter)pdb.GenerateDerivedMacParameters(hashByteSize * 8);
        return key.GetKey();
    }

    /// <summary>
    /// Validates a password given a hash of the correct one. (OVERLOAD)
    /// </summary>
    /// <param name="password">The original password to hash</param>
    /// <param name="salt">The salt that was used when hashing the password</param>
    /// <param name="iterations">The number of times it was encrypted</param>
    /// <param name="hashByteSize">The byte size of the final hash</param>
    /// <param name="hashAsBase64String">The hash the password previously provided as a base64 string</param>
    /// <returns>True if the hashes match</returns>
    public bool ValidatePassword(string password, string salt, int iterations, int hashByteSize, string hashAsBase64String)
    {
        byte[] saltBytes = Convert.FromBase64String(salt);
        byte[] actualHashBytes = Convert.FromBase64String(hashAsBase64String);
        return ValidatePassword(password, saltBytes, iterations, hashByteSize, actualHashBytes);
    }

    /// <summary>
    /// Validates a password given a hash of the correct one (MAIN METHOD).
    /// </summary>
    /// <param name="password">The password to check.</param>
    /// <param name="correctHash">A hash of the correct password.</param>
    /// <returns>True if the password is correct. False otherwise.</returns>
    public bool ValidatePassword(string password, byte[] saltBytes, int iterations, int hashByteSize, byte[] actualGainedHasAsByteArray)
    {
        byte[] testHash = PBKDF2_SHA256_GetHash(password, saltBytes, iterations, hashByteSize);
        return SlowEquals(actualGainedHasAsByteArray, testHash);
    }

    /// <summary>
    /// Compares two byte arrays in length-constant time. This comparison
    /// method is used so that password hashes cannot be extracted from
    /// on-line systems using a timing attack and then attacked off-line.
    /// </summary>
    /// <param name="a">The first byte array.</param>
    /// <param name="b">The second byte array.</param>
    /// <returns>True if both byte arrays are equal. False otherwise.</returns>
    private bool SlowEquals(byte[] a, byte[] b)
    {
        uint diff = (uint)a.Length ^ (uint)b.Length;
        for (int i = 0; i < a.Length && i < b.Length; i++)
            diff |= (uint)(a[i] ^ b[i]);
        return diff == 0;
    }

}
public void CreatePasswordHash_Single()
{
    int iterations = 100000; // The number of times to encrypt the password - change this
    int saltByteSize = 64; // the salt size - change this
    int hashByteSize = 128; // the final hash - change this

    BouncyCastleHashing mainHashingLib = new BouncyCastleHashing();

    var password = "password"; // That's really secure! :)

    byte[] saltBytes = mainHashingLib.CreateSalt(saltByteSize);
    string saltString = Convert.ToBase64String(saltBytes);

    string pwdHash = mainHashingLib.PBKDF2_SHA256_GetHash(password, saltString, iterations, hashByteSize);

    var isValid = mainHashingLib.ValidatePassword(password, saltBytes, iterations, hashByteSize, Convert.FromBase64String(pwdHash));

}
 类似资料:
  • 我一直在研究散列/加密密码并将其存储在数据库中的正确方法。我知道盐和散列,所以我环顾四周,PBKDF2似乎是一个不错的选择。所以我找到了这个网站,它提供了一个很好的教程,以及一个适用于PHP的PBKDF2(这是我在我的网站上使用的)。 因此,我设置了我的网站,以使用这些功能生成/创建密码,但正如您在以下代码中看到的: salt在create_散列函数中生成,并存储在生成的散列中,该散列最终看起来像

  • 求求你帮帮我!我正在尝试使用pbkdf2-sha256算法哈希密码。Password=“user1”,salt=“ifo7kxyswe7fiu3bovnowg=”,hashIterations=“27500”。我知道结果。必须类似于“ZnxO94AYITK7T+OJ1PXPZTVEQ+G82LFWT6VNSTBHZPEUWZGMPRJJVKAUEXGH1IQPZWMX1SRVTUMLN/JCM8G

  • 问题内容: 我正在尝试为Laravel创建哈希密码。现在有人告诉我使用Laravel哈希帮助器,但我似乎找不到它,或者我的方向错误。 如何创建laravel哈希密码?在哪 编辑:我知道代码是什么,但我不知道在哪里以及如何使用它,因此它给了我哈希密码。如果得到哈希密码,则可以手动将其插入数据库 问题答案: 使用Bcrypt散列密码: 这将创建一个哈希密码。您可以在控制器中甚至在模型中使用它,例如,如

  • 我生成一个不对称密码密钥对,如下所示: 我的意图是提取公钥和私钥,然后在以后重建密钥。我首先提取了如下密钥: 如何重新创建公钥和私钥参数以便使用它们?在本例中,我确实重新创建了私钥,然后对数据字节数组进行签名。 虽然它感觉像一个真正的黑客,但它工作得很好。如何使用公钥执行此操作?我将变量xxx设置为(ECPublicKeyParameters)aKeyPair。Public和我可以使用下面的代码验

  • 我正在为Web应用程序制作登录系统。要将密码存储在数据库中,我正在使用sha256加密密码,如下所示: 在数据库中,我存储了用户、用户密码和用于散列和验证用户登录的salt。现在,我正在向用户发送包含您的密码的电子邮件,但是当用户收到电子邮件时,由于存储在sha256加密密码中,用户收到的是一个长字符串,而不是用户应该知道的密码。 我的问题是,我可以通过任何方法向您发送实际的用户密码和非密码加密,

  • 问题内容: 我需要解密密码。密码已使用功能加密。 现在,我们假设它存储在数据库中(有一个“用户”表,其中包含用户名,密码等),我需要登录:我必须查看用户输入的密码是否与存储在其中的加密密码匹配。数据库。 这是SQL代码… …但未加密,因此不等于表用户的密码字段中存储的内容… 所以,有一个使用?后解密的功能。还是应该更改我的加密方法?或者还有什么? 问题答案: Bcrypt是一种单向哈希算法,您无法