代码之家  ›  专栏  ›  技术社区  ›  Kirtan

唯一随机字符串生成

  •  86
  • Kirtan  · 技术社区  · 15 年前

    我想生成随机的唯一字符串,就像MSDN库生成的字符串一样( Error Object

    13 回复  |  直到 5 年前
        1
  •  177
  •   Michael Kropat    6 年前

    更新日期2016/1/23

    a simple (~500 SLOC) password generation library I published :

    Install-Package MlkPwgen
    

    然后您可以生成随机字符串,如下所示:

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

    该库的一个优点是代码被更好地分解,因此您可以使用安全的随机性 for more than generating strings . 退房 the project site

    由于还没有人提供安全代码,我将发布以下内容,以防有人发现它有用。

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

    感谢Ahmad指出了如何让代码在.NETCore上运行。

        2
  •  92
  •   Mark Synowiec    15 年前

    使用Guid是一种很好的方法,但要获得类似于示例的内容,您可能需要将其转换为Base64字符串:

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

    我把“=”和“+”去掉,让你更接近你的例子,否则你在字符串末尾得到“==”,中间加上“+”。下面是一个示例输出字符串:

    “OZVV5TpP4U6wJthaCORZEQ”

        3
  •  38
  •   Community Reversed Engineer    4 年前

    不是随机数 . 它们不应该被用作生成任何你认为是完全随机的东西的基础(参见 http://en.wikipedia.org/wiki/Globally_Unique_Identifier ):

    WinAPI GUID生成器的密码分析表明,由于V4 GUID序列是伪随机的,因此给定初始状态,可以预测UuidCreate函数返回的多达25万个GUID。这就是为什么不应该在密码学中使用guid,例如。g、 ,作为随机键。

    相反,只需使用C#Random方法。像这样的( code found here ):

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

    唯一的 (就像数据库中的唯一文件名或密钥),但它们并不适合您想要的东西 (如密码或加密密钥)。因此,这取决于您的应用程序。

    编辑 . 微软表示,Random也没那么好( http://msdn.microsoft.com/en-us/library/system.random(VS.71).aspx ):

    例如,要生成适合创建随机密码的加密安全随机数,请使用从System.Security.Cryptography.RandomNumberGenerator派生的类,例如System.Security.Cryptography.RNGCryptoServiceProvider。

        4
  •  13
  •   Oskar Sjöberg    8 年前

    我简化了@Michael Kropats解决方案,并制作了一个LINQ风格的版本。

    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();
        }   
    }
    
        5
  •  12
  •   Lucero    15 年前

    我不认为它们真的是随机的,但我猜它们是一些散列。

    每当我需要一些随机标识符时,我通常使用GUID并将其转换为“裸”表示:

    Guid.NewGuid().ToString("n");
    
        6
  •  4
  •   ASalameh    8 年前

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

    我很惊讶为什么没有一个水晶照相解决方案。 GUID是唯一的,但不是加密安全的 . See this Dotnet Fiddle.

    var bytes = new byte[40]; // byte size
    using (var crypto = new RNGCryptoServiceProvider())
      crypto.GetBytes(bytes);
    
    var base64 = Convert.ToBase64String(bytes);
    Console.WriteLine(base64);
    

    如果要在前面加上Guid:

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

    更清晰的字母数字字符串:

    result = Regex.Replace(result,"[^A-Za-z0-9]","");
    Console.WriteLine(result);
    
        8
  •  2
  •   MarlinG    6 年前

    这对我来说非常合适

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

    Michael Kropats在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
    
        10
  •  0
  •   Community Reversed Engineer    7 年前

    这是对各种语言的要求。这是 one question about passwords 这在这里也应该适用。

    如果要使用字符串来缩短URL,还需要一本字典<&燃气轮机;或数据库检查以查看生成的ID是否已被使用。

        11
  •  0
  •   Timo    9 年前

    如果需要小写字母数字字符串

    至于独特性,请查看 birthday problem 计算碰撞发生的可能性(a)生成字符串的长度和(B)生成字符串的数量。

    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)
    
        12
  •  -1
  •   Fabian Vilers    15 年前
    • 不确定微软的链接是随机生成的
    • 查看新的Guid().ToString()
        13
  •  -1
  •   Chris Doggett    15 年前

    Get Unique Key using GUID Hash code

    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);
    }
    
        14
  •  -2
  •   att    4 年前

    从中安装铲斗 scoop.sh

    scoop install openssl
    openssl rand -base64 32
    Dca3c3pptVkcb8fx243wN/3f/rQxx/rWYL8y7rZrGrA=