Wie kann ich eine zufällige 8 Zeichen alphanumerische Zeichenfolge in C# generieren?
Antworten
Zu viele Anzeigen?Die Hauptziele meines Codes sind:
- Die Verteilung der Strings ist nahezu gleichmäßig (geringe Abweichungen sind egal, solange sie klein sind)
- Es gibt mehr als ein paar Milliarden Zeichenfolgen für jedes Argument aus. Die Erzeugung einer Zeichenkette mit 8 Zeichen (~47 Bits Entropie) ist bedeutungslos, wenn Ihr PRNG nur 2 Milliarden (31 Bits Entropie) verschiedene Werte erzeugt.
- Es ist sicher, da ich davon ausgehe, dass die Leute es für Passwörter oder andere Sicherheitstoken verwenden werden.
Die erste Eigenschaft wird erreicht, indem ein 64-Bit-Wert modulo der Alphabetgröße genommen wird. Bei kleinen Alphabeten (wie den 62 Zeichen in der Frage) führt dies zu einer vernachlässigbaren Verzerrung. Die zweite und dritte Eigenschaft wird erreicht durch die Verwendung von RNGCryptoServiceProvider
anstelle von 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];
var result = new char[length];
using (var cryptoProvider = new RNGCryptoServiceProvider())
{
cryptoProvider.GetBytes(bytes);
}
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);
}
Das Einfachste:
public static string GetRandomAlphaNumeric()
{
return Path.GetRandomFileName().Replace(".", "").Substring(0, 8);
}
Sie können eine bessere Leistung erzielen, wenn Sie das Char-Array hart kodieren und sich auf System.Random
:
public static string GetRandomAlphaNumeric()
{
var chars = "abcdefghijklmnopqrstuvwxyz0123456789";
return new string(chars.Select(c => chars[random.Next(chars.Length)]).Take(8).ToArray());
}
Wenn Sie befürchten, dass sich das englische Alphabet irgendwann ändern könnte und Sie dadurch Geschäftseinbußen erleiden könnten, dann können Sie auf Hardcoding verzichten, sollten aber etwas schlechtere Ergebnisse erzielen (vergleichbar mit Path.GetRandomFileName
Ansatz)
public static string GetRandomAlphaNumeric()
{
var chars = 'a'.To('z').Concat('0'.To('9')).ToList();
return new string(chars.Select(c => chars[random.Next(chars.Length)]).Take(8).ToArray());
}
public static IEnumerable<char> To(this char start, char end)
{
if (end < start)
throw new ArgumentOutOfRangeException("the end char should not be less than start char", innerException: null);
return Enumerable.Range(start, end - start + 1).Select(i => (char)i);
}
Die letzten beiden Ansätze sehen besser aus, wenn Sie sie zu einer Erweiterungsmethode von System.Random
Instanz.
Nur einige Leistungsvergleiche der verschiedenen Antworten in diesem Thread:
Methoden & Einrichtung
// what's available
public static string possibleChars = "abcdefghijklmnopqrstuvwxyz";
// optimized (?) what's available
public static char[] possibleCharsArray = possibleChars.ToCharArray();
// optimized (precalculated) count
public static int possibleCharsAvailable = possibleChars.Length;
// shared randomization thingy
public static Random random = new Random();
// http://stackoverflow.com/a/1344242/1037948
public string LinqIsTheNewBlack(int num) {
return new string(
Enumerable.Repeat(possibleCharsArray, num)
.Select(s => s[random.Next(s.Length)])
.ToArray());
}
// http://stackoverflow.com/a/1344258/1037948
public string ForLoop(int num) {
var result = new char[num];
while(num-- > 0) {
result[num] = possibleCharsArray[random.Next(possibleCharsAvailable)];
}
return new string(result);
}
public string ForLoopNonOptimized(int num) {
var result = new char[num];
while(num-- > 0) {
result[num] = possibleChars[random.Next(possibleChars.Length)];
}
return new string(result);
}
public string Repeat(int num) {
return new string(new char[num].Select(o => possibleCharsArray[random.Next(possibleCharsAvailable)]).ToArray());
}
// http://stackoverflow.com/a/1518495/1037948
public string GenerateRandomString(int num) {
var rBytes = new byte[num];
random.NextBytes(rBytes);
var rName = new char[num];
while(num-- > 0)
rName[num] = possibleCharsArray[rBytes[num] % possibleCharsAvailable];
return new string(rName);
}
//SecureFastRandom - or SolidSwiftRandom
static string GenerateRandomString(int Length) //Configurable output string length
{
byte[] rBytes = new byte[Length];
char[] rName = new char[Length];
SolidSwiftRandom.GetNextBytesWithMax(rBytes, biasZone);
for (var i = 0; i < Length; i++)
{
rName[i] = charSet[rBytes[i] % charSet.Length];
}
return new string(rName);
}
Ergebnisse
Getestet in LinqPad. Für String-Größe von 10, erzeugt:
- von Linq = chdgmevhcy [10]
- von Loop = gtnoaryhxr [10]
- from Select = rsndbztyby [10]
- von GenerateRandomString = owyefjjakj [10]
- von SecureFastRandom = VzougLYHYP [10]
- von SecureFastRandom-NoCache = oVQXNGmO1S [10]
Und die Leistungszahlen schwanken gelegentlich leicht. NonOptimized
ist tatsächlich schneller, und manchmal ForLoop
y GenerateRandomString
wechseln, wer die Führung hat.
- LinqIsTheNewBlack (10000x) = 96762 Ticks verstrichen (9,6762 ms)
- ForLoop (10000x) = 28970 Ticks verstrichen (2,897 ms)
- ForLoopNonOptimized (10000x) = 33336 Ticks verstrichen (3,3336 ms)
- Wiederholung (10000x) = 78547 Ticks verstrichen (7,8547 ms)
- GenerateRandomString (10000x) = 27416 Ticks verstrichen (2,7416 ms)
- SecureFastRandom (10000x) = 13176 verstrichene Ticks (5ms) niedrigste [anderer Rechner]
- SecureFastRandom-NoCache (10000x) = 39541 Ticks verstrichen (17ms) niedrigste [anderer Rechner]
Eine Codezeile Membership.GeneratePassword()
funktioniert das :)
Hier ist ein Demo für dasselbe.
Mein einfacher Ein-Zeilen-Code funktioniert bei mir :)
string random = string.Join("", Guid.NewGuid().ToString("n").Take(8).Select(o => o));
Response.Write(random.ToUpper());
Response.Write(random.ToLower());
Um dies für eine beliebig lange Zeichenkette zu erweitern
public static string RandomString(int length)
{
//length = length < 0 ? length * -1 : length;
var str = "";
do
{
str += Guid.NewGuid().ToString().Replace("-", "");
}
while (length > str.Length);
return str.Substring(0, length);
}
2 Stimmen
Welcher Rest
8 Stimmen
O s o s
2 Stimmen
Es wäre schön, wenn die Sprachlokalisierung in diese Frage einbezogen würde. Vor allem, wenn Ihre Benutzeroberfläche für Chinesisch oder Bulgarisch geeignet sein soll!
0 Stimmen
Siehe auch Wie erstellt man eine zufällige Folge von Zahlen und Buchstaben mit einer Länge von 5?
22 Stimmen
Ein Beitrag mit so vielen positiven Bewertungen und so vielen guten Antworten hat es nicht verdient, als geschlossen markiert zu werden. Ich stimme dafür, dass es wieder geöffnet wird.
0 Stimmen
Als Kryptograph sehe ich hauptsächlich absolut falsche Antworten mit vielen positiven Bewertungen, um ehrlich zu sein. Wenn Sie eine sichere Zufallszeichenkette haben wollen, dann beschäftigen Sie sich bitte selbst mit Zufälligkeit und unvoreingenommenen Verteilungen, denn die stehen nicht auf der ersten Seite der Antworten.
0 Stimmen
Übrigens, hier ist eine Sammlung von Erzeugung von Zufallszeichenfolgen in verschiedenen Programmiersprachen .
0 Stimmen
Wer hat etwas von Sicherheit gesagt? Der OP fragte nur, wie man eine Zeichenkette erzeugt.