独特的随机string生成
我想生成随机的唯一string,如MSDN库生成的string:
例如http://msdn.microsoft.com/en-us/library/t9zk6eay.aspx 。 应该生成一个像“t9zk6eay”的string。
使用Guid将是一个非常好的方法,但是为了得到类似于你的例子的东西,你可能想把它转换成一个Base64string:
Guid g = Guid.NewGuid(); string GuidString = Convert.ToBase64String(g.ToByteArray()); GuidString = GuidString.Replace("=",""); GuidString = GuidString.Replace("+","");
我摆脱了“=”和“+”,以接近你的例子,否则你会得到“==”在你的string的末尾和“+”在中间。 以下是一个输出string示例:
“OZVV5TpP4U6wJthaCORZEQ”
更新2016/1/23
如果你觉得这个答案有用,你可能会对我发布的一个简单的(〜500 SLOC)密码生成库感兴趣:
Install-Package MlkPwgen
然后你可以像下面的答案一样生成随机string:
var str = PasswordGenerator.Generate(length: 10, allowed: Sets.Alphanumerics);
该库的一个优点是代码更好的分解,所以你可以使用安全的随机性不仅仅是生成string 。 查看项目网站了解更多详情。
原始答复
由于没有人提供了安全的代码,我张贴以下情况,以防有人发现它有用。
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 = new 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指出如何让代码在.NET Core上工作。
我会提醒说,GUID 不是随机数字 。 他们不应该被用作产生任何你期望是完全随机的基础(见http://en.wikipedia.org/wiki/Globally_Unique_Identifier ):
WinAPI GUID生成器的密码分析表明,由于V4 GUID的序列是伪随机的,给定初始状态,可以预测由函数UuidCreate返回的最多250 000个GUID。 这就是为什么GUID不应该用于密码学,例如,作为随机密钥。
相反,只需使用C#Random方法即可。 像这样的东西( 代码在这里find ):
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(); }
如果你想要一些独特的东西(比如数据库中唯一的文件名或者关键字),那么GUID就可以,但是对于你想要随机的东西(比如密码或者encryption密钥)来说,它们并不好。 所以这取决于你的应用程序。
编辑 。 微软表示Random也不是那么好( http://msdn.microsoft.com/en-us/library/system.random(VS.71).aspx ):
要生成适合创build随机密码的encryption安全随机数,例如,请使用System.Security.Cryptography.RandomNumberGenerator(如System.Security.Cryptography.RNGCryptoServiceProvider)派生的类。
我不认为他们真的是随机的,但我的猜测是这些哈希。
每当我需要一些随机的标识符,我通常使用一个GUID并将其转换为它的“裸体”表示:
Guid.NewGuid().ToString("n");
我简化了@Michael Kropats解决scheme,并制作了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(); } }
试试Guid和Time.Ticks的组合
var randomNumber = Convert.ToBase64String(Guid.NewGuid().ToByteArray()) + DateTime.Now.Ticks; randomNumber = System.Text.RegularExpressions.Regex.Replace(randomNumber, "[^0-9a-zA-Z]+", "");
迈克尔Kropats解决scheme在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
- 不确定微软的链接是随机生成的
- 看看新的Guid()。ToString()
这已被要求各种语言。 这里有一个关于密码的问题 ,这里也应该适用。
如果要使用string进行URL缩短,则还需要使用Dictionary <>或数据库检查以查看是否已使用生成的ID。
如果您想使用小写字母和大写字母的字母数字string([a-zA-Z0-9]),则可以使用Convert.ToBase64String()作为快速而简单的解决scheme。
至于唯一性,检查出生问题 ,计算碰撞的可能性有多大(A)产生的string的长度和(B)产生的string的数量。
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)
使用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); }