合并两个数组时,第一个数组变短 1

When merging two arrays, the first array gets shorter by 1

我有一个用 SHA256 散列的密码。然后我有一个看起来像这样的盐:

AAAAAAAAAAAAAAAAAAAAAAAAAA==

在这个过程的最后,它们都是字节数组,然后我将它们合并成一个新的字节数组。

我的问题是在将密码与盐合并时,我的散列密码在末尾缩短了一个字符。

预期输出:

uIxnpgdBQpSPJrqwYucIOeyOyqyCv7HbBfd74ovoxjI=AAAAAAAAAAAAAAAAAAAAAAAAAA==

输出:

uIxnpgdBQpSPJrqwYucIOeyOyqyCv7HbBfd74ovoxjIAAAAAAAAAAAAAAAAAAAAAAAAA==

如您所见,在 l.

之后缺少 =

我的方法:

public static byte[] HashPassword(byte[] passwordToHash)
{
    byte[] hInput;
    byte[] hSalt = GetSalt();
    using(SHA256 sh = SHA256.Create())
    {
        hInput = sh.ComputeHash(passwordToHash);
    }
    byte[] SaltedPw = new byte[(hInput.Length+ 1 ) + (hSalt.Length + 3)];
    Array.Copy(hInput,0, SaltedPw, 0,hInput.Length);
    Array.Copy(hSalt, 0, SaltedPw, hInput.Length, hSalt.Length);
    return SaltedPw;
}

public static byte[] GetSalt()
{
    byte[] salt = new byte[16];
    return salt;
}

如何防止我的密码被缩短?

你做错了。您不得将盐添加到散列密码中。您必须将盐添加到纯密码中,然后进行哈希处理。重点是使当前密码或短密码的哈希无法识别。

base 64 编码仅应用于最终结果,以允许将密码哈希存储为字符串。因此,您永远不必合并 base 64 字符串。 Base 64 字符串在末尾用 = 填充以获得长度是 4 的倍数。因此你永远不会在中间看到 =

public static string GetHashedPassword(string plainPassword, byte[] salt)
{
    byte[] passwordBytes = GetBytes(plainPassword);

    // Merge the password bytes and the salt bytes
    var mergedBytes = new byte[passwordBytes.Length + salt.Length];
    Array.Copy(passwordBytes, mergedBytes, passwordBytes.Length);
    Array.Copy(salt, 0, mergedBytes, passwordBytes.Length, salt.Length);

    // Now hash password + salt
    byte[] hash;
    using (var sha = SHA256.Create()) {
        hash = sha.ComputeHash(mergedBytes);
    }
    return Base64Encode(hash);
}

您还需要这个:

public static string Base64Encode(byte[] bytes)
{
    return System.Convert.ToBase64String(bytes);
}

static byte[] GetBytes(string str)
{
    byte[] bytes = new byte[str.Length * sizeof(char)];
    System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
    return bytes;
}

为每个密码创建随机盐字节,并将盐作为单独的信息与散列密码一起存储。像这样,每个密码都有不同的盐。这使得 Pre-computed dictionary attack/Rainbow table attack 不可行。盐不需要加密。您可能还想将其存储为 base 64 字符串。要再次获取盐字节,您将需要 Convert.FromBase64String().