質問
当社サイトのユーザーがパスワードを紛失し、「パスワード紛失」ページに移動した場合、新しい一時パスワードを与える必要があります。これがどれほどランダムであるか、または「必要な」強力なパスワード ルールがすべて一致するかどうかはあまり気にしません。私がしたいのは、後で変更できるパスワードをユーザーに与えることだけです。
このアプリケーションは、C# で書かれた Web アプリケーションです。そこで私は意地悪をして、Guid の一部を使用するという簡単な方法を選択しようと考えていました。つまり
Guid.NewGuid().ToString("d").Substring(1,8)
提案はありますか?考えは?
他のヒント
public string CreatePassword(int length)
{
const string valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
StringBuilder res = new StringBuilder();
Random rnd = new Random();
while (0 < length--)
{
res.Append(valid[rnd.Next(valid.Length)]);
}
return res.ToString();
}
これには、生成されたパスワードとして使用可能な文字のリストから選択できるという良い利点があります (例:数字のみ、大文字のみ、小文字のみなど)
私のコードの主な目標は次のとおりです。
- 文字列の分布はほぼ均一です (小さい限り、多少のずれは気にしないでください)
- 各引数セットに対して数十億を超える文字列が出力されます。PRNG が 20 億 (31 ビットのエントロピー) の異なる値しか生成しない場合、8 文字の文字列 (約 47 ビットのエントロピー) を生成しても意味がありません。
- 人々がこれをパスワードやその他のセキュリティ トークンに使用すると予想されるため、これは安全です。
最初のプロパティは、アルファベット サイズを法とする 64 ビット値を取得することによって実現されます。小さなアルファベット (質問の 62 文字など) の場合、これは無視できる程度のバイアスにつながります。2 番目と 3 番目のプロパティは、次を使用して実現されます。 RNGCryptoServiceProvider
の代わりに System.Random
.
using System;
using System.Security.Cryptography;
public static string GetRandomAlphanumericString(int length)
{
const string alphanumericCharacters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
"abcdefghijklmnopqrstuvwxyz" +
"0123456789";
return GetRandomString(length, alphanumericCharacters);
}
public static string GetRandomString(int length, IEnumerable<char> characterSet)
{
if (length < 0)
throw new ArgumentException("length must not be negative", "length");
if (length > int.MaxValue / 8) // 250 million chars ought to be enough for anybody
throw new ArgumentException("length is too big", "length");
if (characterSet == null)
throw new ArgumentNullException("characterSet");
var characterArray = characterSet.Distinct().ToArray();
if (characterArray.Length == 0)
throw new ArgumentException("characterSet must not be empty", "characterSet");
var bytes = new byte[length * 8];
new RNGCryptoServiceProvider().GetBytes(bytes);
var result = new char[length];
for (int i = 0; i < length; i++)
{
ulong value = BitConverter.ToUInt64(bytes, i * 8);
result[i] = characterArray[value % (uint)characterArray.Length];
}
return new string(result);
}
(これは私の回答のコピーです C# でランダムな 8 文字の英数字文字列を生成するにはどうすればよいですか?)
ランダムなトークンを生成する方法は次のとおりです。
public string GenerateToken(int length)
{
RNGCryptoServiceProvider cryptRNG = new RNGCryptoServiceProvider();
byte[] tokenBuffer = new byte[length];
cryptRNG.GetBytes(tokenBuffer);
return Convert.ToBase64String(tokenBuffer);
}
これは Base-64 文字列を返すため、出力の長さは常に 4 の倍数であり、余分なスペースは次のようになります。 =
パディング文字として。の length
パラメータは、出力文字列ではなく、バイト バッファの長さを指定します (したがって、今考えてみると、おそらくそのパラメータに最適な名前ではありません)。これは、バイト数を制御します エントロピ パスワードはあります。ただし、base-64 は 4 文字のブロックを使用して入力の各 3 バイトをエンコードするため、3 の倍数ではない長さを要求すると、余分な「スペース」が存在し、 =
余分なものを埋めるために。
何らかの理由で Base64 文字列を使用したくない場合は、 Convert.ToBase64String()
通常の文字列への変換、または次のいずれかを使用して呼び出します。 Encoding
メソッド。例えば。 Encoding.UTF8.GetString(tokenBuffer)
- RNG から出力される値の全範囲を表現でき、これを送信または保存する場所と互換性のある文字を生成する文字セットを必ず選択してください。たとえば、Unicode を使用すると、大量の漢字が生成される傾向があります。Base-64 を使用すると、広く互換性のある文字セットが保証され、適切なハッシュ アルゴリズムを使用している限り、そのような文字列の特性によって安全性が低下することはありません。
これはかなり大きいですが、もう少し包括的に見えると思います。http://www.obviex.com/Samples/Password.aspx
///////////////////////////////////////////////////////////////////////////////
// SAMPLE: Generates random password, which complies with the strong password
// rules and does not contain ambiguous characters.
//
// To run this sample, create a new Visual C# project using the Console
// Application template and replace the contents of the Class1.cs file with
// the code below.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
//
// Copyright (C) 2004 Obviex(TM). All rights reserved.
//
using System;
using System.Security.Cryptography;
/// <summary>
/// This class can generate random passwords, which do not include ambiguous
/// characters, such as I, l, and 1. The generated password will be made of
/// 7-bit ASCII symbols. Every four characters will include one lower case
/// character, one upper case character, one number, and one special symbol
/// (such as '%') in a random order. The password will always start with an
/// alpha-numeric character; it will not start with a special symbol (we do
/// this because some back-end systems do not like certain special
/// characters in the first position).
/// </summary>
public class RandomPassword
{
// Define default min and max password lengths.
private static int DEFAULT_MIN_PASSWORD_LENGTH = 8;
private static int DEFAULT_MAX_PASSWORD_LENGTH = 10;
// Define supported password characters divided into groups.
// You can add (or remove) characters to (from) these groups.
private static string PASSWORD_CHARS_LCASE = "abcdefgijkmnopqrstwxyz";
private static string PASSWORD_CHARS_UCASE = "ABCDEFGHJKLMNPQRSTWXYZ";
private static string PASSWORD_CHARS_NUMERIC= "23456789";
private static string PASSWORD_CHARS_SPECIAL= "*$-+?_&=!%{}/";
/// <summary>
/// Generates a random password.
/// </summary>
/// <returns>
/// Randomly generated password.
/// </returns>
/// <remarks>
/// The length of the generated password will be determined at
/// random. It will be no shorter than the minimum default and
/// no longer than maximum default.
/// </remarks>
public static string Generate()
{
return Generate(DEFAULT_MIN_PASSWORD_LENGTH,
DEFAULT_MAX_PASSWORD_LENGTH);
}
/// <summary>
/// Generates a random password of the exact length.
/// </summary>
/// <param name="length">
/// Exact password length.
/// </param>
/// <returns>
/// Randomly generated password.
/// </returns>
public static string Generate(int length)
{
return Generate(length, length);
}
/// <summary>
/// Generates a random password.
/// </summary>
/// <param name="minLength">
/// Minimum password length.
/// </param>
/// <param name="maxLength">
/// Maximum password length.
/// </param>
/// <returns>
/// Randomly generated password.
/// </returns>
/// <remarks>
/// The length of the generated password will be determined at
/// random and it will fall with the range determined by the
/// function parameters.
/// </remarks>
public static string Generate(int minLength,
int maxLength)
{
// Make sure that input parameters are valid.
if (minLength <= 0 || maxLength <= 0 || minLength > maxLength)
return null;
// Create a local array containing supported password characters
// grouped by types. You can remove character groups from this
// array, but doing so will weaken the password strength.
char[][] charGroups = new char[][]
{
PASSWORD_CHARS_LCASE.ToCharArray(),
PASSWORD_CHARS_UCASE.ToCharArray(),
PASSWORD_CHARS_NUMERIC.ToCharArray(),
PASSWORD_CHARS_SPECIAL.ToCharArray()
};
// Use this array to track the number of unused characters in each
// character group.
int[] charsLeftInGroup = new int[charGroups.Length];
// Initially, all characters in each group are not used.
for (int i=0; i<charsLeftInGroup.Length; i++)
charsLeftInGroup[i] = charGroups[i].Length;
// Use this array to track (iterate through) unused character groups.
int[] leftGroupsOrder = new int[charGroups.Length];
// Initially, all character groups are not used.
for (int i=0; i<leftGroupsOrder.Length; i++)
leftGroupsOrder[i] = i;
// Because we cannot use the default randomizer, which is based on the
// current time (it will produce the same "random" number within a
// second), we will use a random number generator to seed the
// randomizer.
// Use a 4-byte array to fill it with random bytes and convert it then
// to an integer value.
byte[] randomBytes = new byte[4];
// Generate 4 random bytes.
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(randomBytes);
// Convert 4 bytes into a 32-bit integer value.
int seed = BitConverter.ToInt32(randomBytes, 0);
// Now, this is real randomization.
Random random = new Random(seed);
// This array will hold password characters.
char[] password = null;
// Allocate appropriate memory for the password.
if (minLength < maxLength)
password = new char[random.Next(minLength, maxLength+1)];
else
password = new char[minLength];
// Index of the next character to be added to password.
int nextCharIdx;
// Index of the next character group to be processed.
int nextGroupIdx;
// Index which will be used to track not processed character groups.
int nextLeftGroupsOrderIdx;
// Index of the last non-processed character in a group.
int lastCharIdx;
// Index of the last non-processed group.
int lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
// Generate password characters one at a time.
for (int i=0; i<password.Length; i++)
{
// If only one character group remained unprocessed, process it;
// otherwise, pick a random character group from the unprocessed
// group list. To allow a special character to appear in the
// first position, increment the second parameter of the Next
// function call by one, i.e. lastLeftGroupsOrderIdx + 1.
if (lastLeftGroupsOrderIdx == 0)
nextLeftGroupsOrderIdx = 0;
else
nextLeftGroupsOrderIdx = random.Next(0,
lastLeftGroupsOrderIdx);
// Get the actual index of the character group, from which we will
// pick the next character.
nextGroupIdx = leftGroupsOrder[nextLeftGroupsOrderIdx];
// Get the index of the last unprocessed characters in this group.
lastCharIdx = charsLeftInGroup[nextGroupIdx] - 1;
// If only one unprocessed character is left, pick it; otherwise,
// get a random character from the unused character list.
if (lastCharIdx == 0)
nextCharIdx = 0;
else
nextCharIdx = random.Next(0, lastCharIdx+1);
// Add this character to the password.
password[i] = charGroups[nextGroupIdx][nextCharIdx];
// If we processed the last character in this group, start over.
if (lastCharIdx == 0)
charsLeftInGroup[nextGroupIdx] =
charGroups[nextGroupIdx].Length;
// There are more unprocessed characters left.
else
{
// Swap processed character with the last unprocessed character
// so that we don't pick it until we process all characters in
// this group.
if (lastCharIdx != nextCharIdx)
{
char temp = charGroups[nextGroupIdx][lastCharIdx];
charGroups[nextGroupIdx][lastCharIdx] =
charGroups[nextGroupIdx][nextCharIdx];
charGroups[nextGroupIdx][nextCharIdx] = temp;
}
// Decrement the number of unprocessed characters in
// this group.
charsLeftInGroup[nextGroupIdx]--;
}
// If we processed the last group, start all over.
if (lastLeftGroupsOrderIdx == 0)
lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
// There are more unprocessed groups left.
else
{
// Swap processed group with the last unprocessed group
// so that we don't pick it until we process all groups.
if (lastLeftGroupsOrderIdx != nextLeftGroupsOrderIdx)
{
int temp = leftGroupsOrder[lastLeftGroupsOrderIdx];
leftGroupsOrder[lastLeftGroupsOrderIdx] =
leftGroupsOrder[nextLeftGroupsOrderIdx];
leftGroupsOrder[nextLeftGroupsOrderIdx] = temp;
}
// Decrement the number of unprocessed groups.
lastLeftGroupsOrderIdx--;
}
}
// Convert password characters into a string and return the result.
return new string(password);
}
}
/// <summary>
/// Illustrates the use of the RandomPassword class.
/// </summary>
public class RandomPasswordTest
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
// Print 100 randomly generated passwords (8-to-10 char long).
for (int i=0; i<100; i++)
Console.WriteLine(RandomPassword.Generate(8, 10));
}
}
//
// END OF FILE
///////////////////////////////////////////////////////////////////////////////
これが古いスレッドであることは承知していますが、誰かが使用できる非常に簡単な解決策となる可能性のあるものを用意しました。実装が簡単、理解が簡単、検証が簡単です。
次の要件を考慮してください。
少なくとも 2 つの小文字、2 つの大文字、2 つの数字を含むランダムなパスワードを生成する必要があります。パスワードの長さも 8 文字以上である必要があります。
次の正規表現でこのケースを検証できます。
^(?=\b\w*[a-z].*[a-z]\w*\b)(?=\b\w*[A-Z].*[A-Z]\w*\b)(?=\b\w*[0-9].*[0-9]\w*\b)[a-zA-Z0-9]{8,}$
それはこの質問の範囲外ですが、正規表現はに基づいています 先読み/後読み そして 見回す.
次のコードは、この要件に一致するランダムな文字セットを作成します。
public static string GeneratePassword(int lowercase, int uppercase, int numerics) {
string lowers = "abcdefghijklmnopqrstuvwxyz";
string uppers = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string number = "0123456789";
Random random = new Random();
string generated = "!";
for (int i = 1; i <= lowercase; i++)
generated = generated.Insert(
random.Next(generated.Length),
lowers[random.Next(lowers.Length - 1)].ToString()
);
for (int i = 1; i <= uppercase; i++)
generated = generated.Insert(
random.Next(generated.Length),
uppers[random.Next(uppers.Length - 1)].ToString()
);
for (int i = 1; i <= numerics; i++)
generated = generated.Insert(
random.Next(generated.Length),
number[random.Next(number.Length - 1)].ToString()
);
return generated.Replace("!", string.Empty);
}
上記の要件を満たすには、次のように呼び出すだけです。
String randomPassword = GeneratePassword(3, 3, 3);
コードが無効な文字 ("!"
) - 文字列が新しい文字を挿入できる長さになるようにします。
次に、1 から必要な小文字の数までループし、各反復で小文字リストからランダムな項目を取得し、文字列内のランダムな位置に挿入します。
次に、大文字と数字に対してループを繰り返します。
これにより、長さ = の文字列が返されます。 lowercase + uppercase + numerics
希望する数の小文字、大文字、数字がランダムな順序で配置されます。
この種のパスワードについては、より「使用されやすい」パスワードを生成しそうなシステムを使用することが多いです。短く、多くの場合、発音可能な断片といくつかの数字で構成され、文字間の曖昧さはありません (0 ですか、それとも O ですか?)。1 ですか、それとも I ですか?)何かのようなもの
string[] words = { 'bur', 'ler', 'meh', 'ree' };
string word = "";
Random rnd = new Random();
for (i = 0; i < 3; i++)
word += words[rnd.Next(words.length)]
int numbCount = rnd.Next(4);
for (i = 0; i < numbCount; i++)
word += (2 + rnd.Next(7)).ToString();
return word;
(ブラウザに直接入力しているため、ガイドラインとしてのみ使用してください。また、単語を追加してください)。
わたしは作った このクラス RNGCryptoServiceProvider を使用しており、柔軟性があります。例:
var generator = new PasswordGenerator(minimumLengthPassword: 8,
maximumLengthPassword: 15,
minimumUpperCaseChars: 2,
minimumNumericChars: 3,
minimumSpecialChars: 2);
string password = generator.Generate();
Membership.GeneratePassword() が作成するパスワードはあまりにも醜く、特殊文字が多すぎるため、私は好きではありません。
このコードは、10 桁のそれほど醜くないパスワードを生成します。
string password = Guid.NewGuid().ToString("N").ToLower()
.Replace("1", "").Replace("o", "").Replace("0","")
.Substring(0,10);
もちろん、正規表現を使用してすべての置換を行うこともできますが、IMO ではこの方が読みやすく保守しやすいです。
私は KeePass に組み込まれたパスワード生成機能にいつもとても満足しています。KeePass は .Net プログラムであり、オープンソースなので、コードを少し調べてみることにしました。結局、標準のアプリケーション インストールで提供されるコピーである KeePass.exe をプロジェクト内の参照として参照し、以下のコードを記述することになりました。KeePass のおかげで、それがいかに柔軟であるかがわかります。長さ、含める/含めない文字などを指定できます。
using KeePassLib.Cryptography.PasswordGenerator;
using KeePassLib.Security;
public static string GeneratePassword(int passwordLength, bool lowerCase, bool upperCase, bool digits,
bool punctuation, bool brackets, bool specialAscii, bool excludeLookAlike)
{
var ps = new ProtectedString();
var profile = new PwProfile();
profile.CharSet = new PwCharSet();
profile.CharSet.Clear();
if (lowerCase)
profile.CharSet.AddCharSet('l');
if(upperCase)
profile.CharSet.AddCharSet('u');
if(digits)
profile.CharSet.AddCharSet('d');
if (punctuation)
profile.CharSet.AddCharSet('p');
if (brackets)
profile.CharSet.AddCharSet('b');
if (specialAscii)
profile.CharSet.AddCharSet('s');
profile.ExcludeLookAlike = excludeLookAlike;
profile.Length = (uint)passwordLength;
profile.NoRepeatingCharacters = true;
KeePassLib.Cryptography.PasswordGenerator.PwGenerator.Generate(out ps, profile, null, _pool);
return ps.ReadString();
}
このメソッドは、メンバーシップ プロバイダーで使用できるものと同様に作成しました。これは、一部のアプリケーションで Web 参照を追加したくない場合に便利です。
とてもうまくいきます。
public static string GeneratePassword(int Length, int NonAlphaNumericChars)
{
string allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789";
string allowedNonAlphaNum = "!@#$%^&*()_-+=[{]};:<>|./?";
Random rd = new Random();
if (NonAlphaNumericChars > Length || Length <= 0 || NonAlphaNumericChars < 0)
throw new ArgumentOutOfRangeException();
char[] pass = new char[Length];
int[] pos = new int[Length];
int i = 0, j = 0, temp = 0;
bool flag = false;
//Random the position values of the pos array for the string Pass
while (i < Length - 1)
{
j = 0;
flag = false;
temp = rd.Next(0, Length);
for (j = 0; j < Length; j++)
if (temp == pos[j])
{
flag = true;
j = Length;
}
if (!flag)
{
pos[i] = temp;
i++;
}
}
//Random the AlphaNumericChars
for (i = 0; i < Length - NonAlphaNumericChars; i++)
pass[i] = allowedChars[rd.Next(0, allowedChars.Length)];
//Random the NonAlphaNumericChars
for (i = Length - NonAlphaNumericChars; i < Length; i++)
pass[i] = allowedNonAlphaNum[rd.Next(0, allowedNonAlphaNum.Length)];
//Set the sorted array values by the pos array for the rigth posistion
char[] sorted = new char[Length];
for (i = 0; i < Length; i++)
sorted[i] = pass[pos[i]];
string Pass = new String(sorted);
return Pass;
}
ソフトウェア キーの生成と同じように、パスワードの生成を検討するのが好きです。適切な慣例に従って、一連の文字から選択する必要があります。何を取ります @Radu094が回答しました を使用して、適切な慣例に従って変更します。文字配列にすべての文字を入れないでください。手紙によっては、電話では言いにくい、理解するのが難しいものもあります。
また、生成されたパスワードにチェックサムを使用して、それが自分で生成されたものであることを確認することも検討してください。これを実現する良い方法は、 LUHN アルゴリズム.
早速まとめてみたのがこちらです。
public string GeneratePassword(int len)
{
string res = "";
Random rnd = new Random();
while (res.Length < len) res += (new Func<Random, string>((r) => {
char c = (char)((r.Next(123) * DateTime.Now.Millisecond % 123));
return (Char.IsLetterOrDigit(c)) ? c.ToString() : "";
}))(rnd);
return res;
}
public static string GeneratePassword(int passLength) {
var chars = "abcdefghijklmnopqrstuvwxyz@#$&ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var random = new Random();
var result = new string(
Enumerable.Repeat(chars, passLength)
.Select(s => s[random.Next(s.Length)])
.ToArray());
return result;
}
これは短いので、私にとってはとても効果的です。
public static string GenerateRandomCode(int length)
{
Random rdm = new Random();
StringBuilder sb = new StringBuilder();
for(int i = 0; i < length; i++)
sb.Append(Convert.ToChar(rdm.Next(101,132)));
return sb.ToString();
}
私のウェブサイトでは次の方法を使用しています。
//Symb array
private const string _SymbolsAll = "~`!@#$%^&*()_+=-\\|[{]}'\";:/?.>,<";
//Random symb
public string GetSymbol(int Length)
{
Random Rand = new Random(DateTime.Now.Millisecond);
StringBuilder result = new StringBuilder();
for (int i = 0; i < Length; i++)
result.Append(_SymbolsAll[Rand.Next(0, _SymbolsAll.Length)]);
return result.ToString();
}
文字列を編集する _SymbolsAll
配列リスト用。
受け入れられた回答に補足コードを追加しました。Random を使用するだけで回答が改善され、いくつかのパスワード オプションが可能になります。KeePass の回答のいくつかのオプションも気に入りましたが、ソリューションに実行可能ファイルを含めたくありませんでした。
private string RandomPassword(int length, bool includeCharacters, bool includeNumbers, bool includeUppercase, bool includeNonAlphaNumericCharacters, bool includeLookAlikes)
{
if (length < 8 || length > 128) throw new ArgumentOutOfRangeException("length");
if (!includeCharacters && !includeNumbers && !includeNonAlphaNumericCharacters) throw new ArgumentException("RandomPassword-Key arguments all false, no values would be returned");
string pw = "";
do
{
pw += System.Web.Security.Membership.GeneratePassword(128, 25);
pw = RemoveCharacters(pw, includeCharacters, includeNumbers, includeUppercase, includeNonAlphaNumericCharacters, includeLookAlikes);
} while (pw.Length < length);
return pw.Substring(0, length);
}
private string RemoveCharacters(string passwordString, bool includeCharacters, bool includeNumbers, bool includeUppercase, bool includeNonAlphaNumericCharacters, bool includeLookAlikes)
{
if (!includeCharacters)
{
var remove = new string[] { "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" };
foreach (string r in remove)
{
passwordString = passwordString.Replace(r, string.Empty);
passwordString = passwordString.Replace(r.ToUpper(), string.Empty);
}
}
if (!includeNumbers)
{
var remove = new string[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
foreach (string r in remove)
passwordString = passwordString.Replace(r, string.Empty);
}
if (!includeUppercase)
passwordString = passwordString.ToLower();
if (!includeNonAlphaNumericCharacters)
{
var remove = new string[] { "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "-", "_", "+", "=", "{", "}", "[", "]", "|", "\\", ":", ";", "<", ">", "/", "?", "." };
foreach (string r in remove)
passwordString = passwordString.Replace(r, string.Empty);
}
if (!includeLookAlikes)
{
var remove = new string[] { "(", ")", "0", "O", "o", "1", "i", "I", "l", "|", "!", ":", ";" };
foreach (string r in remove)
passwordString = passwordString.Replace(r, string.Empty);
}
return passwordString;
}
これは、ランダムなパスワードの生成について検索したときの最初のリンクでした。以下は現在の質問の範囲外ですが、考慮することが重要である可能性があります。
- という仮定に基づいて、
System.Web.Security.Membership.GeneratePassword
少なくとも 20% の文字が非英数字であるため、暗号的に安全です。 - この場合、文字を削除して文字列を追加することが適切な方法と考えられ、十分なエントロピーが提供されるかどうかはわかりません。
- 何らかの方法で実装することを検討するとよいでしょう セキュアストリング パスワードをメモリに安全に保存します。
validChars は任意の構造にすることができますが、制御文字を削除した ASCII コード範囲に基づいて選択することにしました。この例では、12 文字の文字列です。
string validChars = String.Join("", Enumerable.Range(33, (126 - 33)).Where(i => !(new int[] { 34, 38, 39, 44, 60, 62, 96 }).Contains(i)).Select(i => { return (char)i; }));
string.Join("", Enumerable.Range(1, 12).Select(i => { return validChars[(new Random(Guid.NewGuid().GetHashCode())).Next(0, validChars.Length - 1)]; }))
Generate random password of specified length with
- Special characters
- Number
- Lowecase
- Uppercase
public static string CreatePassword(int length = 12)
{
const string lower = "abcdefghijklmnopqrstuvwxyz";
const string upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string number = "1234567890";
const string special = "!@#$%^&*";
var middle = length / 2;
StringBuilder res = new StringBuilder();
Random rnd = new Random();
while (0 < length--)
{
if (middle == length)
{
res.Append(number[rnd.Next(number.Length)]);
}
else if (middle - 1 == length)
{
res.Append(special[rnd.Next(special.Length)]);
}
else
{
if (length % 2 == 0)
{
res.Append(lower[rnd.Next(lower.Length)]);
}
else
{
res.Append(upper[rnd.Next(upper.Length)]);
}
}
}
return res.ToString();
}
ポットに別の無謀な答えを追加します。
マシン間の通信にランダムなパスワードが必要なユースケースがあるため、人間が読みやすいという要件はありません。私もアクセスできません Membership.GeneratePassword
私のプロジェクトでは、依存関係を追加したくないのです。
私はかなり確信しています Membership.GeneratePassword
はこれと似たようなことを行っていますが、ここでは描画元のキャラクターのプールを調整できます。
public static class PasswordGenerator
{
private readonly static Random _rand = new Random();
public static string Generate(int length = 24)
{
const string lower = "abcdefghijklmnopqrstuvwxyz";
const string upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string number = "1234567890";
const string special = "!@#$%^&*_-=+";
// Get cryptographically random sequence of bytes
var bytes = new byte[length];
new RNGCryptoServiceProvider().GetBytes(bytes);
// Build up a string using random bytes and character classes
var res = new StringBuilder();
foreach(byte b in bytes)
{
// Randomly select a character class for each byte
switch (_rand.Next(4))
{
// In each case use mod to project byte b to the correct range
case 0:
res.Append(lower[b % lower.Count()]);
break;
case 1:
res.Append(upper[b % upper.Count()]);
break;
case 2:
res.Append(number[b % number.Count()]);
break;
case 3:
res.Append(special[b % special.Count()]);
break;
}
}
return res.ToString();
}
}
出力例:
PasswordGenerator.Generate(12)
"pzY=64@-ChS$"
"BG0OsyLbYnI_"
"l9#5^2&adj_i"
"#++Ws9d$%O%X"
"IWhdIN-#&O^s"
の使用に関する苦情を事前に解決するため Random
:ランダム性の主な原因は依然として暗号 RNG です。たとえ、出てくる順序を決定論的に事前に決めることができたとしても、 Random
(それはただ生産しただけだと言います) 1
) 次に選択される文字はまだわかりません (ただし、 するだろう 可能性の範囲を制限します)。
簡単な拡張の 1 つは、さまざまな文字セットに重みを追加することです。これは、最大値を増やし、フォールスルー ケースを追加して重みを増やすのと同じくらい簡単です。
switch (_rand.Next(6))
{
// Prefer letters 2:1
case 0:
case 1:
res.Append(lower[b % lower.Count()]);
break;
case 2:
case 3:
res.Append(upper[b % upper.Count()]);
break;
case 4:
res.Append(number[b % number.Count()]);
break;
case 5:
res.Append(special[b % special.Count()]);
break;
}
より人道的なランダムパスワード生成のために、私はかつて、以下を使用してプロンプトシステムを実装しました。 EFF サイコロワードリスト.
タイマーを挿入します。タイマー1、2ボタン:ボタン1、ボタン2、テキストボックス1個:textBox1 とコンボボックス:コンボボックス1。必ず次のことを宣言してください。
int count = 0;
ソースコード:
private void button1_Click(object sender, EventArgs e)
{
// This clears the textBox, resets the count, and starts the timer
count = 0;
textBox1.Clear();
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
// This generates the password, and types it in the textBox
count += 1;
string possible = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
string psw = "";
Random rnd = new Random { };
psw += possible[rnd.Next(possible.Length)];
textBox1.Text += psw;
if (count == (comboBox1.SelectedIndex + 1))
{
timer1.Stop();
}
}
private void Form1_Load(object sender, EventArgs e)
{
// This adds password lengths to the comboBox to choose from.
comboBox1.Items.Add("1");
comboBox1.Items.Add("2");
comboBox1.Items.Add("3");
comboBox1.Items.Add("4");
comboBox1.Items.Add("5");
comboBox1.Items.Add("6");
comboBox1.Items.Add("7");
comboBox1.Items.Add("8");
comboBox1.Items.Add("9");
comboBox1.Items.Add("10");
comboBox1.Items.Add("11");
comboBox1.Items.Add("12");
}
private void button2_click(object sender, EventArgs e)
{
// This encrypts the password
tochar = textBox1.Text;
textBox1.Clear();
char[] carray = tochar.ToCharArray();
for (int i = 0; i < carray.Length; i++)
{
int num = Convert.ToInt32(carray[i]) + 10;
string cvrt = Convert.ToChar(num).ToString();
textBox1.Text += cvrt;
}
}
public string Sifre_Uret(int boy, int noalfa)
{
// 01.03.2016
// Genel amaçlı şifre üretme fonksiyonu
//Fonskiyon 128 den büyük olmasına izin vermiyor.
if (boy > 128 ) { boy = 128; }
if (noalfa > 128) { noalfa = 128; }
if (noalfa > boy) { noalfa = boy; }
string passch = System.Web.Security.Membership.GeneratePassword(boy, noalfa);
//URL encoding ve Url Pass + json sorunu yaratabilecekler pass ediliyor.
//Microsoft Garanti etmiyor. Alfa Sayısallar Olabiliyorimiş . !@#$%^&*()_-+=[{]};:<>|./?.
//https://msdn.microsoft.com/tr-tr/library/system.web.security.membership.generatepassword(v=vs.110).aspx
//URL ve Json ajax lar için filtreleme
passch = passch.Replace(":", "z");
passch = passch.Replace(";", "W");
passch = passch.Replace("'", "t");
passch = passch.Replace("\"", "r");
passch = passch.Replace("/", "+");
passch = passch.Replace("\\", "e");
passch = passch.Replace("?", "9");
passch = passch.Replace("&", "8");
passch = passch.Replace("#", "D");
passch = passch.Replace("%", "u");
passch = passch.Replace("=", "4");
passch = passch.Replace("~", "1");
passch = passch.Replace("[", "2");
passch = passch.Replace("]", "3");
passch = passch.Replace("{", "g");
passch = passch.Replace("}", "J");
//passch = passch.Replace("(", "6");
//passch = passch.Replace(")", "0");
//passch = passch.Replace("|", "p");
//passch = passch.Replace("@", "4");
//passch = passch.Replace("!", "u");
//passch = passch.Replace("$", "Z");
//passch = passch.Replace("*", "5");
//passch = passch.Replace("_", "a");
passch = passch.Replace(",", "V");
passch = passch.Replace(".", "N");
passch = passch.Replace("+", "w");
passch = passch.Replace("-", "7");
return passch;
}