अद्वितीय यादृच्छिक स्ट्रिंग पीढ़ी


98

मैं उदाहरण के लिए, MSDN लाइब्रेरी द्वारा उत्पन्न किए जा रहे रैंडम यूनिक स्ट्रिंग्स उत्पन्न करना चाहूंगा। ( त्रुटि ऑब्जेक्ट ), उदाहरण के लिए। 'T9zk6eay' जैसा एक स्ट्रिंग उत्पन्न किया जाना चाहिए।


1
इस कोशिश string randoms = Guid.NewGuid().ToString().Replace("-", string.Empty).Replace("+", string.Empty).Substring(0, 4);अधिक पाया जा सकता है यहां
shaijut

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

जवाबों:


85

गाइड का उपयोग करना एक बहुत अच्छा तरीका होगा, लेकिन अपने उदाहरण की तरह कुछ पाने के लिए, आप शायद इसे बेस 64 स्ट्रिंग में बदलना चाहते हैं:

    Guid g = Guid.NewGuid();
    string GuidString = Convert.ToBase64String(g.ToByteArray());
    GuidString = GuidString.Replace("=","");
    GuidString = GuidString.Replace("+","");

मैं "=" और "+" से छुटकारा पाने के लिए अपने उदाहरण के थोड़ा करीब पहुंच गया हूं, अन्यथा आपको अपनी स्ट्रिंग के अंत में "==" और बीच में एक "+" मिलता है। यहाँ एक उदाहरण आउटपुट स्ट्रिंग है:

"OZVV5TpP4U6wJthaCORZEQ"


15
आपको बदलने / भी विचार करना चाहिए।
जेसन केली

20
एक गाइड को एक सुरक्षित यादृच्छिक स्ट्रिंग के रूप में नहीं माना जाना चाहिए क्योंकि अनुक्रम का अनुमान लगाया जा सकता है। एक गाइड को यादृच्छिक होने के बजाय प्रमुख संघर्षों से बचने के लिए डिज़ाइन किया गया है। स्टैक ओवरफ्लो पर चारों ओर एक गाइड की यादृच्छिकता की कुछ अच्छी चर्चाएं हैं
डैनियल ब्रैडले

क्या Convert.ToBase64Stringहै, इसके बारे में स्पष्ट और संक्षिप्त विवरण के लिए , यहां देखें
ज्वालिस्ज़को

2
बेस 64 में गाइड को परिवर्तित कर सकते हैं और + और = को टक्कर की संभावना बढ़ा सकते हैं?
मिलन अग्रवाल

5
@SimonEjsing मैं आपको एक बीयर के लिए आमंत्रित करूंगा यदि आप वास्तव में new Guid()"हैकिंग" (घड़ी या आंतरिक विंडोज डेटा संरचनाओं के साथ छेड़छाड़) का उपयोग किए बिना टकराव होने पर एक एप्लिकेशन लिख सकते हैं । आप की तरह के रूप में कई कोर, धागे, तुल्यकालन आदिम उपयोग करने के लिए स्वतंत्र महसूस करें।
लुसिरो

175

अपडेट २०१६/१/२३

यदि आपको यह उत्तर उपयोगी लगता है, तो आप एक साधारण (~ 500 SLOC) पासवर्ड जनरेशन लाइब्रेरी में रुचि रख सकते हैं, जिसे मैंने प्रकाशित किया है :

Install-Package MlkPwgen

फिर आप नीचे दिए गए उत्तर की तरह यादृच्छिक तार उत्पन्न कर सकते हैं:

var str = PasswordGenerator.Generate(length: 10, allowed: Sets.Alphanumerics);

लाइब्रेरी का एक फायदा यह है कि कोड बेहतर ढंग से तैयार किया जाता है ताकि आप स्ट्रिंग्स उत्पन्न करने से अधिक के लिए सुरक्षित यादृच्छिकता का उपयोग कर सकें । की जाँच करें परियोजना स्थल अधिक जानकारी के लिए।

मूल उत्तर

चूंकि किसी ने अभी तक सुरक्षित कोड प्रदान नहीं किया है, इसलिए मैं निम्नलिखित पोस्ट करता हूं कि कोई भी इसे उपयोगी पाता है।

string RandomString(int length, string allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") {
    if (length < 0) throw new ArgumentOutOfRangeException("length", "length cannot be less than zero.");
    if (string.IsNullOrEmpty(allowedChars)) throw new ArgumentException("allowedChars may not be empty.");

    const int byteSize = 0x100;
    var allowedCharSet = new HashSet<char>(allowedChars).ToArray();
    if (byteSize < allowedCharSet.Length) throw new ArgumentException(String.Format("allowedChars may contain no more than {0} characters.", byteSize));

    // Guid.NewGuid and System.Random are not particularly random. By using a
    // cryptographically-secure random number generator, the caller is always
    // protected, regardless of use.
    using (var rng = System.Security.Cryptography.RandomNumberGenerator.Create()) {
        var result = new StringBuilder();
        var buf = new byte[128];
        while (result.Length < length) {
            rng.GetBytes(buf);
            for (var i = 0; i < buf.Length && result.Length < length; ++i) {
                // Divide the byte into allowedCharSet-sized groups. If the
                // random value falls into the last group and the last group is
                // too small to choose from the entire allowedCharSet, ignore
                // the value in order to avoid biasing the result.
                var outOfRangeStart = byteSize - (byteSize % allowedCharSet.Length);
                if (outOfRangeStart <= buf[i]) continue;
                result.Append(allowedCharSet[buf[i] % allowedCharSet.Length]);
            }
        }
        return result.ToString();
    }
}

.NET कोर पर काम करने वाले कोड को प्राप्त करने के लिए अहमद को धन्यवाद।


@Keltex समाधान meh के लिए सही काम नहीं कर रहा था (यह कुछ उपयोगों के बाद उसी स्ट्रिंग को वापस कर रहा था)। यह समाधान एकदम सही काम करता है :)
JoanComasFdz

2
@LeeGrissom, पक्षपात एक महत्वपूर्ण पहलू है। उदाहरण के लिए कहते हैं कि आपके वर्णमाला में 255 वर्ण हैं और आपको 0-255 के बीच एक यादृच्छिक मान मिलता है। एक रिंग बफ़र में मान 0 और 255 दोनों समान वर्ण के अनुरूप होंगे जो वर्णमाला में पहले वर्ण के पक्ष में परिणाम को तिरछा करेगा, यह कम यादृच्छिक होगा। यदि यह मामला पाठ्यक्रम के आवेदन पर निर्भर करता है।
Oskar Sjöberg

4
कौन लक्ष्य बनाता .netcore: बदलें var rng = new RNGCryptoServiceProvider()साथvar rng = RandomNumberGenerator.Create()
AMD

1
आप 'var outOfRangeStart = byteSize - (byteSize% allowCharSet.Length) की गणना क्यों करते हैं;' प्रत्येक पुनरावृत्ति के लिए? आप 'उपयोग' करने से पहले इसकी गणना कर सकते हैं।
mtkachenko

1
@BartCalixto फिक्स्ड। धन्यवाद!
माइकल क्रोपत

38

मैं चेतावनी दूंगा कि GUIDs यादृच्छिक संख्या नहीं हैं । उन्हें किसी भी चीज़ को उत्पन्न करने के लिए आधार के रूप में उपयोग नहीं किया जाना चाहिए, जिसे आप पूरी तरह से यादृच्छिक होने की उम्मीद करते हैं (देखें http://en.wikipedia.org/wiki/Glo Worldwide_Unique_Identifier ):

WinAPI GUID जनरेटर के क्रिप्टानालिसिस से पता चलता है कि, चूंकि V4 GUIDs का अनुक्रम छद्म-यादृच्छिक है, इसे देखते हुए प्रारंभिक अवस्था में अगले 250 000 GUIDs जो कि UuidCreate फ़ंक्शन द्वारा वापस आ सकते हैं, की भविष्यवाणी कर सकते हैं। यही कारण है कि GUIDs का उपयोग क्रिप्टोग्राफी में नहीं किया जाना चाहिए, उदाहरण के लिए, यादृच्छिक कुंजियों के रूप में।

इसके बजाय, बस C # रैंडम विधि का उपयोग करें। कुछ इस तरह ( कोड यहां पाया गया ):

private string RandomString(int size)
{
  StringBuilder builder = new StringBuilder();
  Random random = new Random();
  char ch ;
  for(int i=0; i<size; i++)
  {
    ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))) ;
    builder.Append(ch);
  }
  return builder.ToString();
}

यदि आप कुछ अनोखा चाहते हैं (जैसे डेटाबेस में एक अद्वितीय फ़ाइल नाम या कुंजी), तो GUIDs ठीक हैं , लेकिन वे उन चीज़ों के लिए अच्छे नहीं हैं जिन्हें आप यादृच्छिक बनाना चाहते हैं (जैसे पासवर्ड या एन्क्रिप्शन कुंजी)। तो यह आपके आवेदन पर निर्भर करता है।

संपादित करें । Microsoft का कहना है कि रैंडम या तो महान नहीं है ( http://msdn.microsoft.com/en-us/library/system.random.VS.71).aspx ):

एक यादृच्छिक पासवर्ड बनाने के लिए उपयुक्त एक क्रिप्टोग्राफिक रूप से सुरक्षित यादृच्छिक संख्या उत्पन्न करने के लिए, उदाहरण के लिए, System.Security.Cryptography.RandomNumberGenerator जैसे System.Security.Cryptography.RNGCryptoShaProvider से प्राप्त एक वर्ग का उपयोग करें।


5
C # यादृच्छिक वर्ग या तो किसी भी क्रिप्टो कोड के लिए "यादृच्छिक" नहीं है और अनुपयुक्त है, क्योंकि यह एक विशिष्ट बीज संख्या से शुरू होने वाला एक क्लासिक यादृच्छिक जनरेटर है। समान बीज भी लौट आए संख्याओं का एक ही क्रम लौटाएगा; GUID दृष्टिकोण पहले से ही यहाँ बहुत बेहतर है ("यादृच्छिक" नहीं बल्कि "अद्वितीय")।
लुकेरो

3
@ ल्यूकोरो: आप सही हैं। Microsoft अनुशंसा करता है, "एक यादृच्छिक पासवर्ड बनाने के लिए उपयुक्त एक क्रिप्टोग्राफिक रूप से सुरक्षित रैंडम संख्या उत्पन्न करने के लिए, उदाहरण के लिए, System.Security.Cryptography.RandomNumberGenerator जैसे System.Security.Cryptography.Cryptography.RGCryptoServiceProvider से प्राप्त वर्ग का उपयोग करें।"
केलटेक्स

खैर, सवाल पहले ही कहा गया था कि वह (छद्म) यादृच्छिक अद्वितीय तार चाहता है, इसलिए कोई क्रिप्टो आवश्यकताओं या यहां तक ​​कि एक विशिष्ट यादृच्छिक वितरण का पालन करने की आवश्यकता नहीं है। तो GUID शायद सबसे आसान तरीका है।
जॉय

1
यह कथन कि "प्रारंभिक अवस्था को देखते हुए अगले 250 000 GUID तक की भविष्यवाणी की जा सकती है" किसी भी PRNG के लिए स्वाभाविक रूप से सही कथन की तरह लगता है ... मुझे यकीन है कि यह भी सुरक्षित नहीं है, लेकिन मुझे यकीन है कि उत्पन्न करने में बहुत मूल्य नहीं है वास्तव में यादृच्छिक यूआरएल, अगर यही ओपी के लिए जा रहा है। ;)
14

1
(वैसे भी - PRNG शिक्षा महत्वपूर्ण है।)
ojrac

13

मैंने @Michael Kropats समाधान को सरल बनाया और एक LINQ-esque संस्करण बनाया।

string RandomString(int length, string alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
{       
    var outOfRange = byte.MaxValue + 1 - (byte.MaxValue + 1) % alphabet.Length;

    return string.Concat(
        Enumerable
            .Repeat(0, int.MaxValue)
            .Select(e => RandomByte())
            .Where(randomByte => randomByte < outOfRange)
            .Take(length)
            .Select(randomByte => alphabet[randomByte % alphabet.Length])
    );
}

byte RandomByte()
{
    using (var randomizationProvider = new RNGCryptoServiceProvider())
    {
        var randomBytes = new byte[1];
        randomizationProvider.GetBytes(randomBytes);
        return randomBytes.Single();
    }   
}

11

मुझे नहीं लगता कि वे वास्तव में यादृच्छिक हैं, लेकिन मेरा अनुमान है कि वे कुछ हैश हैं।

जब भी मुझे कुछ यादृच्छिक पहचानकर्ता की आवश्यकता होती है, मैं आमतौर पर एक GUID का उपयोग करता हूं और इसे अपने "नग्न" प्रतिनिधित्व में परिवर्तित करता हूं:

Guid.NewGuid().ToString("n");

जैसा कि @Keltex ने बताया: WinAPI GUID जनरेटर का क्रिप्टैनालिसिस दर्शाता है कि, चूंकि V4 GUIDs का अनुक्रम छद्म-यादृच्छिक है, जिसे देखते हुए प्रारंभिक अवस्था अगले UUidCreate द्वारा दिए गए अगले 250 000 GUIDs की भविष्यवाणी कर सकती है।
JoanComasFdz

4

गाइड और Time.Ticks के बीच संयोजन का प्रयास करें

 var randomNumber = Convert.ToBase64String(Guid.NewGuid().ToByteArray()) + DateTime.Now.Ticks;
     randomNumber = System.Text.RegularExpressions.Regex.Replace(randomNumber, "[^0-9a-zA-Z]+", "");

3

मुझे आश्चर्य है कि क्रायटपोग्राफिक सॉल्यूशन क्यों नहीं है। GUID अद्वितीय है लेकिन क्रिप्टोग्राफिक रूप से सुरक्षित नहीं हैइस डॉटनेट फिडेल को देखें।

var bytes = new byte[40]; // byte size
using (var crypto = new RNGCryptoServiceProvider())
  crypto.GetBytes(bytes);

var base64 = Convert.ToBase64String(bytes);
Console.WriteLine(base64);

मामले में आप एक गाइड के साथ प्रस्तुत करना चाहते हैं:

var result = Guid.NewGuid().ToString("N") + base64;
Console.WriteLine(result);

एक क्लीनर अल्फ़ान्यूमेरिक स्ट्रिंग:

result = Regex.Replace(result,"[^A-Za-z0-9]","");
Console.WriteLine(result);

1

VB.net में माइकल क्रॉपेट्स समाधान

Private Function RandomString(ByVal length As Integer, Optional ByVal allowedChars As String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") As String
    If length < 0 Then Throw New ArgumentOutOfRangeException("length", "length cannot be less than zero.")
    If String.IsNullOrEmpty(allowedChars) Then Throw New ArgumentException("allowedChars may not be empty.")


    Dim byteSize As Integer = 256
    Dim hash As HashSet(Of Char) = New HashSet(Of Char)(allowedChars)
    'Dim hash As HashSet(Of String) = New HashSet(Of String)(allowedChars)
    Dim allowedCharSet() = hash.ToArray

    If byteSize < allowedCharSet.Length Then Throw New ArgumentException(String.Format("allowedChars may contain no more than {0} characters.", byteSize))


    ' Guid.NewGuid and System.Random are not particularly random. By using a
    ' cryptographically-secure random number generator, the caller is always
    ' protected, regardless of use.
    Dim rng = New System.Security.Cryptography.RNGCryptoServiceProvider()
    Dim result = New System.Text.StringBuilder()
    Dim buf = New Byte(128) {}
    While result.Length < length
        rng.GetBytes(buf)
        Dim i
        For i = 0 To buf.Length - 1 Step +1
            If result.Length >= length Then Exit For
            ' Divide the byte into allowedCharSet-sized groups. If the
            ' random value falls into the last group and the last group is
            ' too small to choose from the entire allowedCharSet, ignore
            ' the value in order to avoid biasing the result.
            Dim outOfRangeStart = byteSize - (byteSize Mod allowedCharSet.Length)
            If outOfRangeStart <= buf(i) Then
                Continue For
            End If
            result.Append(allowedCharSet(buf(i) Mod allowedCharSet.Length))
        Next
    End While
    Return result.ToString()
End Function

1

यह मेरे लिए एकदम सही काम करता है

    private string GeneratePasswordResetToken()
    {
        string token = Guid.NewGuid().ToString();
        var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(token);
        return Convert.ToBase64String(plainTextBytes);
    }

0

यह विभिन्न भाषाओं के लिए कहा गया है। यहां पासवर्ड के बारे में एक प्रश्न है जो यहां भी लागू होना चाहिए।

यदि आप URL को छोटा करने के लिए स्ट्रिंग्स का उपयोग करना चाहते हैं, तो आपको यह देखने के लिए एक शब्दकोश <या डेटाबेस चेक की भी आवश्यकता होगी कि क्या पहले से ही एक जनरेटेड आईडी का उपयोग किया गया है।


0

यदि आप लोअरकेस और अपरकेस अक्षर ([a-zA-Z0-9]) के साथ एक अल्फ़ान्यूमेरिक स्ट्रिंग्स चाहते हैं , तो आप तेज और सरल समाधान के लिए Convert.ToBase64String () का उपयोग कर सकते हैं।

विशिष्टता के लिए, जन्मदिन की समस्या की जांच करें कि गणना करने के लिए कैसे गणना की जाती है (ए) उत्पन्न स्ट्रिंग्स की लंबाई और (बी) उत्पन्न स्ट्रिंग्स की संख्या।

Random random = new Random();

int outputLength = 10;
int byteLength = (int)Math.Ceiling(3f / 4f * outputLength); // Base64 uses 4 characters for every 3 bytes of data; so in random bytes we need only 3/4 of the desired length
byte[] randomBytes = new byte[byteLength];
string output;
do
{
    random.NextBytes(randomBytes); // Fill bytes with random data
    output = Convert.ToBase64String(randomBytes); // Convert to base64
    output = output.Substring(0, outputLength); // Truncate any superfluous characters and/or padding
} while (output.Contains('/') || output.Contains('+')); // Repeat if we contain non-alphanumeric characters (~25% chance if length=10; ~50% chance if length=20; ~35% chance if length=32)

-1
  • सुनिश्चित नहीं है कि Microsoft का लिंक बेतरतीब ढंग से उत्पन्न हुआ है
  • नए गाइड पर नज़र डालें ()। ToString ()

4
आपका मतलब है गाइड। न्यूग्विड ()। ToString ()
गाइड के

3
आप संभावित रूप से सही हैं, w / o verfiying टाइप कर रहा था। मुझे यकीन है कि मूल पोस्टर में बात है।
फेबियन विलर्स

-1

GUID हैश कोड का उपयोग करके अद्वितीय कुंजी प्राप्त करें

public static string GetUniqueKey(int length)
{
    string guidResult = string.Empty;

    while (guidResult.Length < length)
    {
        // Get the GUID.
        guidResult += Guid.NewGuid().ToString().GetHashCode().ToString("x");
    }

    // Make sure length is valid.
    if (length <= 0 || length > guidResult.Length)
        throw new ArgumentException("Length must be between 1 and " + guidResult.Length);

    // Return the first length bytes.
    return guidResult.Substring(0, length);
}

यह पूरी तरह से काम करता है लेकिन यादृच्छिक शब्दों में अद्वितीय वर्ण नहीं होते हैं। अक्षर दोहरा रहे हैं, जैसे 114e3 (दो 1), eaeaea (तीन ए और दो ई), 60207 (दो 0 के) और इसी तरह। अल्फ़ान्यूमेरिक संयोजन वाले वर्णों की पुनरावृत्ति के साथ रैंडम स्ट्रिंग कैसे उत्पन्न करें?
विजय

@vijay: चूंकि यह हेक्स अंकों का उत्पादन कर रहा है, आप अपने आप को 16 वर्णों तक सीमित कर रहे हैं, और 16! संभव आउटपुट। रैंडम स्ट्रिंग्स बस यही हैं, रैंडम। आप सैद्धांतिक रूप से सभी (aaaaaaaaaaaaaaaa) की एक स्ट्रिंग प्राप्त कर सकते हैं। यह बहुत ही असंभव है, लेकिन किसी भी अन्य यादृच्छिक स्ट्रिंग की तुलना में अधिक नहीं। मुझे यकीन नहीं है कि आपको उस बाधा की आवश्यकता क्यों होगी, लेकिन जैसा कि आप वर्णों को जोड़ रहे हैं, उन्हें एक HashSet <T> में पॉप करें, उनके अस्तित्व की जांच करें, और उन्हें स्ट्रिंग में जोड़ें या तदनुसार उन्हें छोड़ दें।
क्रिस डोगेट 20
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.