用户的密码设定是网络安全的重中之重,生成安全密码,在重要的网络数据安全中尤显重要。重要的用户密码很需要帮助他们随机生成高强度的密码。一般随机数都是伪随机,我们需要不同的种子,让它无限接近于真随机。下面就是一个生成随机密码的类,并根据密码的长度和密码字符的种类进行赋值判断强度。
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
namespace GeneratePassword
{
public partial class GeneratePassword
{
private const int minimumNumberOfChars = 4;//最小密码长度
/// <summary>
/// 随机生成密码
/// </summary>
/// <param name="mumNumberOfChars" 指定的密码长度></param>
/// <param name="minimumLowerCaseChars" 小写字母最小位数></param>
/// <param name="minimumUpperCaseChars" 大写字母最小位数></param>
/// <param name="minimumNumericChars" 数字最小位数></param>
/// <param name="minimumSpecialChars" 特殊字符最小位数></param>
/// <returns>"GeneratePassword"</returns>
public string GenerateNewPassword(int mumNumberOfChars, int minimumLowerCaseChars, int minimumUpperCaseChars, int minimumNumericChars, int minimumSpecialChars)
{
if (mumNumberOfChars < minimumNumberOfChars)
{
throw new ArgumentException("最小密码长度不能小于4位!");
}
if (minimumLowerCaseChars < 0 || minimumUpperCaseChars < 0 || minimumNumericChars < 0 || minimumSpecialChars < 0)
{
throw new ArgumentException("参数不能小于0!");
}
if (mumNumberOfChars < minimumLowerCaseChars + minimumUpperCaseChars + minimumNumericChars + minimumSpecialChars)
{
throw new ArgumentException("密码长度不能小于4个分类字符最小位数之和!");
}
string allAvailableChars;
var allLowerCaseChars = "abcdefghijkmnpqrstuvwxyz";//不使用ol,避免混淆或看不清,以下同
var allUpperCaseChars = "ABCDEFGHIJKLMNPQRSTUVWXYZ";//不使用O
var allNumericChars = "23456789";//不使用01
var allSpecialChars = @"~!@#$%&*_-+=|\(){}[]<>?/";//不使用^`:;,.
StringBuilder stringBuilder = new();
stringBuilder.Append(GetOnlyIfOneCharIsRequired(mumNumberOfChars, minimumLowerCaseChars, allLowerCaseChars));
stringBuilder.Append(GetOnlyIfOneCharIsRequired(mumNumberOfChars, minimumUpperCaseChars, allUpperCaseChars));
stringBuilder.Append(GetOnlyIfOneCharIsRequired(mumNumberOfChars, minimumNumericChars, allNumericChars));
stringBuilder.Append(GetOnlyIfOneCharIsRequired(mumNumberOfChars, minimumSpecialChars, allSpecialChars));
allAvailableChars = stringBuilder.ToString();
return GetRandomString(allAvailableChars, mumNumberOfChars);
}
private string GetOnlyIfOneCharIsRequired(int mumNumberOfChars, int minimum, string allChars)
{
return minimum > 0 || mumNumberOfChars == 0 ? allChars : string.Empty;
}
private string GetRandomString(string possibleChars, int lenght)
{
var result = string.Empty;
for (var position = 0; position < lenght; position++)
{
var index = Next(possibleChars.Length);
result += possibleChars[index];
}
return result;
}
private int Next()
{
var randomBuffer = new byte[4];
using (var generator = RandomNumberGenerator.Create())
{
generator.GetBytes(randomBuffer);
}
var result = BitConverter.ToInt32(randomBuffer, 0);
return result;
}
private int Next(int maximumValue)
{
// 不要使用Next()%maximumValue,因为分布不正常
return Next(0, maximumValue);
}
private int Next(int minimumValue, int maximumValue)
{
var seed = Next();
// 在给定范围内生成均匀分布的随机整数。
return new Random(seed).Next(minimumValue, maximumValue);
}
public string GetPasswordStrength(string password)
{
if (password == null || password.Length < minimumNumberOfChars)
{
throw new ArgumentException("密码不能为空或小于4位数");
}
var result = string.Empty;
var count = 0;
if (NumberRegex().IsMatch(password))
{
count += 10;
}
if (LowerRegex().IsMatch(password))
{
count += 26;
}
if (UpperRegex().IsMatch(password))
{
count += 26;
}
if (PunctuationRegex().IsMatch(password))
{
count += 31;
}
double strength = Math.Log(Math.Pow(count, password.Length)) / Math.Log(2);
if (strength <= 32) { result = "Weak"; }
else if (strength <= 64) { result = "Good"; }
else if (strength <= 128) { result = "Strong"; }
else if (strength > 128) { result = "Very strong"; }
return result;
}
[GeneratedRegex("[\\d]")]
private static partial Regex NumberRegex();
[GeneratedRegex("[a-z]")]
private static partial Regex LowerRegex();
[GeneratedRegex("[A-Z]")]
private static partial Regex UpperRegex();
[GeneratedRegex("[\\W|_]")]
private static partial Regex PunctuationRegex();
}
}
这个类是根据 https://github.com/it-nilesh/password-generator/blob/master/PasswordGenerator 的源码简化修改而成。