在 C# 中生成强密码?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2266721/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Generating a strong password in C#?
提问by Alon Gubkin
I was wondering how I can generate a strong and secure password in C#.
我想知道如何在 C# 中生成一个强大而安全的密码。
I googled a little bit and saw this formula in Wikipedia, where L
is the length of the password and N
is the number of possible symbols:
我用谷歌搜索了一下,在维基百科中看到了这个公式,其中L
是密码的长度和N
可能的符号数:
Also, I've found this question, but for some reason the method Membership.GeneratePassword
just returns a random number with 1 digit, which absolutely no password. All the rest solutions, were very slow (>= 0.5 secs).
另外,我发现了这个问题,但由于某种原因,该方法Membership.GeneratePassword
只返回一个带有 1 位数字的随机数,绝对没有密码。所有其他解决方案都非常慢(> = 0.5 秒)。
I need help implementing this formula (I don't know where to start). You may also suggest another solution or explain why the GeneratePassword
isn't working.
我需要帮助实现这个公式(我不知道从哪里开始)。您也可以建议另一种解决方案或解释为什么GeneratePassword
不起作用。
采纳答案by Joey
I just tried the following in linqpad:
我刚刚在 linqpad 中尝试了以下内容:
System.Web.Security.Membership.GeneratePassword(25, 10)
This is the password I got:
这是我得到的密码:
[XTJ_67g.i/ag1rL)6_Yv>*+%
Or, if that's not secure enough, try this:
或者,如果这还不够安全,请尝试以下操作:
System.Web.Security.Membership.GeneratePassword(128, 100)
which got me the following when running it three times:
运行三遍时,我得到了以下信息:
|c^.:?m)#q+(]V;}[Z(})/?-;$]+@!|^/8*_9.$&.&!(?=^!Wx?[@%+&-@b;)>N;&+*w[>+_$%l;+h+#zhs^{e?&=*(}X_%|:}]]}*X[+)Er%J/-=;Q0{:+=%c7:^$ /:_)hxF+*){2|;(>:*N^+!_&|}B.$})?[V=[+v({-:-@9-Z$j?.[-}(@MHx+}(}Mz_S(7#4}{..>@G|!+++{+C=|_}=+r^@&;L*|kz-;$++/N3$=}?;%&]]*/^#^!+ :*{]-x^$g{|?*))_=B@^.#%L;g|+)#[nq}?y(_(m;]S^I$*q=l-[_/?}&-!k^(+[_{Z|&:^%!_)!=p%=)=wYd-#.UP$%s1{*l%+[%?!c+7=@=.;{+M)!^}&d/]{];(&}private string Token(byte Length) { char[] Chars = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; string String = string.Empty; Random Random = new Random(); for (byte a = 0; a < Length; a++) { String += Chars[Random.Next(0, 61)]; }; return (String); }
this took way less than a second, btw. The framework is your friend.
这花了不到一秒钟的时间,顺便说一句。框架是你的朋友。
See http://msdn.microsoft.com/en-us/library/system.web.security.membership.generatepassword.aspx
请参阅http://msdn.microsoft.com/en-us/library/system.web.security.membership.generatepassword.aspx
回答by anthares
Why not just fill an array with some characters and pick on random a number of them. You can divide them in groups to be sure that are include letters numbers and special characters.
为什么不只用一些字符填充数组并随机选择其中的一些。您可以将它们分组以确保包含字母数字和特殊字符。
You will also have to pick a proper length and how much of every group of characters to include and that's it. I don't think you need some sophisticated formulas.
您还必须选择合适的长度以及要包含的每组字符的数量,仅此而已。我认为你不需要一些复杂的公式。
回答by Joey
For systems that don't allow user-generated passwords it's very easy, actually: Any password is as secure as it's long. Not counting, of course, people who tack post-its to monitors, etc.
对于不允许用户生成密码的系统来说,这很容易,实际上:任何密码都是安全的,因为它很长。当然,不包括将便利贴贴到显示器等的人。
You probably want to maximize the set of characters from which the password is generated. But restricting the generated passwords greatly reduces the search space and therefore makes the password lesssecure. Again, this only holds if the user can't choose their own password.
您可能希望最大化生成密码的字符集。但是,限制生成的密码大大降低了搜索空间,并因此使密码不太安全。同样,这仅适用于用户无法选择自己的密码的情况。
If you deal with both generated and user-created passwords, then all bets are off, obviously. You then probably want to generate the passwords in a way that it uses as many characters from different classes as possible, resembling a strong user-chosen password. Ideally it should conform to the same constraints that the user-created password has to pass as well (if any).
如果您同时处理生成的密码和用户创建的密码,那么显然所有的赌注都没有了。然后,您可能希望以使用尽可能多的来自不同类别的字符的方式生成密码,类似于用户选择的强密码。理想情况下,它应该符合用户创建的密码也必须通过的相同约束(如果有)。
回答by dkackman
How about Guid.NewGuid().ToString();
?
怎么样Guid.NewGuid().ToString();
?
回答by Eric Lippert
To address your question about that formula:
要解决您关于该公式的问题:
The formula is saying that a password of length L drawn from an alphabet of N symbols is equivalent to a password of length H drawn from an alphabet of twosymbols. So if you have, say, 64 symbols (say abc...xyzABC...XYZ01...89_!) and the password is 10 characters long, then that gives you equivalent security to a password 10 log2 64 = 60 characters long drawn from the alphabet "ab".
该公式是说,从 N 个符号的字母表中提取的长度为 L 的密码等效于从两个符号的字母表中提取的长度为 H 的密码。因此,如果您有 64 个符号(例如 abc...xyzABC...XYZ01...89_!)并且密码长度为 10 个字符,那么这为您提供了与密码 10 log2 64 = 60 个字符长度相同的安全性取自字母“ab”。
A "log" is the inverse operation of exponentiation. Two to the sixth power gives you sixty-four, therefore the "log two" of sixty-four gives you six.
“对数”是取幂的逆运算。二的六次方给你六十四,因此六十四的“对数二”给你六。
回答by Ash
I'd use Guid myself :), and make the user edit the password after login
我会自己使用 Guid :),并让用户在登录后编辑密码
回答by Gup3rSuR4c
I don't know if this will help you, but this is what I use when I want to generate a random password which is also strong. It's quick and simple to implement/understand and isn't as much of an overkill as the one through the membership provider above...
我不知道这是否对您有帮助,但是当我想生成一个也很强的随机密码时,这就是我使用的方法。它的实施/理解既快速又简单,并且不像通过上面的会员提供者那样过度...
using System.Security.Cryptography;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class PasswordGenerator
{
public int MinimumLengthPassword { get; private set; }
public int MaximumLengthPassword { get; private set; }
public int MinimumLowerCaseChars { get; private set; }
public int MinimumUpperCaseChars { get; private set; }
public int MinimumNumericChars { get; private set; }
public int MinimumSpecialChars { get; private set; }
public static string AllLowerCaseChars { get; private set; }
public static string AllUpperCaseChars { get; private set; }
public static string AllNumericChars { get; private set; }
public static string AllSpecialChars { get; private set; }
private readonly string _allAvailableChars;
private readonly RandomSecureVersion _randomSecure = new RandomSecureVersion();
private int _minimumNumberOfChars;
static PasswordGenerator()
{
// Define characters that are valid and reject ambiguous characters such as ilo, IO and 1 or 0
AllLowerCaseChars = GetCharRange('a', 'z', exclusiveChars: "ilo");
AllUpperCaseChars = GetCharRange('A', 'Z', exclusiveChars: "IO");
AllNumericChars = GetCharRange('2', '9');
AllSpecialChars = "!@#%*()$?+-=";
}
public PasswordGenerator(
int minimumLengthPassword = 15,
int maximumLengthPassword = 20,
int minimumLowerCaseChars = 2,
int minimumUpperCaseChars = 2,
int minimumNumericChars = 2,
int minimumSpecialChars = 2)
{
if (minimumLengthPassword < 15)
{
throw new ArgumentException("The minimumlength is smaller than 15.",
"minimumLengthPassword");
}
if (minimumLengthPassword > maximumLengthPassword)
{
throw new ArgumentException("The minimumLength is bigger than the maximum length.",
"minimumLengthPassword");
}
if (minimumLowerCaseChars < 2)
{
throw new ArgumentException("The minimumLowerCase is smaller than 2.",
"minimumLowerCaseChars");
}
if (minimumUpperCaseChars < 2)
{
throw new ArgumentException("The minimumUpperCase is smaller than 2.",
"minimumUpperCaseChars");
}
if (minimumNumericChars < 2)
{
throw new ArgumentException("The minimumNumeric is smaller than 2.",
"minimumNumericChars");
}
if (minimumSpecialChars < 2)
{
throw new ArgumentException("The minimumSpecial is smaller than 2.",
"minimumSpecialChars");
}
_minimumNumberOfChars = minimumLowerCaseChars + minimumUpperCaseChars +
minimumNumericChars + minimumSpecialChars;
if (minimumLengthPassword < _minimumNumberOfChars)
{
throw new ArgumentException(
"The minimum length of the password is smaller than the sum " +
"of the minimum characters of all catagories.",
"maximumLengthPassword");
}
MinimumLengthPassword = minimumLengthPassword;
MaximumLengthPassword = maximumLengthPassword;
MinimumLowerCaseChars = minimumLowerCaseChars;
MinimumUpperCaseChars = minimumUpperCaseChars;
MinimumNumericChars = minimumNumericChars;
MinimumSpecialChars = minimumSpecialChars;
_allAvailableChars =
OnlyIfOneCharIsRequired(minimumLowerCaseChars, AllLowerCaseChars) +
OnlyIfOneCharIsRequired(minimumUpperCaseChars, AllUpperCaseChars) +
OnlyIfOneCharIsRequired(minimumNumericChars, AllNumericChars) +
OnlyIfOneCharIsRequired(minimumSpecialChars, AllSpecialChars);
}
private string OnlyIfOneCharIsRequired(int minimum, string allChars)
{
return minimum > 0 || _minimumNumberOfChars == 0 ? allChars : string.Empty;
}
public string Generate()
{
var lengthOfPassword = _randomSecure.Next(MinimumLengthPassword, MaximumLengthPassword);
// Get the required number of characters of each catagory and
// add random charactes of all catagories
var minimumChars = GetRandomString(AllLowerCaseChars, MinimumLowerCaseChars) +
GetRandomString(AllUpperCaseChars, MinimumUpperCaseChars) +
GetRandomString(AllNumericChars, MinimumNumericChars) +
GetRandomString(AllSpecialChars, MinimumSpecialChars);
var rest = GetRandomString(_allAvailableChars, lengthOfPassword - minimumChars.Length);
var unshuffeledResult = minimumChars + rest;
// Shuffle the result so the order of the characters are unpredictable
var result = unshuffeledResult.ShuffleTextSecure();
return result;
}
private string GetRandomString(string possibleChars, int lenght)
{
var result = string.Empty;
for (var position = 0; position < lenght; position++)
{
var index = _randomSecure.Next(possibleChars.Length);
result += possibleChars[index];
}
return result;
}
private static string GetCharRange(char minimum, char maximum, string exclusiveChars = "")
{
var result = string.Empty;
for (char value = minimum; value <= maximum; value++)
{
result += value;
}
if (!string.IsNullOrEmpty(exclusiveChars))
{
var inclusiveChars = result.Except(exclusiveChars).ToArray();
result = new string(inclusiveChars);
}
return result;
}
}
internal static class Extensions
{
private static readonly Lazy<RandomSecureVersion> RandomSecure =
new Lazy<RandomSecureVersion>(() => new RandomSecureVersion());
public static IEnumerable<T> ShuffleSecure<T>(this IEnumerable<T> source)
{
var sourceArray = source.ToArray();
for (int counter = 0; counter < sourceArray.Length; counter++)
{
int randomIndex = RandomSecure.Value.Next(counter, sourceArray.Length);
yield return sourceArray[randomIndex];
sourceArray[randomIndex] = sourceArray[counter];
}
}
public static string ShuffleTextSecure(this string source)
{
var shuffeldChars = source.ShuffleSecure().ToArray();
return new string(shuffeldChars);
}
}
internal class RandomSecureVersion
{
//Never ever ever never use Random() in the generation of anything that requires true security/randomness
//and high entropy or I will hunt you down with a pitchfork!! Only RNGCryptoServiceProvider() is safe.
private readonly RNGCryptoServiceProvider _rngProvider = new RNGCryptoServiceProvider();
public int Next()
{
var randomBuffer = new byte[4];
_rngProvider.GetBytes(randomBuffer);
var result = BitConverter.ToInt32(randomBuffer, 0);
return result;
}
public int Next(int maximumValue)
{
// Do not use Next() % maximumValue because the distribution is not OK
return Next(0, maximumValue);
}
public int Next(int minimumValue, int maximumValue)
{
var seed = Next();
// Generate uniformly distributed random integers within a given range.
return new Random(seed).Next(minimumValue, maximumValue);
}
}
回答by Richard
Not sure where I found this but here's a class to generate high entropy, truly random strings that can be used as passwords.
不确定我在哪里找到的,但这里有一个生成高熵、可用作密码的真正随机字符串的类。
var generator = new PasswordGenerator();
string password = generator.Generate();
Console.WriteLine(password);
Consume in your code thusly:
因此在您的代码中使用:
##代码##