【问题标题】:When merging two arrays, the first array gets shorter by 1合并两个数组时,第一个数组变短 1
【发布时间】:2019-03-09 17:45:23
【问题描述】:

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

AAAAAAAAAAAAAAAAAAAAAA==

在过程结束时,它们都是字节数组,然后我将它们合并到一个新的字节数组中。

我的问题是,在将密码与盐合并时,我的哈希密码在最后缩短了一个字符。

预期输出:

uIxnpgdBQpSPJrqwYucIOeyOyqyCv7HbBfd74ovoxjI=AAAAAAAAAAAAAAAAAAAAAAAAA==

输出:

uIxnpgdBQpSPJrqwYucIOeyOyqyCv7HbBfd74ovoxjIAAAAAAAAAAAAAAAAAAAAAAAAAAAA==

如您所见,在 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;
}

如何防止密码被缩短?

【问题讨论】:

  • 在第二个 Array.Copy 中应该是 hInput.Length+1
  • 它仍然带走了我的散列密码的“=”
  • @kelalaka: 不,我不应该是hInput.Length+1,因为第一部分的索引范围是0..Length - 1Length 自动成为第二部分的起始索引。跨度>
  • 我尝试的是在第一个 Copy 中将 + 1 添加到 hInput.Length ,但这也不起作用。
  • 如果你是 Base64 编码连接的字节数组,你将永远在结果中间得到一个=,Base64 只在末尾添加=如果原始输入的长度不是 3 的倍数,则作为填充字符串。如果您可以 Base64 解码结果并取回正确的原始输入,那么看起来一切正常。

标签: c# arrays .net security password-protection


【解决方案1】:

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

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 不可行。 salt不需要加密。您可能还希望将其存储为 base 64 字符串。要再次获取盐字节,您需要Convert.FromBase64String()

【讨论】:

    猜你喜欢
    • 2012-03-31
    • 1970-01-01
    • 2021-07-16
    • 1970-01-01
    • 1970-01-01
    • 2015-12-31
    • 2019-01-27
    • 2021-02-24
    • 1970-01-01
    相关资源
    最近更新 更多