मैं यादृच्छिक अक्षरांकीय तार कैसे उत्पन्न कर सकता हूं?


966

मैं C # में एक यादृच्छिक 8 वर्ण अल्फ़ान्यूमेरिक स्ट्रिंग कैसे उत्पन्न कर सकता हूं?


2
यदि आपके पास चरित्र सेट पर कोई प्रतिबंध है तो क्या होगा? सिर्फ अंग्रेजी भाषा के अक्षर और 0-9? मिश्रित केस?
एरिक जे।


9
ध्यान दें कि Randomपासवर्ड बनाने के लिए आपको कक्षा के आधार पर किसी भी विधि का उपयोग नहीं करना चाहिए । बीजारोपण Randomबहुत कम एन्ट्रापी है, इसलिए यह वास्तव में सुरक्षित नहीं है। पासवर्ड के लिए एक क्रिप्टोग्राफ़िक PRNG का उपयोग करें।
कोडइन्चोस

2
इस सवाल में भाषा स्थानीयकरण को शामिल करना अच्छा होगा। खासकर यदि आपके गुई को चीनी या बल्गेरियाई के लिए पूरा करने की आवश्यकता है!
पीटर जमसमेनसन

15
इस कई upvotes के साथ कुछ और यह कई गुणवत्ता के जवाब बंद के रूप में चिह्नित करने के लिए योग्य नहीं है। मैं वोट देता हूं कि इसे फिर से खोल दिया जाए।
जॉन कोलमैन

जवाबों:


1684

मैंने सुना है LINQ नया काला है, इसलिए यहाँ 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());
}

(नोट: Randomकक्षा का उपयोग सुरक्षा से संबंधित किसी भी चीज़ के लिए अनुपयुक्त बनाता है , जैसे पासवर्ड या टोकन बनाना। RNGCryptoServiceProviderयदि आपको एक मजबूत यादृच्छिक संख्या जनरेटर की आवश्यकता है तो कक्षा का उपयोग करें ।)


23
@ एलेक्स: मैंने कुछ त्वरित परीक्षण चलाए हैं और लंबे समय तक तार उत्पन्न करते हुए (जब तक वास्तव में पर्याप्त स्मृति उपलब्ध है) उत्पन्न करने के लिए यह बहुत अधिक रैखिक पैमाने पर लगता है। ऐसा कहने के बाद, डैन रिग्बी का जवाब हर परीक्षा में लगभग दोगुना था।
ल्यूक

6
कुंआ। यदि आपका मानदंड है कि यह linq का उपयोग करता है और यह एक घटिया कोड कथा है तो यह निश्चित रूप से मधुमक्खी के घुटने है। निष्पादन की कोड कथा और वास्तविक मार्ग दोनों ही अक्षम और अप्रत्यक्ष हैं। मुझे गलत मत समझो, मैं एक विशाल कोड हिप्स्टर (i python) से प्यार करता हूं, लेकिन यह एक बहुत ही रब गोल्डबर्ग मशीन है।
eremzeit

5
हालांकि यह तकनीकी रूप से सवाल का जवाब देता है, यह आउटपुट बहुत भ्रामक है। 8 यादृच्छिक वर्णों को उत्पन्न करना ऐसा लगता है कि बहुत अधिक परिणाम हो सकते हैं , जबकि यह सबसे अच्छा 2 बिलियन विभिन्न परिणाम उत्पन्न करता है। और व्यवहार में भी कम। आपको किसी सुरक्षा संबंधित सामान के लिए इसका उपयोग नहीं करने के लिए एक BIG FAT चेतावनी भी जोड़नी चाहिए।
कोडइन्चौस

41
@xaisoft: लोअरकेस अक्षर को पाठक के लिए एक अभ्यास के रूप में छोड़ दिया जाता है।
dtb

15
निम्नलिखित पंक्ति अधिक स्मृति (और इस प्रकार) दिए गए एक से अधिक कुशल हैreturn new string(Enumerable.Range(1, length).Select(_ => chars[random.Next(chars.Length)]).ToArray());
टायसन विलियम्स

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

Linq समाधान के रूप में सुरुचिपूर्ण नहीं।

(नोट: Randomकक्षा का उपयोग सुरक्षा से संबंधित किसी भी चीज़ के लिए अनुपयुक्त बनाता है , जैसे पासवर्ड या टोकन बनाना। RNGCryptoServiceProviderयदि आपको एक मजबूत यादृच्छिक संख्या जनरेटर की आवश्यकता है तो कक्षा का उपयोग करें ।)


4
@ एलेक्स: यह पूर्ण रूप से सबसे तेज़ उत्तर नहीं है, लेकिन यह सबसे तेज़ "वास्तविक" उत्तर है (यानी, उनमें से जो इस्तेमाल किए गए वर्णों और स्ट्रिंग की लंबाई पर नियंत्रण की अनुमति देते हैं)।
ल्यूक

2
@ एलेक्स: एडम पोराड का GetRandomFileNameसमाधान तेज है, लेकिन उपयोग किए गए वर्णों के किसी भी नियंत्रण की अनुमति नहीं देता है और अधिकतम संभव लंबाई 11 वर्ण है। डगलस का Guidसमाधान बिजली की तेजी से है लेकिन वर्ण A-F0-9 तक ही सीमित हैं और अधिकतम संभव लंबाई 32 वर्ण है।
ल्यूक

1
@ एडडम: हां, आप कई कॉल के परिणाम को संक्षिप्त कर सकते हैं, GetRandomFileNameलेकिन तब (ए) आप अपना प्रदर्शन लाभ खो देंगे, और (बी) आपका कोड अधिक जटिल हो जाएगा।
ल्यूक

1
@xaisoft अपने लूप के बाहर रैंडम () ऑब्जेक्ट की अपनी आवृत्ति बनाएं। यदि आप थोड़े-थोड़े अंतराल में रैंडम () के बहुत सारे उदाहरण बनाते हैं तो कॉल .Next () रैंडम के समान मान लौटाएगा () समय आधारित बीज का उपयोग करता है।
दान रिग्बी

2
@xaisoft इस उत्तर का उपयोग किसी भी सुरक्षा के लिए महत्वपूर्ण नहीं है, जैसे पासवर्ड। System.Randomसुरक्षा के लिए उपयुक्त नहीं है।
कोडइन्चोस

333

टिप्पणियों के आधार पर अद्यतन। मूल कार्यान्वयन आह ~ समय का 1.95% और शेष वर्ण ~ 1.56% समय उत्पन्न करता है। अद्यतन समय के सभी वर्ण ~ 1.61% उत्पन्न करता है।

फ्रेमवर्क समर्थन - .NET कोर 3 (और भविष्य के प्लेटफ़ॉर्म जो .NET मानक 2.1 या उससे ऊपर का समर्थन करते हैं) एक क्रिप्टोग्राफिक रूप से ध्वनि विधि प्रदान करता है RandomNumberGenerator.GetInt32 () वांछित सीमा के भीतर एक यादृच्छिक पूर्णांक उत्पन्न करने के लिए।

प्रस्तुत कुछ विकल्पों के विपरीत, यह एक क्रिप्टोग्राफिक रूप से ध्वनि है

using System;
using System.Security.Cryptography;
using System.Text;

namespace UniqueKey
{
    public class KeyGenerator
    {
        internal static readonly char[] chars =
            "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray(); 

        public static string GetUniqueKey(int size)
        {            
            byte[] data = new byte[4*size];
            using (RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider())
            {
                crypto.GetBytes(data);
            }
            StringBuilder result = new StringBuilder(size);
            for (int i = 0; i < size; i++)
            {
                var rnd = BitConverter.ToUInt32(data, i * 4);
                var idx = rnd % chars.Length;

                result.Append(chars[idx]);
            }

            return result.ToString();
        }

        public static string GetUniqueKeyOriginal_BIASED(int size)
        {
            char[] chars =
                "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
            byte[] data = new byte[size];
            using (RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider())
            {
                crypto.GetBytes(data);
            }
            StringBuilder result = new StringBuilder(size);
            foreach (byte b in data)
            {
                result.Append(chars[b % (chars.Length)]);
            }
            return result.ToString();
        }
    }
}

यहां विकल्पों की चर्चा के आधार पर आधार पर और नीचे की टिप्पणियों के आधार पर अद्यतन / संशोधित किया गया है।

यहां एक छोटा परीक्षण हार्नेस है जो पुराने और अद्यतन आउटपुट में वर्णों के वितरण को प्रदर्शित करता है। Randomness के विश्लेषण की गहन चर्चा के लिए , random.org देखें।

using System;
using System.Collections.Generic;
using System.Linq;
using UniqueKey;

namespace CryptoRNGDemo
{
    class Program
    {

        const int REPETITIONS = 1000000;
        const int KEY_SIZE = 32;

        static void Main(string[] args)
        {
            Console.WriteLine("Original BIASED implementation");
            PerformTest(REPETITIONS, KEY_SIZE, KeyGenerator.GetUniqueKeyOriginal_BIASED);

            Console.WriteLine("Updated implementation");
            PerformTest(REPETITIONS, KEY_SIZE, KeyGenerator.GetUniqueKey);
            Console.ReadKey();
        }

        static void PerformTest(int repetitions, int keySize, Func<int, string> generator)
        {
            Dictionary<char, int> counts = new Dictionary<char, int>();
            foreach (var ch in UniqueKey.KeyGenerator.chars) counts.Add(ch, 0);

            for (int i = 0; i < REPETITIONS; i++)
            {
                var key = generator(KEY_SIZE); 
                foreach (var ch in key) counts[ch]++;
            }

            int totalChars = counts.Values.Sum();
            foreach (var ch in UniqueKey.KeyGenerator.chars)
            {
                Console.WriteLine($"{ch}: {(100.0 * counts[ch] / totalChars).ToString("#.000")}%");
            }
        }
    }
}

11
यह मेरे लिए सही दृष्टिकोण की तरह दिखता है - यादृच्छिक पासवर्ड, लवण, एन्ट्रॉपी और इसके आगे रैंडम () का उपयोग करके उत्पन्न नहीं किया जाना चाहिए जो कि गति के लिए अनुकूलित है और संख्याओं के प्रतिलिपि प्रस्तुत करने योग्य अनुक्रम उत्पन्न करता है; RNGCryptoServiceProvider.GetNonZeroBytes () दूसरी ओर संख्या के जंगली दृश्यों का उत्पादन करता है जो प्रतिलिपि प्रस्तुत करने योग्य नहीं हैं।
mindplay.dk

25
अक्षर थोड़े पक्षपाती (255% 62! = 0) हैं। इस मामूली दोष के बावजूद, यह अब तक का सबसे अच्छा समाधान है।
कोडइन्चोस 20

13
ध्यान दें कि यदि आप क्रिप्टो-ताकत, निष्पक्ष यादृच्छिकता चाहते हैं तो यह ध्वनि नहीं है । (और यदि आप ऐसा नहीं चाहते हैं, तो RNGCSPपहली जगह का उपयोग क्यों करें ?) charsसरणी में अनुक्रमित करने के लिए मॉड का उपयोग करने का मतलब है कि आप पक्षपाती आउटपुट प्राप्त करेंगे जब तक कि chars.Length256 का भाजक नहीं होगा।
ल्यूक

15
पूर्वाग्रह को कम करने की एक संभावना, 4*maxSizeयादृच्छिक बाइट्स का अनुरोध है , फिर उपयोग करें (UInt32)(BitConverter.ToInt32(data,4*i)% chars.Length। मैं भी के GetBytesबजाय का उपयोग करेंगे GetNonZeroBytes। और अंत में आप पहली कॉल को हटा सकते हैं GetNonZeroBytes। आप इसके परिणाम का उपयोग नहीं कर रहे हैं।
कोडइन्चोस

14
मजेदार तथ्य: AZ az 0-9 62 अक्षर हैं। लोग अक्षर पूर्वाग्रह को इंगित कर रहे हैं क्योंकि 256% 62! = 0. YouTube की वीडियो आईडी AZ az 0-9 हैं, साथ ही "-" और "_", जो 64 संभावित वर्णों का उत्पादन करता है, जो 256 समान रूप से विभाजित होता है। संयोग? मुझे नहीं लगता! :)
qJake

200

समाधान 1 - सबसे लचीली लंबाई के साथ सबसे बड़ी 'रेंज'

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

इस समाधान में GUID का उपयोग करने की तुलना में अधिक सीमा है क्योंकि एक GUID में कुछ निश्चित बिट्स होते हैं जो हमेशा समान होते हैं और इसलिए यादृच्छिक नहीं होते हैं, उदाहरण के लिए हेक्स में 13 वर्ण हमेशा "4" होता है - कम से कम एक संस्करण 6 GUID में।

यह समाधान आपको किसी भी लम्बाई की एक स्ट्रिंग उत्पन्न करने देता है।

समाधान 2 - कोड की एक पंक्ति - 22 वर्णों के लिए अच्छा है

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

जब तक आप समाधान 1 को तार नहीं बना सकते और स्ट्रिंग GUID में बिट्स के कारण समान सीमा नहीं है, , लेकिन बहुत सारे मामलों में यह कार्य करेगा।

समाधान 3 - थोड़ा कम कोड

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

ज्यादातर इसे ऐतिहासिक उद्देश्य के लिए यहां रखा जाता है। यह थोड़ा कम कोड का उपयोग करता है, हालांकि यह कम रेंज होने के खर्च के रूप में आता है - क्योंकि यह base64 के बजाय हेक्स का उपयोग करता है यह अन्य वर्णों की तुलना में एक ही सीमा का प्रतिनिधित्व करने के लिए अधिक वर्ण लेता है।

जिसका अर्थ है टक्कर की अधिक संभावना - 8 वर्ण तारों के 100,000 पुनरावृत्तियों के साथ इसका परीक्षण करना एक डुप्लिकेट उत्पन्न करता है।


22
आप वास्तव में एक डुप्लिकेट उत्पन्न? GUID के संभावित संयोजनों में 5,316,911,983,139,663,491,615,228,241,121,400,000 संभावित आश्चर्य।
एलेक्स

73
@ एलेक्स: वह GUID को 8 वर्णों को छोटा कर रहा है, इसलिए टक्कर की संभावना GUID की तुलना में बहुत अधिक है।
dtb

23
Nerds के अलावा कोई भी इसकी सराहना नहीं कर सकता है :) हां आप बिल्कुल सही हैं, 8 char की सीमा से फर्क पड़ता है।
एलेक्स

31
गाइड.न्यूजीड ()। ToString ("n") डैश को बाहर रखेगा, कोई रिप्लेसमेंट () कॉल की आवश्यकता नहीं है। लेकिन यह उल्लेख किया जाना चाहिए, GUID केवल 0-9 और AF हैं। संयोजनों की संख्या "काफी अच्छी है", लेकिन कहीं भी एक सच्चे अल्फ़ान्यूमेरिक यादृच्छिक स्ट्रिंग परमिट के करीब नहीं है । टक्कर की संभावना 1: 4,294,967,296 है - एक यादृच्छिक 32-बिट पूर्णांक के समान।
richardtallent

32
1) GUIDs को अद्वितीय होने के लिए डिज़ाइन किया गया है, यादृच्छिक नहीं। जबकि विंडोज़ के वर्तमान संस्करण V4 GUID उत्पन्न करते हैं जो वास्तव में यादृच्छिक हैं, इसकी गारंटी नहीं है। उदाहरण के लिए विंडोज़ के पुराने संस्करणों ने V1 GUID का उपयोग किया, जहां आपकी विफलता विफल हो जाएगी। 2) हेक्स पात्रों का उपयोग करने से यादृच्छिक स्ट्रिंग की गुणवत्ता में काफी कमी आती है। 47 से 32 बिट्स तक। 3) लोग टकराव की संभावना को कम कर रहे हैं, क्योंकि वे इसे व्यक्तिगत जोड़े के लिए देते हैं। यदि आप 100k 32 बिट मान उत्पन्न करते हैं, तो संभवतः आपके बीच एक टक्कर है। जन्मदिन समस्या देखें।
कोडइन्चोस 12

72

यहाँ एक उदाहरण है कि मैंने डॉट नेट पर्ल्स पर सैम एलन उदाहरण से चुरा लिया है

यदि आपको केवल 8 वर्णों की आवश्यकता है, तो System.IO नाम स्थान में Path.GetRandomFileName () का उपयोग करें। सैम कहते हैं, "Path.GetRandomFileName विधि यहाँ का उपयोग करना कभी-कभी बेहतर होता है, क्योंकि यह बेहतर यादृच्छिकता के लिए RNGCryptoServiceProvider का उपयोग करता है। हालांकि, यह 11 यादृच्छिक वर्णों तक सीमित है।"

GetRandomFileName हमेशा 9 वें चरित्र की अवधि के साथ 12 वर्ण स्ट्रिंग देता है। तो आपको अवधि (क्योंकि यह यादृच्छिक नहीं है) पट्टी करने की आवश्यकता होगी और फिर स्ट्रिंग से 8 वर्णों को लें। वास्तव में, आप पहले 8 अक्षर ले सकते हैं और अवधि के बारे में चिंता नहीं करते।

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

पुनश्च: धन्यवाद सैम


27
यह अच्छा काम करता है। मैंने इसे 100,000 पुनरावृत्तियों के माध्यम से चलाया और कभी भी इसका डुप्लिकेट नाम नहीं था। हालांकि, मैं था कई अभद्र शब्द (अंग्रेजी में) लगता है। इस बारे में भी नहीं सोचा होगा कि सूची में पहले लोगों में से एक को छोड़कर इसमें F *** था। यदि आप उपयोगकर्ता द्वारा देखी जाने वाली किसी चीज़ के लिए इसका उपयोग करते हैं तो बस एक हेड अप।
Techturtle

3
@techturtle चेतावनी के लिए धन्यवाद। मुझे लगता है कि वर्णमाला के सभी अक्षरों का उपयोग करने वाले किसी भी यादृच्छिक स्ट्रिंग पीढ़ी के साथ अशिष्ट शब्दों के लिए एक जोखिम है।
एडम पोराड

अच्छा और सरल लेकिन लंबी स्ट्रिंग के लिए अच्छा नहीं ... इस अच्छी चाल के लिए वोट करें
मैहर अबुथ्रा

यह विधि केवल निचले मामले अल्फ़ान्यूमेरिक स्ट्रिंग्स को वापस करने के लिए लगता है।
14

2
समय-समय पर अश्लील शब्द आते हैं, लेकिन अगर आप इसे लंबे समय तक चला रहे हैं तो अंततः यह शेक्सपियर लिखता है। (ब्रह्मांड के कुछ ही जीवनकाल। :)
स्लॉथैरियो

38

मेरे कोड के मुख्य लक्ष्य हैं:

  1. तार का वितरण लगभग समान है (जब तक वे छोटे हैं, तब तक मामूली विचलन की परवाह न करें)
  2. यह प्रत्येक तर्क सेट के लिए कुछ बिलियन स्ट्रिंग्स से अधिक आउटपुट देता है। 8 वर्ण स्ट्रिंग (~ 47 बिट्स ऑफ एन्ट्रॉपी) उत्पन्न करना अर्थहीन है यदि आपका PRNG केवल 2 बिलियन (31 बिट्स ऑफ एन्ट्रापी) विभिन्न मान उत्पन्न करता है।
  3. यह सुरक्षित है, क्योंकि मुझे उम्मीद है कि लोग पासवर्ड या अन्य सुरक्षा टोकन के लिए इसका उपयोग करेंगे।

वर्णमाला के आकार का 64 बिट मान लेकर पहली प्रॉपर्टी हासिल की जाती है। छोटे अक्षर के लिए (जैसे प्रश्न से 62 वर्ण) यह नगण्य पूर्वाग्रह की ओर जाता है। दूसरी और तीसरी संपत्ति का उपयोग करके प्राप्त किया 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];
    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);
}

1
64 x Z और Math.Pow (2, Y) के साथ कोई चौराहा नहीं है। इसलिए बड़ी संख्या बनाते समय पूर्वाग्रह को कम करता है, यह इसे खत्म नहीं करता है। मैंने नीचे अपना जवाब अपडेट किया, मेरा दृष्टिकोण यादृच्छिक आदानों को त्यागने और दूसरे मूल्य के साथ बदलने का था।
टॉड

@ मुझे पता है कि यह पूर्वाग्रह को खत्म नहीं करता है, लेकिन मैंने व्यावहारिक रूप से अप्रासंगिक पूर्वाग्रह को खत्म करने के लिए इस समाधान की सादगी को चुना।
कोडइन्चोस

मैं ज्यादातर मामलों के लिए सहमत हूं, यह संभवतः व्यावहारिक रूप से अप्रासंगिक है। लेकिन अब मैंने अपना रैंडम रैंडम के रूप में तेजी से और आपके मुकाबले थोड़ा अधिक सुरक्षित होने के लिए अपडेट किया है। सभी को साझा करने के लिए सभी खुले स्रोत। हां, मैंने इस पर बहुत समय बर्बाद किया ...
टोड

यदि हम RNG प्रदाता का उपयोग कर रहे हैं तो क्या हमारे पास सिद्धांत में पूर्वाग्रह से बचने का कोई तरीका है? मुझे यकीन नहीं है ... यदि टॉड का मतलब है जब वह अतिरिक्त यादृच्छिक संख्या (जब हम पूर्वाग्रह क्षेत्र में होते हैं) उत्पन्न करते हैं तो यह गलत धारणा हो सकती है। RNG में औसतन सभी उत्पन्न मूल्यों का लगभग रेखीय वितरण है। लेकिन इसका मतलब यह नहीं है कि उत्पन्न बाइट्स के बीच हमारा स्थानीय संबंध नहीं होगा। इसलिए केवल बायस ज़ोन के लिए अतिरिक्त बाइट अभी भी हमें कुछ पूर्वाग्रह दे सकता है लेकिन अलग कारण के कारण। सबसे अधिक संभावना है कि यह पूर्वाग्रह बहुत छोटा होगा। इस मामले में कुल उत्पन्न बाइट की बढ़ती संख्या अधिक सीधा तरीका है।
मैक्सिम

1
@ मोम आप पूरी तरह से पूर्वाग्रह को खत्म करने के लिए अस्वीकृति का उपयोग कर सकते हैं (अंतर्निहित जनरेटर पूरी तरह से यादृच्छिक है)। बदले में कोड मनमाने ढंग से लंबा (तेजी से छोटी संभावना के साथ) चल सकता है।
कोडइंचौस

32

सबसे आसान:

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

आप बेहतर प्रदर्शन प्राप्त कर सकते हैं यदि आप चार वर्णों को हार्ड कोड देते हैं और भरोसा करते हैं System.Random:

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

अगर आपको कभी चिंता होती है कि अंग्रेजी अक्षर कुछ समय के आसपास बदल सकते हैं और आप व्यवसाय खो सकते हैं, तो आप हार्ड कोडिंग से बच सकते हैं, लेकिन थोड़ा खराब प्रदर्शन करना चाहिए ( Path.GetRandomFileNameदृष्टिकोण के लिए तुलनीय )

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

पिछले दो दृष्टिकोण बेहतर दिखते हैं यदि आप उन्हें System.Randomउदाहरण के लिए एक विस्तार विधि बना सकते हैं ।


1
उपयोग करना chars.Selectएक बड़ा बदसूरत है क्योंकि यह सबसे अधिक वर्णमाला के आकार में आउटपुट आकार पर निर्भर करता है।
कोडइंचौस

@CodesInChaos मुझे यकीन नहीं है कि अगर मैं आपको समझता हूं। आप 'a'.To('z')दृष्टिकोण में मतलब है ?
नवफाल

1
1)। chars.Select()टेक (एन) `केवल काम करता है अगर chars.Count >= n। एक अनुक्रम पर चयन करना जो आप वास्तव में उपयोग नहीं करते हैं, थोड़ा सा अनपेक्षित है, विशेष रूप से उस अंतर्निहित लंबाई बाधा के साथ। मैं बल्कि उपयोग करूँगा Enumerable.Rangeया Enumerable.Repeat। 2) एरर मैसेज "एंड चार्ज़ स्टार्ट बी से कम होना चाहिए" गलत तरीका है राउंड / मिसिंग ए not
कोडइन्चोस

@CodesInChaos लेकिन मेरे मामले chars.Countमें तरीका है > n। इसके अलावा मैं unintuitive हिस्सा नहीं मिलता है। यह सभी का उपयोग करता है Takeunintuitive इसे नहीं करता है? मुझे विश्वास नहीं होता। टाइपो को इंगित करने के लिए धन्यवाद।
नवफाल

4
यह कोड कोड लेख के रूप में theDailyWTF.com पर चित्रित किया गया है ।

22

इस धागे में विभिन्न जवाबों की तुलना में बस कुछ प्रदर्शन:

तरीके और सेटअप

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

परिणाम

LinqPad में परीक्षण किया गया। 10 के स्ट्रिंग आकार के लिए, उत्पन्न करता है:

  • Linq से = chdgmevhcy [10]
  • लूप = gtnoaryhxr [10] से
  • चयन करें = rsndbztyby [10] से
  • GenerateRandomString = owyefjjakj [10] से
  • SecureFastRandom = VzougLYHYP [10] से
  • SecureFastRandom-NoCache = oVQXNGmO1S [10] से

और प्रदर्शन संख्याओं में थोड़ा भिन्न होता है, कभी-कभी NonOptimizedवास्तव में तेज होता है, और कभी-कभी ForLoopऔर GenerateRandomStringस्विच करता है जो लीड में है।

  • LinqIsTheNewBlack (10000x) = 96762 टिक टिक गए (9.6762 एमएस)
  • फोरप्लॉप (10000x) = 28970 टिके हुए (2.897 एमएस)
  • ForLoopNonOptimized (10000x) = 33336 टिके हुए (3.3336 एमएस)
  • दोहराना (10000x) = 78547 टिके हुए (7.8547 एमएस)
  • GenerateRandomString (10000x) = 27416 टिके हुए (2.7416 एमएस)
  • SecureFastRandom (10000x) = 13176 टिक (5ms) सबसे कम [अलग मशीन]
  • SecureFastRandom-NoCache (10000x) = 39541 टिक (17ms) सबसे कम [अलग मशीन]

3
यह जानना दिलचस्प होगा कि किन लोगों ने नकल की।
रेबेका

@ जूनो - यह पता लगाने के लिए कि डुप्लिकेट में कौन सा परिणाम है, कुछ ऐसा है var many = 10000; Assert.AreEqual(many, new bool[many].Select(o => EachRandomizingMethod(10)).Distinct().Count());, जहां आप प्रतिस्थापित EachRandomizingMethodकरते हैं ... प्रत्येक विधि
drzaus

19

कोड की एक लाइन Membership.GeneratePassword()चाल है :)

यहाँ उसी के लिए एक डेमो है


1
माइक्रोसॉफ्ट की तरह लग रहा लिंक चले गए .. एक और कोड नमूना पर है msdn.microsoft.com/en-us/library/ms152017 या aspnet.4guysfromrolla.com/demos/GeneratePassword.aspx या developer.xamarin.com/api/member/...
पूरन

मुझे लगता है कि लेकिन गैर अल्फ़ान्यूमेरिक वर्णों से छुटकारा नहीं पा सकता था क्योंकि दूसरा तर्क
मिनिमम

13

एरिक जे द्वारा लिखित कोड काफी मैला है (यह काफी स्पष्ट है कि यह 6 साल पहले से है ... वह शायद आज उस कोड को नहीं लिखेंगे), और यहां तक ​​कि कुछ समस्याएं भी हैं।

प्रस्तुत कुछ विकल्पों के विपरीत, यह एक क्रिप्टोग्राफिक रूप से ध्वनि है।

असत्य ... पासवर्ड में एक पूर्वाग्रह है (जैसा कि एक टिप्पणी में लिखा गया है), bcdefghदूसरों की तुलना में थोड़ा अधिक संभावित हैं ( aऐसा नहीं है क्योंकि GetNonZeroBytesयह शून्य के मूल्य के साथ बाइट्स पैदा नहीं कर रहा है, इसलिए पूर्वाग्रह इसके लिए aसंतुलित है), इसलिए यह वास्तव में क्रिप्टोग्राफिक रूप से ध्वनि नहीं है।

यह सभी समस्याओं को ठीक करना चाहिए।

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

7

हम कस्टम स्ट्रिंग का भी बेतरतीब ढंग से इस्तेमाल करते हैं लेकिन हमने लागू किया है एक स्ट्रिंग के सहायक के रूप में तो यह कुछ लचीलापन प्रदान करता है ...

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

प्रयोग

var random = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".Random();

या

var random = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".Random(16);

7

मेरा सरल एक लाइन कोड मेरे लिए काम करता है :)

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

Response.Write(random.ToUpper());
Response.Write(random.ToLower());

किसी भी लंबाई स्ट्रिंग के लिए इस पर विस्तार करने के लिए

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

मुझे
गाइड

6

एक अन्य विकल्प Linq का उपयोग करना और एक स्ट्रिंगर में यादृच्छिक वर्ण एकत्र करना हो सकता है।

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

6

प्रश्न: मुझे Enumerable.Rangeटाइप करने के बजाय अपना समय क्यों बर्बाद करना चाहिए "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;
    }
}

उत्तर: मैजिक स्ट्रिंग्स BAD हैं। क्या किसी ने नोटिस किया "I किया कि शीर्ष पर मेरी स्ट्रिंग में " ? मेरी माँ ने मुझे सिखाया कि इस कारण जादू के तार का इस्तेमाल न करें ...

nb 1: @dtb जैसे कई अन्य लोगों ने कहा, System.Randomयदि आपको क्रिप्टोग्राफ़िक सुरक्षा की आवश्यकता है , तो इसका उपयोग न करें ...

nb 2: यह उत्तर सबसे अधिक कुशल या छोटा नहीं है, लेकिन मैं इस प्रश्न से उत्तर को अलग करने के लिए स्थान चाहता था। मेरे जवाब का उद्देश्य एक जादुई अभिनव जवाब देने की तुलना में जादू के तार के खिलाफ चेतावनी देना अधिक है।


मुझे क्यों परवाह है कि कोई "नहीं है I?"
क्रिस्टिन

1
अल्फ़ान्यूमेरिक (मामले की अनदेखी) है [A-Z0-9]। यदि, गलती से, आपका यादृच्छिक स्ट्रिंग केवल [A-HJ-Z0-9]परिणाम को कवर करता है, तो पूर्ण स्वीकार्य सीमा को कवर नहीं करता है, जो समस्याग्रस्त हो सकता है।
वाई हा ली

यह समस्यात्मक कैसे होगा? तो यह शामिल नहीं है I। क्या यह इसलिए है क्योंकि एक कम चरित्र है और यह दरार करना आसान बनाता है? क्रैकेबल पासवर्ड पर आंकड़े क्या हैं, जिसमें 36 की तुलना में 35 वर्ण हैं। मुझे लगता है कि मैं इसे जोखिम में डालना चाहता हूं ... या केवल चरित्र सीमा को रीड करें ... मेरे कोड में वह सभी अतिरिक्त कचरा शामिल हैं। लेकिन, वह मैं हूं। मेरा मतलब है, बट होल नहीं, मैं सिर्फ कह रहा हूं। कभी-कभी मुझे लगता है कि प्रोग्रामर के पास अतिरिक्त-जटिल होने के लिए अतिरिक्त-जटिल मार्ग है।
क्रिस्टीन

1
यह उपयोग के मामले पर गहरा होता है। इस तरह के Iऔर Oइस प्रकार के बेतरतीब तारों से पात्रों को बाहर करना बहुत आम है, ताकि मनुष्यों को उनके साथ भ्रमित किया जा सके 1और 0। यदि आप मानव-पढ़ने योग्य स्ट्रिंग होने के बारे में परवाह नहीं करते हैं, तो ठीक है, लेकिन अगर यह कुछ ऐसा है जिसे किसी को टाइप करने की आवश्यकता हो सकती है, तो यह वास्तव में आपके पात्रों को हटाने के लिए स्मार्ट है।
क्रिस प्रैट

5

DTB के समाधान का थोड़ा क्लीनर संस्करण।

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

आपकी शैली प्राथमिकताएँ भिन्न हो सकती हैं।


यह स्वीकृत उत्तर की तुलना में बहुत बेहतर और कुशल है।
कील

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

5

अन्य जवाबों की समीक्षा करने और CodeInChaos की टिप्पणियों पर विचार करने के बाद, CodeInChaos के साथ अभी भी पक्षपाती (हालांकि कम) जवाब है, मैंने सोचा कि अंतिम अंतिम कट और पेस्ट समाधान की आवश्यकता थी। इसलिए अपने जवाब को अपडेट करते हुए मैंने सभी बाहर जाने का फैसला किया।

इस कोड के अद्यतित संस्करण के लिए, कृपया Bitbucket पर नई Hg रिपॉजिटरी पर जाएँ: https://bitbucket.org/merarischroeder/secureswiftrandom । मैं आपको कोड की प्रतिलिपि बनाने और उससे कोड पेस्ट करने की सलाह देता हूं: https://bitbucket.org/merarischroeder/secureswiftrandom/src/6c14b874f34a3f6576b0213379ecdfcffc7496ea/Code/Alivate.SolidSwiftRwift.iftRiftRiftRift.ift (सुनिश्चित करें कि आप क्लिक करें कच्चे बटन को कॉपी करना आसान है और सुनिश्चित करें कि आपके पास नवीनतम संस्करण है, मुझे लगता है कि यह लिंक कोड के एक विशिष्ट संस्करण पर जाता है, नवीनतम नहीं)।

अपडेट किए गए नोट:

  1. कुछ अन्य उत्तरों से संबंधित - यदि आप आउटपुट की लंबाई जानते हैं, तो आपको StringBuilder की आवश्यकता नहीं है, और ToCharArray का उपयोग करते समय, यह सरणी को बनाता है और भरता है (आपको पहले खाली सरणी बनाने की आवश्यकता नहीं है)
  2. कुछ अन्य उत्तरों से संबंधित - आपको प्रदर्शन के लिए एक समय पर एक होने के बजाय, नेक्स्टबाइट्स का उपयोग करना चाहिए
  3. तकनीकी रूप से आप तेजी से पहुंच के लिए बाइट सरणी को पिन कर सकते हैं .. यह आमतौर पर इसके लायक है जब आपका बाइट सरणी पर 6-8 से अधिक बार पुनरावृति करता है। (यहाँ नहीं किया गया)
  4. सर्वश्रेष्ठ यादृच्छिकता के लिए RNGCryptoServiceProvider का उपयोग
  5. यादृच्छिक डेटा के 1 एमबी बफर के कैशिंग का उपयोग - बेंचमार्किंग से पता चलता है कि कैश्ड सिंगल बाइट्स एक्सेस स्पीड ~ 1000x तेज़ है - अनचाहे के लिए 1 एमबी बनाम 989ms पर 9ms ले रही है।
  6. मेरी नई कक्षा के भीतर पूर्वाग्रह क्षेत्र का अनुकूलित अस्वीकृति

प्रश्न का अंतिम समाधान:

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

लेकिन आपको मेरी नई (अप्रयुक्त) श्रेणी की आवश्यकता है:

/// <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
        }
    }
}

इतिहास के लिए - इस उत्तर के लिए मेरा पुराना समाधान, रैंडम ऑब्जेक्ट का उपयोग किया गया है:

    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's still a bias on index 0.
                  rBytes[i] = rGen.NextByte();
              rName[i] = charSet[rBytes[i] % charSet.Length];
          }
      }
      return new string(rName);
    }

प्रदर्शन:

  1. सिक्योर फ़र्स्टग्रैंड - पहला एकल रन = ~ 9-33 मी । अतीन्द्रिय। चल रहा है : 10,000 से अधिक पुनरावृत्तियों पर 5ms (कभी-कभी यह 13ms तक जाता है), एक एकल औसत चलना = 1.5 माइक्रोसेकंड के साथ।। नोट: आम तौर पर 2 की आवश्यकता होती है, लेकिन कभी-कभी 8 कैश रीफ्रेश तक - यह निर्भर करता है कि कितने सिंगल बाइट्स पूर्वाग्रह क्षेत्र से अधिक हैं
  2. रैंडम - पहला एकल रन = ~ 0-1ms । अतीन्द्रिय। चल रहा है : 10,000 से अधिक पुनरावृत्तियों पर 5ms । एक एकल औसत चलना = .5 माइक्रोसेकंड के साथ। । उसी गति के बारे में।

यह भी देखें:

ये लिंक एक और दृष्टिकोण हैं। बफ़रिंग को इस नए कोड बेस में जोड़ा जा सकता है, लेकिन सबसे महत्वपूर्ण पूर्वाग्रह को हटाने के लिए अलग-अलग दृष्टिकोणों की खोज कर रहा था, और गति और पेशेवरों / विपक्ष को बेंचमार्क कर रहा था।


मुझे आपकी विधि में कुछ मामूली प्रदर्शन संवर्द्धन मिला, जो गुच्छा का उपवास लग रहा था - stackoverflow.com/a/17092645/1037948
drzaus

5
1) क्यों उन सभी जादू स्थिरांक? आपने आउटपुट लंबाई तीन बार निर्दिष्ट की । बस इसे एक स्थिर या एक पैरामीटर के रूप में परिभाषित करें। आप उपयोग कर सकते हैं charSet.Lengthके बजाय 62। 2) Randomलॉकिंग के बिना एक स्थिर का मतलब है कि यह कोड थ्रेडसेफ़ नहीं है। 3) 0-255 मॉड 62 को कम करना एक पता लगाने योग्य पूर्वाग्रह का परिचय देता है। 4) आप ToStringएक चारपाइयों पर उपयोग नहीं कर सकते , जो हमेशा लौटता है "System.Char[]"। आपको new String(rName)इसके बजाय उपयोग करने की आवश्यकता है ।
कोडइन्चोस

धन्यवाद @CodesInChaos, मैंने उन चीजों के बारे में कभी नहीं सोचा था। अभी भी केवल रैंडम क्लास का उपयोग कर रहे हैं, लेकिन यह बेहतर होना चाहिए। मैं पूर्वाग्रह इनपुट का पता लगाने और सही करने के लिए किसी भी बेहतर तरीके के बारे में नहीं सोच सकता।
टोड

यह कमजोर आरएनजी ( System.Random) के साथ शुरू करने के लिए थोड़ा मूर्खतापूर्ण है और फिर ध्यान से अपने स्वयं के कोड में किसी भी पूर्वाग्रह से बचना है। "मन को चमकाने वाली" अभिव्यक्ति मन में आती है।
कोडइन्चोस

@CodesInChaos और अब प्रशिक्षु ने
टोड

4

भयानक, मुझे पता है, लेकिन मैं सिर्फ अपनी मदद नहीं कर सकता:


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

मैं एक अधिक विशिष्ट उत्तर की तलाश में था, जहां मैं यादृच्छिक स्ट्रिंग के प्रारूप को नियंत्रित करना चाहता हूं और इस पद पर आया हूं। उदाहरण के लिए: लाइसेंस प्लेट (कारों का) का एक विशिष्ट प्रारूप (प्रति देश) है और मैं यादृच्छिक लाइसेंस प्लेट बनाना चाहता था।
मैंने इसके लिए रैंडम की अपनी विस्तार विधि लिखने का फैसला किया। (यह उसी रैंडम ऑब्जेक्ट का पुन: उपयोग करने के लिए है, जैसा कि आप मल्टी-थ्रेडिंग परिदृश्यों में डबल्स कर सकते थे)। मैंने एक gist ( https://gist.github.com/SamVanhoutte/808845ca78b9c041e928 ) बनाया, लेकिन यहां एक्सटेंशन क्लास की प्रतिलिपि भी बनाऊंगा:

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

अब एक-लाइनर स्वाद में।

private string RandomName()
{
        return new string(
            Enumerable.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 13)
                .Select(s =>
                {
                    var cryptoResult = new byte[4];
                    using (var cryptoProvider = new RNGCryptoServiceProvider())
                        cryptoProvider.GetBytes(cryptoResult);

                    return s[new Random(BitConverter.ToInt32(cryptoResult, 0)).Next(s.Length)];
                })
                .ToArray());
}

2
किसी ऐसी चीज़ के लिए एक संपत्ति का उपयोग करना जो हर पहुंच में परिवर्तन करती है, बल्कि संदिग्ध होती है। मैं इसके बजाय एक विधि का उपयोग करने की सलाह दूंगा।
कोडइन्चोस

2
RNGCryptoServiceProviderउपयोग के बाद निपटाया जाना चाहिए।
त्सही अशर

मैंने IDisposable समस्या को ठीक कर दिया है, लेकिन यह अभी भी अत्यधिक संदिग्ध है, प्रत्येक अक्षर के लिए एक नया RNGCryptoServiceProvider बना रहा है।
पीजो

@CodesInChaos किया, अब एक विधि।
माटस वैतकेविसियस

3

दो भागों को संयोजित करने का प्रयास करें: अद्वितीय (अनुक्रम, काउंटर या दिनांक) और यादृच्छिक

public class RandomStringGenerator
{
    public static string Gen()
    {
        return ConvertToBase(DateTime.UtcNow.ToFileTimeUtc()) + GenRandomStrings(5); //keep length fixed at least of one part
    }

    private static string GenRandomStrings(int strLen)
    {
        var result = string.Empty;

        var Gen = new RNGCryptoServiceProvider();
        var data = new byte[1];

        while (result.Length < strLen)
        {
            Gen.GetNonZeroBytes(data);
            int code = data[0];
            if (code > 48 && code < 57 || // 0-9
                code > 65 && code < 90 || // A-Z
                code > 97 && code < 122   // a-z
                )
            {
                result += Convert.ToChar(code);
            }
        }

        return result;
    }

    private static string ConvertToBase(long num, int nbase = 36)
    {
        var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //if you wish make algorithm more secure - change order of letter here

        // check if we can convert to another base
        if (nbase < 2 || nbase > chars.Length)
            return null;

        int r;
        var newNumber = string.Empty;

        // in r we have the offset of the char that was converted to the new base
        while (num >= nbase)
        {
            r = (int) (num % nbase);
            newNumber = chars[r] + newNumber;
            num = num / nbase;
        }
        // the last number to convert
        newNumber = chars[(int)num] + newNumber;

        return newNumber;
    }
}

टेस्ट:

[Test]
    public void Generator_Should_BeUnigue1()
    {
        //Given
        var loop = Enumerable.Range(0, 1000);
        //When
        var str = loop.Select(x=> RandomStringGenerator.Gen());
        //Then
        var distinct = str.Distinct();
        Assert.AreEqual(loop.Count(),distinct.Count()); // Or Assert.IsTrue(distinct.Count() < 0.95 * loop.Count())
    }

1) आप उन पात्रों से जुड़े ASCII मूल्यों के बजाय चरित्र शाब्दिक का उपयोग कर सकते हैं। 2) आप अपने अंतराल मिलान कोड में एक-एक गलती करते हैं। आप उपयोग करने की आवश्यकता <=है और >=के बजाय <और >। 3) मैं &&अभिव्यक्तियों के चारों ओर अनावश्यक कोष्ठक जोड़ूंगा ताकि यह स्पष्ट हो सके कि उनमें पूर्वता है, लेकिन निश्चित रूप से यह केवल एक शैलीगत विकल्प है।
कोडइन्चोस

+ 1 पूर्वाग्रह को दूर करने और परीक्षण को जोड़ने के लिए अच्छा है। मुझे यकीन नहीं है कि आप टाइमस्टैम्प-व्युत्पन्न स्ट्रिंग के साथ अपने यादृच्छिक स्ट्रिंग को क्यों दिखाते हैं? इसके अलावा, आपको अभी भी अपने RNGCryptoServiceProvider
monty

2

उपयोग किए बिना एक समाधान Random:

var chars = Enumerable.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 8);

var randomStr = new string(chars.SelectMany(str => str)
                                .OrderBy(c => Guid.NewGuid())
                                .Take(8).ToArray());

2
न्यूगिड आंतरिक रूप से यादृच्छिक का उपयोग करता है। तो यह अभी भी यादृच्छिक का उपयोग कर रहा है, यह सिर्फ इसे छिपा रहा है।
कील

2

यहां WinRT (विंडोज स्टोर ऐप) के लिए एरिक जे के समाधान का एक संस्करण है, अर्थात क्रिप्टोग्राफिक रूप से ध्वनि,

public static string GenerateRandomString(int length)
{
    var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
    var result = new StringBuilder(length);
    for (int i = 0; i < length; ++i)
    {
        result.Append(CryptographicBuffer.GenerateRandomNumber() % chars.Length);
    }
    return result.ToString();
}

यदि प्रदर्शन मायने रखता है (विशेषकर जब लंबाई अधिक हो):

public static string GenerateRandomString(int length)
{
    var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
    var result = new System.Text.StringBuilder(length);
    var bytes = CryptographicBuffer.GenerateRandom((uint)length * 4).ToArray();
    for (int i = 0; i < bytes.Length; i += 4)
    {
        result.Append(BitConverter.ToUInt32(bytes, i) % chars.Length);
    }
    return result.ToString();
}

1
यह क्रिप्टोग्राफिक रूप से ध्वनि नहीं है। मॉडुलस ऑपरेशन के कारण एक छोटा सा पूर्वाग्रह है कि यह पूरी तरह से उल्टी की पूरी चौड़ाई को 62 चार्ट में नहीं फैलाएगा।
रेयान

1

मुझे पता है कि यह सबसे अच्छा तरीका नहीं है। लेकिन आप यह कोशिश कर सकते हैं।

string str = Path.GetRandomFileName(); //This method returns a random file name of 11 characters
str = str.Replace(".","");
Console.WriteLine("Random string: " + str);

2
वह एक पंक्ति कैसे है? Console.WriteLine ($ "रैंडम स्ट्रिंग: {Path.GetRandomFileName) ()। प्रतिस्थापन (", ",")} "); एक पंक्ति है।
पमनसैस

1

मुझे नहीं पता कि यह कैसे क्रिप्टोग्राफिक रूप से ध्वनि है, लेकिन यह अधिक जटिल समाधानों की तुलना में अधिक पठनीय और संक्षिप्त है (इमो), और यह System.Random-ब्लेड समाधानों की तुलना में अधिक "यादृच्छिक" होना चाहिए ।

return alphabet
    .OrderBy(c => Guid.NewGuid())
    .Take(strLength)
    .Aggregate(
        new StringBuilder(),
        (builder, c) => builder.Append(c))
    .ToString();

मैं यह तय नहीं कर सकता कि क्या मुझे लगता है कि यह संस्करण है या अगला "प्रेटियर" है, लेकिन वे ठीक उसी परिणाम देते हैं:

return new string(alphabet
    .OrderBy(o => Guid.NewGuid())
    .Take(strLength)
    .ToArray());

दी, यह गति के लिए अनुकूलित नहीं है, इसलिए यदि यह हर सेकंड लाखों यादृच्छिक तार उत्पन्न करने के लिए महत्वपूर्ण है, तो एक और प्रयास करें!

नोट: यह समाधान वर्णमाला में प्रतीकों की पुनरावृत्ति की अनुमति नहीं देता है, और वर्णमाला आउटपुट स्ट्रिंग की तुलना में समान या अधिक आकार का होना चाहिए, इस दृष्टिकोण को कुछ परिस्थितियों में कम वांछनीय बनाता है, यह सब आपके उपयोग-मामले पर निर्भर करता है।


0

यदि आपके मूल्य पूरी तरह से यादृच्छिक नहीं हैं, लेकिन वास्तव में कुछ पर निर्भर हो सकता है - आप उस 'somwthing' के एक md5 या sha1 हैश की गणना कर सकते हैं और फिर इसे उस लंबाई तक काट सकते हैं जो आप चाहते हैं।

साथ ही आप एक गाइड को जनरेट कर सकते हैं और काट सकते हैं।


0
public static class StringHelper
{
    private static readonly Random random = new Random();

    private const int randomSymbolsDefaultCount = 8;
    private const string availableChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    private static int randomSymbolsIndex = 0;

    public static string GetRandomSymbols()
    {
        return GetRandomSymbols(randomSymbolsDefaultCount);
    }

    public static string GetRandomSymbols(int count)
    {
        var index = randomSymbolsIndex;
        var result = new string(
            Enumerable.Repeat(availableChars, count)
                      .Select(s => {
                          index += random.Next(s.Length);
                          if (index >= s.Length)
                              index -= s.Length;
                          return s[index];
                      })
                      .ToArray());
        randomSymbolsIndex = index;
        return result;
    }
}

2
1) स्थिर तरीके थ्रेड सुरक्षित होना चाहिए। 2) random.Nextसीधे परिणाम का उपयोग करने के बजाय सूचकांक को बढ़ाने की बात क्या है ? कोड की शिकायत करता है और उपयोगी कुछ भी हासिल नहीं करता है।
कोडइंचोज

0

यहाँ एक यादृच्छिक अल्फा-न्यूमेरिक स्ट्रिंग उत्पन्न करने के लिए एक तंत्र है (मैं पासवर्ड और परीक्षण डेटा उत्पन्न करने के लिए इसका उपयोग करता हूं) वर्णमाला और संख्याओं को परिभाषित किए बिना,

CleanupBase64 स्ट्रिंग में आवश्यक भागों को हटा देगा और यादृच्छिक रूप से अल्फा-न्यूमेरिक अक्षरों को जोड़कर रखेगा।

        public static string GenerateRandomString(int length)
        {
            var numArray = new byte[length];
            new RNGCryptoServiceProvider().GetBytes(numArray);
            return CleanUpBase64String(Convert.ToBase64String(numArray), length);
        }

        private static string CleanUpBase64String(string input, int maxLength)
        {
            input = input.Replace("-", "");
            input = input.Replace("=", "");
            input = input.Replace("/", "");
            input = input.Replace("+", "");
            input = input.Replace(" ", "");
            while (input.Length < maxLength)
                input = input + GenerateRandomString(maxLength);
            return input.Length <= maxLength ?
                input.ToUpper() : //In my case I want capital letters
                input.ToUpper().Substring(0, maxLength);
        }

आपने घोषणा की है GenerateRandomStringऔर GetRandomStringभीतर से एक कॉल करें SanitiseBase64String। साथ ही आपने घोषित किया है SanitiseBase64String और कॉल CleanUpBase64Stringकिया है GenerateRandomString
वाई हा ली


0

100% निश्चित नहीं है, क्योंकि मैंने यहां हर विकल्प का परीक्षण नहीं किया है, लेकिन जिन लोगों का मैंने परीक्षण किया है, यह सबसे तेज़ है। स्टॉपवॉच के साथ इसे समयबद्ध किया और इसने 9-10 टिक्स दिखाए ताकि यदि गति सुरक्षा की तुलना में अधिक महत्वपूर्ण है, तो यह प्रयास करें:

 private static Random random = new Random(); 
 public static string Random(int length)
     {   
          var stringChars = new char[length];

          for (int i = 0; i < length; i++)
              {
                  stringChars[i] = (char)random.Next(0x30, 0x7a);                  
                  return new string(stringChars);
              }
     }

उत्तर क्यों? यह सवाल बार का एक बहुत जवाब दिया गया है और अभी तक आप अभी भी अपने आधा काम कर रहे उत्तर पोस्ट ..
लौरेंत
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.