programing

임의의 영숫자 문자열을 생성하려면 어떻게 해야 합니까?

topblog 2023. 5. 13. 08:41
반응형

임의의 영숫자 문자열을 생성하려면 어떻게 해야 합니까?

C#에서 임의의 8자 영숫자 문자열을 생성하려면 어떻게 해야 합니까?

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강력한 난수 생성기가 필요한 경우 클래스.)

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강력한 난수 생성기가 필요한 경우 클래스.)

에 대해 업데이트됨.NET 6. RNGCryptoServiceProvider가 구식으로 표시됩니다.대신 난수 생성기를 호출합니다.작성().그에 따라 답변의 코드가 업데이트되었습니다.

주석을 기반으로 업데이트되었습니다.원래 구현에서는 a-h ~1.95%의 시간과 나머지 문자 ~1.56%의 시간이 생성되었습니다.업데이트는 모든 문자를 ~1.61%의 시간 동안 생성합니다.

프레임워크 지원 - .NET Core 3(및 지원하는 향후 플랫폼).NET Standard 2.1 이상)은 암호화된 방식으로 건전한 난수 생성기를 제공합니다.원하는 범위 내에서 임의 정수를 생성하려면 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 (var crypto = RandomNumberGenerator.Create())
            {
                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();
        }
    }
}

여기서 대안에 대한 논의를 바탕으로 하고 아래 의견을 바탕으로 업데이트/수정되었습니다.

여기 오래된 출력과 업데이트된 출력의 문자 분포를 보여주는 작은 테스트 하네스가 있습니다.랜덤성 분석에 대한 자세한 내용은 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")}%");
            }
        }
    }
}

2022년 7월 25일 업데이트

댓글에 올라온 질문을 토대로 분포가 정말 무작위인지 궁금했습니다.

저는 통계학자는 아니지만, 아마 TV에서 하나를 재생할 수 있을 것입니다.실제 통계학자가 참여하고 싶다면, 그것은 가장 환영할 것입니다.

과 62개의 출력값(A-Za-Z0-9)이 .int.MaxValue배열 인덱스를 선택하는 데 사용되는 숫자입니다. int.MaxValue % 621이므로 한 문자가 다른 문자보다 40억분의 1로 더 자주 선택됩니다.인덱싱 전에 출력 값 배열을 무작위로 회전하여 선택 편향을 더욱 줄일 수 있습니다.

T-test나 다른 통계적 측정은 출력 결과에 편향이 있는지 여부를 결정하는 가장 좋은 접근법이 될 것입니다. 하지만 그것은 점심시간에 제가 할 수 있는 것이 아닙니다. 그래서 대신 저는 여러분에게 예상에서 벗어나는 것을 측정하는 위 코드의 수정을 남겨둡니다.0이 되는 경향이 있습니다.

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

const int REPETITIONS = 1_000_000;
const int KEY_SIZE = 32;
int TASK_COUNT = Environment.ProcessorCount - 1;

var expectedPercentage = 100.0 / KeyGenerator.chars.Length;

var done = false;
var iterationNr = 1;
var totalRandomSymbols = 0L;

var grandTotalCounts = new Dictionary<char, long>();
foreach (var ch in KeyGenerator.chars) grandTotalCounts.Add(ch, 0);

while (!done)
{
    var experiments = Enumerable.Range(0, TASK_COUNT).Select(i => Task.Run(Experiment)).ToArray();
    Task.WaitAll(experiments);
    var totalCountsThisRun = experiments.SelectMany(e => e.Result)
        .GroupBy(e => e.Key)
        .Select(e => new { e.Key, Count = e.Select(_ => _.Value).Sum() })
        .ToDictionary(e => e.Key, e => e.Count);

    foreach (var ch in KeyGenerator.chars)
        grandTotalCounts[ch] += totalCountsThisRun[ch];

    var totalChars = grandTotalCounts.Values.Sum();
    totalRandomSymbols += totalChars;

    var distributionScores = KeyGenerator.chars.Select(ch =>
    new
    {
        Symbol = ch,
        OverUnder = (100.0 * grandTotalCounts[ch] / totalChars) - expectedPercentage

    });

    Console.WriteLine($"Iteration {iterationNr++}. Total random symbols: {totalRandomSymbols:N0}");
    foreach (var chWithValue in distributionScores.OrderByDescending(c => c.OverUnder))
    {
        Console.WriteLine($"{chWithValue.Symbol}: {chWithValue.OverUnder:#.00000}%");
    }

    done = Console.KeyAvailable;        
}

Dictionary<char, long> Experiment()
{
    var counts = new Dictionary<char, long>();
    foreach (var ch in KeyGenerator.chars) counts.Add(ch, 0);

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

    return counts;
}

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

    public static string GetUniqueKey(int size)
    {
        byte[] data = new byte[4 * size];
        using (var crypto = RandomNumberGenerator.Create())
        {
            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();
    }
}

솔루션 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에는 항상 동일하고 따라서 랜덤하지 않은 고정 비트가 몇 개 있기 때문입니다. 예를 들어, 16진수의 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 대신 16진수를 사용하기 때문에 다른 솔루션에 비해 동일한 범위를 나타내는 데 더 많은 문자가 필요합니다.

이는 충돌 가능성이 더 높다는 것을 의미합니다. 8개 문자열을 100,000번 반복하여 테스트하면 하나의 중복이 생성됩니다.

여기 도트 넷 펄의 샘 알렌의 예에서 제가 훔친 예시가 있습니다.

8자만 필요한 경우 경로를 사용합니다.시스템에서 임의 파일 이름()을 가져옵니다.IO 네임스페이스입니다.샘은 "경로"를 사용하여 말합니다.여기서 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
}

PS: 샘 감사합니다.

내 코드의 주요 목표는 다음과 같습니다.

  1. 문자열의 분포는 거의 균일합니다(작은 편차는 신경쓰지 마십시오, 작은 편차만 있으면 됩니다).
  2. 각 인수 집합에 대해 수십억 개 이상의 문자열을 출력합니다.PRNG가 20억(31비트 엔트로피)의 서로 다른 값만 생성하는 경우 8문자열(~47비트 엔트로피)을 생성하는 것은 의미가 없습니다.
  3. 사람들이 이것을 비밀번호나 다른 보안 토큰에 사용할 것으로 예상하기 때문에 안전합니다.

첫 번째 속성은 알파벳 크기에 64비트 값 모듈을 사용하여 얻을 수 있습니다.작은 알파벳(예: 질문의 62자)의 경우 이는 무시할 수 있는 편향으로 이어집니다.두 번째 및 세 번째 속성은 대신 를 사용하여 수행됩니다.

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

가장 단순한 방법:

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사례.

이 스레드의 다양한 답변에 대한 몇 가지 성능 비교:

방법 및 설정

// 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인 경우 다음을 생성합니다.

  • From Linq = chdgmevhcy [10]
  • From 루프 = gtnoaryhxr [10]
  • [10]까지 = rsndbzty 선택
  • GenerateRandomString = owyefjakj [10]에서 시작합니다.
  • SecureFastRandom = Vzoug로부터LYHYP [10]
  • SecureFast Random-NoCache = oVQXNGmO1S에서 전송 [10]

그리고 성능 수치는 약간, 아주 가끔 변화하는 경향이 있습니다.NonOptimized은 더 빠르고, 은더빠고르은가끔사실, 가은끔▁is,.ForLoop그리고.GenerateRandomString누가 선두에 서는지 전환합니다.

  • LinkqIsTheNewBlack(10000x) = 96762 눈금 경과(9.6762ms)
  • 루프(10000x) = 28970 눈금 경과(2.897ms)
  • 루프 최적화되지 않은 경우(10000x) = 33336 눈금 경과(3.3336ms)
  • 반복(10000x) = 78547 눈금 경과(7.8547ms)
  • 랜덤 문자열 생성(10000x) = 27416개의 눈금 통과(2.7416ms)
  • SecureFastRandom(10000x) = 13176개의 눈금이 최저 통과(5ms) [다른 기계]
  • SecureFastRandom-NoCache(10000x) = 39541개의 눈금이 가장 낮음(17ms) [다른 컴퓨터]

코드 한 줄이 트릭을 합니다 :)

여기 같은 것에 대한 데모가 있습니다.

에릭 J.가 작성한 암호는 상당히 엉성합니다(6년 전의 것임이 꽤 분명합니다...그는 아마 오늘 그 코드를 작성하지 않았을 것입니다.) 그리고 심지어 몇 가지 문제가 있습니다.

제시된 일부 대안과는 달리, 이 대안은 암호학적으로 타당합니다.

사실이 아닙니다...비밀번호에 편향이 있습니다(댓글에 기재된 바와 같이),bcdefgh이 조금 더 높습니다.a에 의한 것이 GetNonZeroBytes하는 것이 이 0인 바 를 생 하 는 성 아 므 대 로 편 한 향 그 값 에 니 것 이 트 이 대 편 향 ▁for ▁it 한 ▁the ▁with 그 ▁bias , ▁0 값 에 ating ▁bytes ▁isn ▁so ▁the 이 인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);
    }
}

나의 간단한 한 줄 코드는 나에게 효과가 있습니다 :)

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

또한 사용자 지정 문자열 랜덤을 사용하지만 문자열의 도우미로 구현하여 유연성을 제공합니다.

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

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

선호하는 스타일은 다를 수 있습니다.

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

또 다른 옵션은 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());

질문:시간을 낭비해야 하는 이유는 무엇이 있습니까?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;
    }
}

답변: 매직 스트링이 불량입니다.누가 알아챘나요?I위에 있는 내 끈 안에?어머니는 이런 이유로 마법의 끈을 사용하지 말라고 가르치셨어요

@같은 다른 n.b.을 사용하지 마세요: @dtb @dtb 같많은은다른사말람마이들했이세요, 듯사지하용와마세요▁n▁n:.System.Random암호 보안이 필요하다면,

n.b. 2: 이 답이 가장 효율적이거나 짧지는 않지만, 저는 공간이 답과 질문을 분리하기를 원했습니다.제 대답의 목적은 환상적이고 혁신적인 대답을 제공하기보다는 마법의 끈에 대해 경고하는 것입니다.

다른 답변을 검토하고 CodeInChaos의 코멘트를 고려한 후, CodeInChaos의 답변이 여전히 편향된(덜 떨어지긴 하지만) 답변과 함께, 최종적인 컷 앤 페이스트 솔루션이 필요하다고 생각했습니다.그래서 제 답변을 업데이트하는 동안 저는 전력을 다하기로 결정했습니다.

이 코드의 최신 버전을 보려면 비트버킷의 새로운 Hg 저장소인 https://bitbucket.org/merarischroeder/secureswiftrandom 를 방문하십시오.https://bitbucket.org/merarischroeder/secureswiftrandom/src/6c14b874f34a3f6576b0213379ecdf0ffc7496ea/Code/Alivate.SolidSwiftRandom/SolidSwiftRandom.cs?at=default&fileviewer=file-view-default 에서 코드를 복사하여 붙여넣는 것이 좋습니다. (원시 단추를 클릭하여 복사하기 쉽게 하고 최신 버전이 있는지 확인하십시오.이 링크는 최신 버전이 아닌 특정 버전의 코드로 가는 것 같습니다.

업데이트된 노트:

  1. 일부 다른 답변 관련 - 출력 길이를 알고 있으면 StringBuilder가 필요하지 않으며 ToCharArray를 사용할 때 이것이 배열을 만들고 채웁니다(먼저 빈 배열을 만들 필요가 없음).
  2. 일부 다른 답변 관련 - 성능을 위해 한 번에 하나씩 받는 것이 아니라 다음 바이트를 사용해야 합니다.
  3. 기술적으로 더 빠른 액세스를 위해 바이트 배열을 고정할 수 있습니다.일반적으로 바이트 배열을 통해 6-8회 이상 반복할 때 가치가 있습니다.(여기서 수행되지 않음)
  4. 최적의 무작위성을 위한 RNGCryptoServiceProvider 사용
  5. 랜덤 데이터로 구성된 1MB 버퍼의 캐슁 사용 - 벤치마크에 따르면 캐슁된 단일 바이트 액세스 속도가 최대 1000배 더 빠릅니다. 캐슁되지 않은 데이터의 경우 989ms에 비해 1MB보다 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. SecureFastRandom - 첫 번째 단일 실행 = ~9-33ms.감지할 수 없습니다.진행 중: 10,000회에 걸쳐 5ms(때로는 13ms까지 증가하기도 함), 단일 평균 반복 = 1.5마이크로초..참고: 일반적으로 2개가 필요하지만 때로는 최대 8개의 캐시를 새로 고칩니다. 이는 바이어스 영역을 초과하는 단일 바이트 수에 따라 달라집니다.
  2. 랜덤 - 첫 번째 단일 실행 = ~0-1ms입니다.감지할 수 없습니다.진행 중: 10,000회 이상 5ms.단일 평균 반복 = .5마이크로초..거의 같은 속도입니다.

또한 체크아웃:

이러한 링크는 또 다른 접근 방식입니다.버퍼링은 이 새로운 코드 기반에 추가될 수 있지만, 가장 중요한 것은 편향을 제거하고 속도와 장단점을 벤치마킹하는 다양한 접근 방식을 모색하는 것이었습니다.

암호화 보안(.)을 갖춘 가장 간단하고 유연한 솔루션)NET Core 3.0+:

를 사용하는 경우.NET Core 3.0 이상에서는 클래스에 대한 새로운 정적 메서드(암호적으로 안전함)를 사용하여 지정된 문자 집합에 대한 임의 인덱스를 생성하고 결과를 매우 쉽게 채울 수 있습니다.

이 방법은 예를 들어 이 답변에서 제안한 방법보다 훨씬 단순하며 원하는 문자 집합을 전달할 수 있기 때문에 완벽한 유연성을 제공합니다.

public static string GenerateRandomString(int length, IEnumerable<char> charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
{
    var charArray = charSet.Distinct().ToArray();
    char[] result = new char[length];
    for (int i = 0; i < length; i++)
        result[i] = charArray[RandomNumberGenerator.GetInt32(charArray.Length)];
    return new string(result);
}

용도:

string randomAlphanumericString = GenerateRandomString(length: 10);

간단하고 안전한 방법은 암호화 Aes 키를 생성하는 것일 수 있습니다.

public static string GenerateRandomString()
{
    using Aes crypto = Aes.Create();
    crypto.GenerateKey();
    return Convert.ToBase64String(crypto.Key);
}

저는 좀 더 구체적인 답을 찾고 있었는데, 랜덤 문자열의 형식을 제어하고 싶었기 때문에 이 게시물을 보게 되었습니다.예를 들어, (자동차의) 번호판은 특정 형식(국가별)을 가지고 있으며, 저는 무작위로 번호판을 만들고 싶었습니다.
저는 이를 위해 Random의 확장 방법을 직접 작성하기로 했습니다.(멀티스레딩 시나리오에서 이중으로 사용할 수 있는 것처럼 동일한 랜덤 개체를 재사용하기 위한 것입니다.)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)];
    }
}

이제 원라이너 맛으로.

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

고유 부품(시퀀스, 카운터 또는 날짜)과 랜덤 부품 두 개를 결합합니다.

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;

        using (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)
    {
        const string chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //if you wish to make the 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())
    }

암호화 및 비암호화 모두에서 효율적으로:

public static string GenerateRandomString(int length, string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") =>
    new Random().GenerateRandomString(length, charset);

public static string GenerateRandomString(this Random random, int length, string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") =>
    RandomString(random.NextBytes, length, charset.ToCharArray());

public static string GenerateRandomCryptoString(int length, string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
{
    using (var crypto = new System.Security.Cryptography.RNGCryptoServiceProvider())
        return crypto.GenerateRandomCryptoString(length, charset);
}

public static string GenerateRandomCryptoString(this RNGCryptoServiceProvider random, int length, string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") => 
    RandomString(random.GetBytes, length, charset.ToCharArray());

private static string RandomString(Action<byte[]> fillRandomBuffer, int length, char[] charset)
{
    if (length < 0)
        throw new ArgumentOutOfRangeException(nameof(length), $"{nameof(length)} must be greater or equal to 0");
    if (charset is null)
        throw new ArgumentNullException(nameof(charset));
    if (charset.Length == 0)
        throw new ArgumentException($"{nameof(charset)} must contain at least 1 character", nameof(charset));

    var maxIdx = charset.Length;
    var chars = new char[length];
    var randomBuffer = new byte[length * 4];
    fillRandomBuffer(randomBuffer);

    for (var i = 0; i < length; i++)
        chars[i] = charset[BitConverter.ToUInt32(randomBuffer, i * 4) % maxIdx];

    return new string(chars);
}

제너레이터 및 LINQ를 사용합니다.가장 빠른 옵션은 아니지만(특히 한 번에 모든 바이트를 생성하지 않기 때문에) 깔끔하고 확장 가능합니다.

private static readonly Random _random = new Random();

public static string GenerateRandomString(int length, string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") =>
    new string(_random.GetGenerator().RandomChars(charset.ToCharArray()).Take(length).ToArray());

public static string GenerateRandomCryptoString(int length, string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
{
    using (var crypto = new System.Security.Cryptography.RNGCryptoServiceProvider())
        return new string(crypto.GetGenerator().RandomChars(charset.ToCharArray()).Take(length).ToArray());
}

public static IEnumerable<char> RandomChars(this Func<uint, IEnumerable<uint>> randomGenerator, char[] charset)
{
    if (charset is null)
        throw new ArgumentNullException(nameof(charset));
    if (charset.Length == 0)
        throw new ArgumentException($"{nameof(charset)} must contain at least 1 character", nameof(charset));

    return randomGenerator((uint)charset.Length).Select(r => charset[r]);
}

public static Func<uint, IEnumerable<uint>> GetGenerator(this Random random)
{
    if (random is null)
        throw new ArgumentNullException(nameof(random));

    return GeneratorFunc_Inner;

    IEnumerable<uint> GeneratorFunc_Inner(uint maxValue)
    {
        if (maxValue > int.MaxValue)
            throw new ArgumentOutOfRangeException(nameof(maxValue));

        return Generator_Inner();

        IEnumerable<uint> Generator_Inner()
        {
            var randomBytes = new byte[4];
            while (true)
            {
                random.NextBytes(randomBytes);
                yield return BitConverter.ToUInt32(randomBytes, 0) % maxValue;
            }
        }
    }
}

public static Func<uint, IEnumerable<uint>> GetGenerator(this System.Security.Cryptography.RNGCryptoServiceProvider random)
{
    if (random is null)
        throw new ArgumentNullException(nameof(random));

    return Generator_Inner;

    IEnumerable<uint> Generator_Inner(uint maxValue)
    {
        var randomBytes = new byte[4];
        while (true)
        {
            random.GetBytes(randomBytes);
            yield return BitConverter.ToUInt32(randomBytes, 0) % maxValue;
        }
    }
}

비암호화 문자열에 대해서만 LINQ를 사용하는 간단한 버전:

private static readonly Random _random = new Random();

public static string RandomString(int length, string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") =>
    new string(_random.GenerateChars(charset).Take(length).ToArray()); 

public static IEnumerable<char> GenerateChars(this Random random, string charset)
{
    if (charset is null) throw new ArgumentNullException(nameof(charset));
    if (charset.Length == 0) throw new ArgumentException($"{nameof(charset)} must contain at least 1 character", nameof(charset));

    return random.Generator(charset.Length).Select(r => charset[r]);
}

public static IEnumerable<int> Generator(this Random random, int maxValue)
{
    if (random is null) throw new ArgumentNullException(nameof(random));

    return Generator_Inner();

    IEnumerable<int> Generator_Inner() { while (true) yield return random.Next(maxValue); }
}

끔찍해요, 알아요 하지만 어쩔 수 없었어요


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

원하는 대로 변경할 수 있는 모든 알파벳 문자와 숫자가 포함된 솔루션:

public static string RandomString(int length)
{
    Random rand = new Random();
    string charbase = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    return new string(Enumerable.Range(0,length)
           .Select(_ => charbase[rand.Next(charbase.Length)])
           .ToArray());
}

한 줄 방법을 좋아한다면 ;)

public static Random rand = new Random();
public const string charbase = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
 

public static string RandomString(int length) =>
        new string(Enumerable.Range(0,length).Select(_ => charbase[rand.Next(charbase.Length)]).ToArray());

를 사용하지 않은 Random:

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

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

다음은 WinRT(Windows Store App)용 Eric J의 다양한 솔루션, 즉 암호화된 사운드입니다.

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

이것이 최선의 방법이 아니라는 것을 압니다.하지만 당신은 이것을 시도할 수 있습니다.

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

더 보다 더 ▁be▁"▁i▁thanr▁▁more▁by▁it▁and▁ando▁should▁concise▁thisim▁readable▁is▁but▁thesically,이▁crypt▁sound'ograph▁solutionso것▁it)합다니▁more▁more보야),▁("▁intricate더▁far▁don▁how덤t▁",이▁know'다보음다훨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());

물론 속도에 최적화되지 않았으므로 초당 수백만 개의 무작위 문자열을 생성하는 것이 미션 크리티컬한 경우 다른 문자열을 사용해 보십시오!

참고: 이 솔루션은 알파벳 기호의 반복을 허용하지 않으며, 알파벳은 출력 문자열과 같거나 큰 크기여야 하므로 일부 상황에서는 이 방법이 바람직하지 않으므로 사용 사례에 따라 달라집니다.

값이 완전히 무작위적이지는 않지만 실제로 어떤 것에 의존할 수 있는 경우에는 해당 'Something'의 md5 또는 sha1 해시를 계산한 다음 원하는 길이로 자를 수 있습니다.

또한 GUID를 생성하고 자를 수 있습니다.

언급URL : https://stackoverflow.com/questions/1344221/how-can-i-generate-random-alphanumeric-strings

반응형