Generating a strong password in C#?
我想知道如何用C语言生成一个安全可靠的密码。
我搜索了一下,在维基百科上看到了这个公式,其中
另外,我也发现了这个问题,但是由于某种原因,方法
我需要帮助实现这个公式(我不知道从哪里开始)。你也可以提出另一个解决方案,或者解释为什么
我刚刚在LinqPad中尝试了以下方法:
1 | System.Web.Security.Membership.GeneratePassword(25, 10) |
这是我得到的密码:
1 | [XTJ_67g.i/ag1rL)6_Yv>*+% |
号
或者,如果这不够安全,请尝试以下操作:
1 | System.Web.Security.Membership.GeneratePassword(128, 100) |
这让我在运行三次时:
1 2 3 4 5 | |c^.:?m)#q+(]V;}[Z(})/?-;$]+@!|^/8*_9.$&.&!(?=^!Wx?[@%+&-@b;)>N;&+*w[>$2+_$%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^@&$0;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/]{];(&} |
。
这只花了不到一秒钟的时间,顺便说一句,框架是你的朋友。
请参阅http://msdn.microsoft.com/en-us/library/system.web.security.membership.generatepassword.aspx
要解决关于该公式的问题:
该公式表示,从n个符号的字母表中提取的长度为l的密码相当于从两个符号的字母表中提取的长度为h的密码。如果你有64个符号(比如abc…xyzabc…xyz01…89!)密码有10个字符长,这就相当于密码的安全性,10 log2 64=60个字符长,从字母"ab"中提取。
"对数"是求幂的逆运算。二到六次方给你六十四次,因此六十四次方的"对数二"给你六次方。
不确定我在哪里找到这个,但这里有一个类来生成高熵,真正的随机字符串,可以用作密码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | 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); } } |
。
在你的代码中消耗:
1 2 3 | var generator = new PasswordGenerator(); string password = generator.Generate(); Console.WriteLine(password); |
。
我不知道这是否对你有帮助,但当我想生成一个随机的密码时,这也是我要使用的,这个密码也很强。它实现/理解起来既快又简单,而且不像通过上面的成员资格提供商那样杀伤力大…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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); } |
埃多克斯1〔0〕怎么样?
对于不允许用户生成密码的系统来说,实际上非常简单:任何密码都和它的长度一样安全。当然,不算那些把它贴在监视器上的人。
您可能希望最大化从中生成密码的字符集。但是限制生成的密码会大大减少搜索空间,从而降低密码的安全性。同样,只有当用户不能选择自己的密码时,这才有效。
如果您同时处理生成的和用户创建的密码,那么显然,所有的赌注都是关闭的。然后,您可能希望以一种方式生成密码,它使用尽可能多的来自不同类的字符,类似于一个强大的用户选择的密码。理想情况下,它应该符合用户创建的密码必须传递的相同约束(如果有的话)。
为什么不在一个数组中填充一些字符,然后随机选取一些字符呢?您可以将它们分组,以确保包括字母、数字和特殊字符。
您还必须选择一个合适的长度,包括每组字符的多少,就这样。我认为你不需要一些复杂的公式。
我会自己使用guid:,并让用户在登录后编辑密码。