【发布时间】:2012-08-17 15:09:30
【问题描述】:
所以我最近为密码相关方法创建了一个静态类,并且必须创建一个生成安全盐的方法。
最初我实现了RNGCryptoServiceProvider并将n个字节归档到一个数组中,我将其转换为base64并返回。
问题在于输出长度在转换后当然比 n (which makes sense) 长。
为了解决这个问题,我将函数更改为下面的方法,我只是想知道通过修剪 base64 字符串是否会引发任何安全风险?
/// <summary>
/// Generates a salt for use with the Hash method.
/// </summary>
/// <param name="length">The length of string to generate.</param>
/// <returns>A cryptographically secure random salt.</returns>
public static string GenerateSalt(int length)
{
// Check the length isn't too short.
if (length < MIN_LENGTH)
{
throw new ArgumentOutOfRangeException("length", "Please increase the salt length to meet the minimum acceptable value of " + MIN_LENGTH + " characters.");
}
// Calculate the number of bytes required.
// https://en.wikipedia.org/wiki/Base64#Padding
// http://stackoverflow.com/questions/17944/how-to-round-up-the-result-of-integer-division
int bytelen = ((3 * length) + 4 - 1) / 4;
// Create our empty salt array.
byte[] bytes = new byte[bytelen];
// Where we'll put our generated salt.
string salt;
// Generate a random secure salt.
using (RNGCryptoServiceProvider randcrypto = new RNGCryptoServiceProvider())
{
// Fill our array with random bytes.
randcrypto.GetBytes(bytes);
// Get a base64 string from the random byte array.
salt = GetBase64(bytes);
}
// Trim the end off only if we need to.
if (salt.Length > length)
{
// Substring is the fastest method to use.
salt = salt.Substring(0, length);
}
// Return the salt.
return salt;
}
另外作为一个附带问题,我快速浏览了一下,实际上找不到RNGCryptoServiceProvider 的C# 实现的哈希函数实际上是什么。有人知道吗?
【问题讨论】:
-
为什么要将盐作为字符串传递?为什么这个 string 的长度是关键工厂?
-
@Damien_The_Unbeliever 对于当盐存储在数据库中时,知道你会得到什么样的输出是更实际的。
-
几乎我听说过的每个数据库都有一些机制可以让你存储二进制数据。
-
作为旁注,我认为您的
Calculate the number of bytes required行不正确。作为指导,0 => 0、2 => 1 和 3 => 2(然后 4 => 3、6 => 4 等),但 1 应该没有意义,因为没有输入可以生成长度为 1 的 Base64 字符串(模式 4)。
标签: c# hash cryptography base64 salt