Kaip generuoti atsitiktines raidines ir skaitmenines eilutes C #?

Kaip generuoti atsitiktines 8 skaitmenų raidines skaitmenines eilutes C #?

737
28 авг. nustatė KingNestor 28 rug . 2009-08-28 02:07 '09, 02:07 2009-08-28 02:07
ответ 31 atsakymų
  • 1
  • 2

Girdėjau, kad LINQ yra nauja juoda, todėl čia bandau naudoti LINQ:

 private static Random random = new Random(); public static string RandomString(int length) { const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; return new string(Enumerable.Repeat(chars, length) .Select(s => s[random.Next(s.Length)]).ToArray()); } 

(Pastaba: naudojant „Random“ klasę, jis netinka bet kuriam saugumui , pvz., Sukurti slaptažodžius ar žetonus. Jei reikia stipraus atsitiktinio skaičiaus generatoriaus, naudokite RNGCryptoServiceProvider klasę.)

1359
28 авг. atsakymas yra dtb 28 rug . 2009-08-28 02:13 '09 - 2009-08-28 02:13 02:13
 var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; var stringChars = new char[8]; var random = new Random(); for (int i = 0; i < stringChars.Length; i++) { stringChars[i] = chars[random.Next(chars.Length)]; } var finalString = new String(stringChars); 

Ne toks pat elegantiškas kaip Linq sprendimas. (-:

border=0

(Pastaba. Naudojant atsitiktinę klasę, ši programa netinka bet kuriam saugumui , pvz., Kuriant slaptažodžius ar žetonus. Jei reikia stipraus atsitiktinių skaičių generatoriaus, naudokite RNGCryptoServiceProvider klasę.)

286
28 авг. Atsakyti Dan Rigby 28 rug. 2009-08-28 02:21 '09, 2:21 am. 2009-08-28 02:21

Šis įgyvendinimas (rastas per „Google“) man atrodo kaip garsas.

Skirtingai nuo kai kurių pateiktų alternatyvų, tai kriptografiškai skamba .

 using System.Security.Cryptography; using System.Text; namespace UniqueKey { public class KeyGenerator { public static string GetUniqueKey(int maxSize) { char[] chars = new char[62]; chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray(); byte[] data = new byte[1]; using (RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider()) { crypto.GetNonZeroBytes(data); data = new byte[maxSize]; crypto.GetNonZeroBytes(data); } StringBuilder result = new StringBuilder(maxSize); foreach (byte b in data) { result.Append(chars[b % (chars.Length)]); } return result.ToString(); } } } 

Pasirinkite šią parinktį iš čia aptariamų alternatyvų .

258
28 авг. Atsakymą pateikė Eric J. Aug 2009-08-28 02:19 '09, 2:19, 2009-08-28 02:19

1 sprendimas - didžiausias „intervalas“, turintis lankstiausią ilgį

 string get_unique_string(int string_length) { using(var rng = new RNGCryptoServiceProvider()) { var bit_count = (string_length * 6); var byte_count = ((bit_count + 7) / 8); // rounded up var bytes = new byte[byte_count]; rng.GetBytes(bytes); return Convert.ToBase64String(bytes); } } 

Šis sprendimas turi didesnį diapazoną nei naudojant GUID, nes GUID turi fiksuotų bitų porą, kuri visada yra tokia pati ir todėl nėra atsitiktinė, pavyzdžiui, 13 simbolių šešioliktainiame formate visada yra "4" - bent jau GUID 6 versijoje.

Šis sprendimas taip pat leidžia sukurti bet kokio ilgio eilutę.

2 sprendimas. Vienoje kodo eilutėje gali būti iki 22 simbolių

 Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Substring(0, 8); 

Jūs negalite generuoti styginių, kol 1 sprendimas ir eilutė neturi to paties intervalo dėl fiksuotų bitų GUID, tačiau daugeliu atvejų jis atliks darbą.

3 sprendimas - šiek tiek mažiau kodo

 Guid.NewGuid().ToString("n").Substring(0, 8); 

Iš esmės tai yra istoriniu tikslu. Jis naudoja šiek tiek mažiau kodo, nors jis yra susijęs su mažesniu diapazonu - kadangi jis naudoja šešioliktainį, o ne base64, kiti sprendimai yra lyginami, kad daugiau simbolių atitiktų tą patį diapazoną.

Tai reiškia didesnį susidūrimo tikimybę - bandymas su 100 000 8 simbolių eilutėmis kartoja vieną egzempliorių.

167
28 авг. Atsakymas duotas Douglas 28 rug. 2009-08-28 03:00 '09, 3:00, 2009-08-28 03:00

Štai pavyzdys, kurį pavogau iš „Sam Allen“ pavyzdžio „ Dot Net Perls“

Jei jums reikia tik 8 simbolių, naudokite „Path.GetRandomFileName“ () „System.IO“ vardų erdvėje. Sam sako, kad naudojant Path.GetRandomFileName metodą kartais yra pranašesnis, nes jis naudoja RNGCryptoServiceProvider, kad būtų geriau atsitiktinai. Tačiau tai yra tik 11 atsitiktinių simbolių.

„GetRandomFileName“ visada grąžina 12 simbolių eilutę su 9-ojo simbolio laikotarpiu. Todėl reikia pašalinti laikotarpį (nes jis nėra atsitiktinis), o tada iš eilės paimkite 8 simbolius. Tiesą sakant, galite tiesiog užimti pirmuosius 8 simbolius ir nesijaudinkite dėl laikotarpio.

 public string Get8CharacterRandomString() { string path = Path.GetRandomFileName(); path = path.Replace(".", ""); // Remove period. return path.Substring(0, 8); // Return 8 character string } 

Ps: ačiū Sam

56
28 авг. atsakymą pateikė Adam Porad 28 rug . 2009-08-28 02:36 '09 at 2:36 am 2009-08-28 02:36

Pagrindiniai mano kodo tikslai yra:

  • Linijų pasiskirstymas yra beveik vienodas (nesirūpinkite mažais nuokrypiais, kai jie yra maži)
  • Kiekvienam argumentų rinkiniui ji spausdina daugiau nei keletą milijardų eilučių. 8 ženklų eilutės (~ 47 bitų entropijos) generavimas yra beprasmis, jei jūsų PRNG generuoja tik 2 milijardus (31 bitų entropijos) skirtingų verčių.
  • Tai saugu, nes tikiuosi, kad žmonės jį naudos slaptažodžiams ar kitiems saugumo žetonams.

Pirmoji nuosavybė pasiekiama dėl 64 bitų vertės modulinio dydžio abėcėlės dydžio. Mažoms abėcėlėms (pvz., Iš 62 klausimynų) tai lemia nežymią kompensaciją. Antroji ir trečioji savybės pasiekiamos naudojant RNGCryptoServiceProvider o ne 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); } 
33
16 нояб. Atsakymas pateikiamas CodesInChaos 16 lapkričio. 2012-11-16 14:57 '12 at 2:57 pm 2012-11-16 14:57

Lengviausias:

 public static string GetRandomAlphaNumeric() { return Path.GetRandomFileName().Replace(".", "").Substring(0, 8); } 

Geresnį našumą galite gauti, jei System.Random char“ masyvą ir System.RandomSystem.Random :

 public static string GetRandomAlphaNumeric() { var chars = "abcdefghijklmnopqrstuvwxyz0123456789"; return new string(chars.Select(c => chars[random.Next(chars.Length)]).Take(8).ToArray()); } 

Jei nerimaujate, kad angliškos abėcėlės gali kada nors pasikeisti, ir jūs galite prarasti verslą, tada galite išvengti sunkių kodavimo, tačiau turėtumėte dirbti šiek tiek blogiau (panašus į „ Path.GetRandomFileName požiūrį)

 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); } 

Paskutiniai du metodai atrodo geriau, jei galite juos padaryti išplėtimo metodu sistemoje.

29
13 апр. Atsakymas pateikiamas nawfal 13 balandžio. 2013-04-13 10:09 13 iš 10:09 2013-14-13 10:09

Tiesiog palyginkite įvairių šios temos atsakymų atlikimą:

Būdai ir nustatymai

 // what available public static string possibleChars = "abcdefghijklmnopqrstuvwxyz"; // optimized (?) what 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); } 

Rezultatai

Išbandyta „LinqPad“. 10 eilutės dydžiui:

  • pateikė Linq = chdgmevhcy [10]
  • nuo Loop = gtnoaryhxr [10]
  • iš Select = rsndbztyby [10]
  • iš GenerateRandomString = owyefjjakj [10]
  • iš SecureFastRandom = VzougLYHYP [10]
  • iš SecureFastRandom-NoCache = oVQXNGmO1S [10]

Ir veiklos rodikliai šiek tiek keičiasi, labai retai „ NonOptimized iš tikrųjų yra greitesnis, o kartais „ ForLoop ir „ GenerateRandomString perjungia lyderį.

  • LinqIsNewBlack (10000x) = 96762 erkių (9,6762 ms)
  • ForLoop (10000x) = 28970 erkių (2.897 ms)
  • ForLoopNonOptimized (10000x) = 33336 erkių praėjo (3,3336 ms)
  • Kartojimas (10000x) = 78547 erkių (7,8547 ms)
  • GeneruotiRandomString (10000x) = 27416 erkių (2,77416 ms)
  • SecureFastRandom (10000x) = 13176 erkės, paskutinės (5 ms) mažiausios [Įvairios mašinos]
  • SecureFastRandom-NoCache (10000x) = 39541 praėjo (17 ms) mažiausia [Įvairi mašina]
18
13 июня '13 в 19:45 2013-06-13 19:45 atsakymą drzaus pateikė birželio 13 d. 13 val. 19:45 2013-06-13 19:45

Vienas eilutės kodas Membership.GeneratePassword() daro triuką :)

Čia yra tos pačios demonstracijos .

16
10 июля '14 в 23:40 2014-07-10 23:40 atsakymas pateikiamas „ Pooran“ liepos 10 d. 14 val. 23:40 2014-07-10 23:40

Erico parašytas kodas yra gana nepatogus (nuo šešerių metų aišku, kad šiandien jis nerašys šio kodo), ir yra net keletas problemų.

Skirtingai nuo kai kurių pateiktų alternatyvų, tai kriptografiškai skamba.

Nepriimtina ... Slaptažodžiu yra šališkas (kaip parašyta komentare), bcdefgh tiek labiau tikėtinas nei kiti (ne todėl, kad „ GetNonZeroBytes jokių baitų, kurių vertė yra 0, taigi „ a “ nuokrypis a subalansuotas) yra kriptografiškai patikimas.

Tai turėtų išspręsti visas problemas.

 public static string GetUniqueKey(int size = 6, string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") { using (var crypto = new RNGCryptoServiceProvider()) { var data = new byte[size]; // If chars.Length isn't a power of 2 then there is a bias if // we simply use the modulus operator. The first characters of // chars will be more probable than the last ones. // buffer used if we encounter an unusable random byte. We will // regenerate it in this buffer byte[] smallBuffer = null; // Maximum random number that can be used without introducing a // bias int maxRandom = byte.MaxValue - ((byte.MaxValue + 1) % chars.Length); crypto.GetBytes(data); var result = new char[size]; for (int i = 0; i < size; i++) { byte v = data[i]; while (v > maxRandom) { if (smallBuffer == null) { smallBuffer = new byte[1]; } crypto.GetBytes(smallBuffer); v = smallBuffer[0]; } result[i] = chars[v % chars.Length]; } return new string(result); } } 
8
12 авг. Atsakymas pateikiamas xanatos 12 rug . 2015-08-12 10:53 '15, 10:53, 2015-08-12 10:53

Mes taip pat naudojame atsitiktinę eilutę, tačiau ją įdiegėme kaip pagalbinį eilutės elementą, todėl jis suteikia tam tikrą lankstumą ...

 public static string Random(this string chars, int length = 8) { var randomString = new StringBuilder(); var random = new Random(); for (int i = 0; i < length; i++) randomString.Append(chars[random.Next(chars.Length)]); return randomString.ToString(); } 

Naudojimas

 var random = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".Random(); 

arba

 var random = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".Random(16); 
6
atsakymas pateikiamas p. 26 июня '14 в 18:12 2014-06-26 18:12 Moliūgas Birželio 26, 14 d. 18:12 pm 2014-06-26 18:12

Jei jums reikia tik pseudo-atsitiktinio raidinio ir skaitmeninio kodo, kuris yra patogus vartotojui ir gautas iš sveiko skaičiaus, čia pateikiau sprendimą:

Sukurkite pseudo-atsitiktines raidines ir skaitmenines reikšmes

Privalumas yra tas, kad kiekvienas generuojamas raktas yra unikalus.

5
11 дек. Atsakymą pateikė Mike, gruodžio 11 d. 2011-12-11 18:01 '11 at 18:01 2011-12-11 18:01

Kita galimybė būtų naudoti „Linq“ ir sujungti savavališkus simbolius į styginių konstruktorių.

 var chars = "abcdefghijklmnopqrstuvwxyz123456789".ToArray(); string pw = Enumerable.Range(0, passwordLength) .Aggregate( new StringBuilder(), (sb, n) => sb.Append((chars[random.Next(chars.Length)])), sb => sb.ToString()); 
5
25 янв. atsakymas duotas AAD 25 sausio. 2012-01-25 02:42 '12 at 2:42 2012-01-25 02:42

Klausimas: Kodėl turėčiau praleisti laiką naudodamas „ Enumerable.Range o ne įvesti "ABCDEFGHJKLMNOPQRSTUVWXYZ0123456789" ?

 using System; using System.Collections.Generic; using System.Linq; public class Test { public static void Main() { var randomCharacters = GetRandomCharacters(8, true); Console.WriteLine(new string(randomCharacters.ToArray())); } private static List<char> getAvailableRandomCharacters(bool includeLowerCase) { var integers = Enumerable.Empty<int>(); integers = integers.Concat(Enumerable.Range('A', 26)); integers = integers.Concat(Enumerable.Range('0', 10)); if ( includeLowerCase ) integers = integers.Concat(Enumerable.Range('a', 26)); return integers.Select(i => (char)i).ToList(); } public static IEnumerable<char> GetRandomCharacters(int count, bool includeLowerCase) { var characters = getAvailableRandomCharacters(includeLowerCase); var random = new Random(); var result = Enumerable.Range(0, count) .Select(_ => characters[random.Next(characters.Count)]); return result; } } 

Atsakymas: BAD magijos linijos. Ar kas nors pastebėjo, kad mano eilutėje viršuje nėra „ I “? Mano motina mokė man nenaudoti magiškų stygų būtent dėl ​​šios priežasties ...

nb 1: kaip ir daugelis kitų, pvz., @ dtb, nenaudokite System.Random jei jums reikia kriptografinės apsaugos ...

nb 2: Šis atsakymas nėra pats efektyviausias ar trumpiausias, bet norėjau, kad atsakymas būtų atskirtas nuo klausimo. Mano atsakymo tikslas yra įspėti prieš magiškas linijas, o ne suteikti fantastišką naujovišką atsakymą.

5
22 февр. Atsakymą pateikė Wai Ha Lee vasario 22 d. 2015-02-22 18:16 '15, 18:16, 2015-02-22 18:16

Mano paprastas vieno eilutės kodas veikia man :)

 string random = string.Join("", Guid.NewGuid().ToString("n").Take(8).Select(o => o)); Response.Write(random.ToUpper()); Response.Write(random.ToLower()); 

Norėdami išplėsti šią eilutę bet kokiam eilutės ilgiui

  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); } 
4
29 сент. atsakymą pateikė Raj kumar rugsėjo 29 d 2015-09-29 15:38 '15 15:38 2015-09-29 15:38

Aš ieškojau tikslesnio atsakymo, kur noriu kontroliuoti atsitiktinės eilutės formatą ir atėjo į šį įrašą. Pavyzdžiui: licencijos ženklai (automobiliai) turi tam tikrą formatą (pagal šalis), ir norėjau sukurti atsitiktines licencijų numerius.
Aš nusprendžiau parašyti savo atsitiktinio pratęsimo metodą. (tai reikalinga pakartotinai naudoti tą patį atsitiktinį objektą, nes galėtumėte padvigubinti daugiapakopius scenarijus). Sukūriau „Gist“ ( https://gist.github.com/SamVanhoutte/808845ca78b9c041e928 ), bet taip pat nukopijuosite išplėtimo klasę:

 void Main() { Random rnd = new Random(); rnd.GetString("1-###-000").Dump(); } public static class RandomExtensions { public static string GetString(this Random random, string format) { // Based on http://stackoverflow.com/questions/1344221/how-can-i-generate-random-alphanumeric-strings-in-c // Added logic to specify the format of the random string (# will be random string, 0 will be random numeric, other characters remain) StringBuilder result = new StringBuilder(); for(int formatIndex = 0; formatIndex < format.Length ; formatIndex++) { switch(format.ToUpper()[formatIndex]) { case '0': result.Append(getRandomNumeric(random)); break; case '#': result.Append(getRandomCharacter(random)); break; default : result.Append(format[formatIndex]); break; } } return result.ToString(); } private static char getRandomCharacter(Random random) { string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; return chars[random.Next(chars.Length)]; } private static char getRandomNumeric(Random random) { string nums = "0123456789"; return nums[random.Next(nums.Length)]; } } 
4
22 янв. Atsakymą pateikė Sam Vanhoutte, sausio 22 d 2015-01-22 13:39 '15, 13:39, 2015-01-22 13:39

Nežinau, aš žinau, bet aš tiesiog negalėjau sau padėti:

 namespace ConsoleApplication2 { using System; using System.Text.RegularExpressions; class Program { static void Main(string[] args) { Random adomRng = new Random(); string rndString = string.Empty; char c; for (int i = 0; i < 8; i++) { while (!Regex.IsMatch((c=Convert.ToChar(adomRng.Next(48,128))).ToString(), "[A-Za-z0-9]")); rndString += c; } Console.WriteLine(rndString + Environment.NewLine); } } }namespace ConsoleApplication2 { using System; using System.Text.RegularExpressions; class Program { static void Main(string[] args) { Random adomRng = new Random(); string rndString = string.Empty; char c; for (int i = 0; i < 8; i++) { while (!Regex.IsMatch((c=Convert.ToChar(adomRng.Next(48,128))).ToString(), "[A-Za-z0-9]")); rndString += c; } Console.WriteLine(rndString + Environment.NewLine); } } } 
4
28 авг. Jemeno atsakymas 28 rug. 2009-08-28 03:26 '09 3:26 am. 2009-08-28 03:26

Šiek tiek švaresnė DTB sprendimo versija.

  var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; var random = new Random(); var list = Enumerable.Repeat(0, 8).Select(x=>chars[random.Next(chars.Length)]); return string.Join("", list); 

Jūsų stiliaus nustatymai gali skirtis.

4
27 апр. Atsakymas, kurį pateikė Rob Deary balandžio 27 2015-04-27 23:47 '15, 23:47, 2015-04-27 23:47
  public static string RandomString(int length) { const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; var random = new Random(); return new string(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray()); } 
3
24 нояб. Atsakymas duotas Tejas lapkričio 24 d. 2015-11-24 11:46 '15, 11:46, 2015-11-24 11:46

Peržiūrėjęs kitus atsakymus ir peržiūrėjęs „CodeInChaos“ komentarus kartu su „CodeInChaos“, vis dar yra šališkas (nors ir mažiau) atsakymas, maniau, kad galutinis galutinis sprendimas buvo reikalingas pjaustymui ir įklijavimui . Todėl, atnaujindamas savo atsakymą, nusprendžiau su visa galinga.

Jei norite atnaujinti šio kodo versiją, apsilankykite naujoje „Hg“ saugykloje „Bitbucket“: https://bitbucket.org/merarischroeder/secureswiftrandom . Aš rekomenduoju, kad jūs nukopijuokite ir įklijuokite šį kodą nuo: https://bitbucket.org/merarischroeder/secureswiftrandom/src/6c14b874f34a3f6576b0213379ecdf0ffc7496ea/Code/Alivate.SolidSwiftRandom/SolidSwiftRandom.cs?at=default> (įsitikinkite, kad paspaudus Mygtukas „Žalia“, kad būtų lengviau kopijuoti ir įsitikinti, kad turite naujausią versiją, manau, kad ši nuoroda yra susijusi su konkrečia kodo versija, o ne paskutine.

Atnaujintos pastabos:

Galutinis sprendimas:

 static char[] charSet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".ToCharArray(); static int byteSize = 256; //Labelling convenience static int biasZone = byteSize - (byteSize % charSet.Length); public string GenerateRandomString(int Length) //Configurable output string length { byte[] rBytes = new byte[Length]; //Do as much before and after lock as possible char[] rName = new char[Length]; SecureFastRandom.GetNextBytesMax(rBytes, biasZone); for (var i = 0; i < Length; i++) { rName[i] = charSet[rBytes[i] % charSet.Length]; } return new string(rName); } 

Bet jums reikia naujos (nepatvirtintos) klasės:

 /// <summary> /// My benchmarking showed that for RNGCryptoServiceProvider: /// 1. There is negligable benefit of sharing RNGCryptoServiceProvider object reference /// 2. Initial GetBytes takes 2ms, and an initial read of 1MB takes 3ms (starting to rise, but still negligable) /// 2. Cached is ~1000x faster for single byte at a time - taking 9ms over 1MB vs 989ms for uncached /// </summary> class SecureFastRandom { static byte[] byteCache = new byte[1000000]; //My benchmark showed that an initial read takes 2ms, and an initial read of this size takes 3ms (starting to raise) static int lastPosition = 0; static int remaining = 0; /// <summary> /// Static direct uncached access to the RNGCryptoServiceProvider GetBytes function /// </summary> /// <param name="buffer"></param> public static void DirectGetBytes(byte[] buffer) { using (var r = new RNGCryptoServiceProvider()) { r.GetBytes(buffer); } } /// <summary> /// Main expected method to be called by user. Underlying random data is cached from RNGCryptoServiceProvider for best performance /// </summary> /// <param name="buffer"></param> public static void GetBytes(byte[] buffer) { if (buffer.Length > byteCache.Length) { DirectGetBytes(buffer); return; } lock (byteCache) { if (buffer.Length > remaining) { DirectGetBytes(byteCache); lastPosition = 0; remaining = byteCache.Length; } Buffer.BlockCopy(byteCache, lastPosition, buffer, 0, buffer.Length); lastPosition += buffer.Length; remaining -= buffer.Length; } } /// <summary> /// Return a single byte from the cache of random data. /// </summary> /// <returns></returns> public static byte GetByte() { lock (byteCache) { return UnsafeGetByte(); } } /// <summary> /// Shared with public GetByte and GetBytesWithMax, and not locked to reduce lock/unlocking in loops. Must be called within lock of byteCache. /// </summary> /// <returns></returns> static byte UnsafeGetByte() { if (1 > remaining) { DirectGetBytes(byteCache); lastPosition = 0; remaining = byteCache.Length; } lastPosition++; remaining--; return byteCache[lastPosition - 1]; } /// <summary> /// Rejects bytes which are equal to or greater than max. This is useful for ensuring there is no bias when you are modulating with a non power of 2 number. /// </summary> /// <param name="buffer"></param> /// <param name="max"></param> public static void GetBytesWithMax(byte[] buffer, byte max) { if (buffer.Length > byteCache.Length / 2) //No point caching for larger sizes { DirectGetBytes(buffer); lock (byteCache) { UnsafeCheckBytesMax(buffer, max); } } else { lock (byteCache) { if (buffer.Length > remaining) //Recache if not enough remaining, discarding remaining - too much work to join two blocks DirectGetBytes(byteCache); Buffer.BlockCopy(byteCache, lastPosition, buffer, 0, buffer.Length); lastPosition += buffer.Length; remaining -= buffer.Length; UnsafeCheckBytesMax(buffer, max); } } } /// <summary> /// Checks buffer for bytes equal and above max. Must be called within lock of byteCache. /// </summary> /// <param name="buffer"></param> /// <param name="max"></param> static void UnsafeCheckBytesMax(byte[] buffer, byte max) { for (int i = 0; i < buffer.Length; i++) { while (buffer[i] >= max) buffer[i] = UnsafeGetByte(); //Replace all bytes which are equal or above max } } } 

Už istoriją - mano seną sprendimą dėl šio atsakymo, naudojant atsitiktinį objektą:

  private static char[] charSet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".ToCharArray(); static rGen = new Random(); //Must share, because the clock seed only has Ticks (~10ms) resolution, yet lock has only 20-50ns delay. static int byteSize = 256; //Labelling convenience static int biasZone = byteSize - (byteSize % charSet.Length); static bool SlightlyMoreSecurityNeeded = true; //Configuration - needs to be true, if more security is desired and if charSet.Length is not divisible by 2^X. public string GenerateRandomString(int Length) //Configurable output string length { byte[] rBytes = new byte[Length]; //Do as much before and after lock as possible char[] rName = new char[Length]; lock (rGen) //~20-50ns { rGen.NextBytes(rBytes); for (int i = 0; i < Length; i++) { while (SlightlyMoreSecurityNeeded  rBytes[i] >= biasZone) //Secure against 1/5 increased bias of index[0-7] values against others. Note: Must exclude where it == biasZone (that is >=), otherwise there still a bias on index 0. rBytes[i] = rGen.NextByte(); rName[i] = charSet[rBytes[i] % charSet.Length]; } } return new string(rName); } 

Našumas:

ответ дан Merari Schroeder 05 окт. '09 в 9:22 2009-10-05 09:22