Tôi muốn tạo các chuỗi duy nhất ngẫu nhiên giống như các chuỗi được tạo bởi thư viện MSDN. ( Đối tượng Lỗi ) chẳng hạn. Một chuỗi như 't9zk6eay' sẽ được tạo.
Tôi muốn tạo các chuỗi duy nhất ngẫu nhiên giống như các chuỗi được tạo bởi thư viện MSDN. ( Đối tượng Lỗi ) chẳng hạn. Một chuỗi như 't9zk6eay' sẽ được tạo.
Câu trả lời:
Sử dụng Guid sẽ là một cách khá hay, nhưng để có được thứ gì đó giống như ví dụ của bạn, bạn có thể muốn chuyển nó thành chuỗi Base64:
Guid g = Guid.NewGuid();
string GuidString = Convert.ToBase64String(g.ToByteArray());
GuidString = GuidString.Replace("=","");
GuidString = GuidString.Replace("+","");
Tôi loại bỏ "=" và "+" để đến gần hơn một chút với ví dụ của bạn, nếu không, bạn nhận được "==" ở cuối chuỗi và dấu "+" ở giữa. Đây là một chuỗi đầu ra ví dụ:
"OZVV5TpP4U6wJthaCORZEQ"
Convert.ToBase64String
, hãy xem ở đây .
new Guid()
mà không bị "hack" (giả mạo đồng hồ hoặc cấu trúc dữ liệu nội bộ của Windows). Hãy thoải mái sử dụng bao nhiêu lõi, luồng, nguyên thủy đồng bộ hóa, v.v. tùy thích.
Cập nhật 2016/1/23
Nếu bạn thấy câu trả lời này hữu ích, bạn có thể quan tâm đến thư viện tạo mật khẩu đơn giản (~ 500 SLOC) mà tôi đã xuất bản :
Install-Package MlkPwgen
Sau đó, bạn có thể tạo các chuỗi ngẫu nhiên giống như trong câu trả lời bên dưới:
var str = PasswordGenerator.Generate(length: 10, allowed: Sets.Alphanumerics);
Một lợi thế của thư viện là mã được tính toán tốt hơn để bạn có thể sử dụng tính ngẫu nhiên an toàn cho nhiều hơn là tạo chuỗi . Kiểm tra trang web dự án để biết thêm chi tiết.
Vì chưa có ai cung cấp mã bảo mật nên tôi đăng phần sau để phòng khi có ai thấy hữu ích.
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();
}
}
Cảm ơn Ahmad đã chỉ ra cách để mã hoạt động trên .NET Core.
.netcore
: Thay thế var rng = new RNGCryptoServiceProvider()
bằngvar rng = RandomNumberGenerator.Create()
Tôi xin lưu ý rằng các GUID không phải là số ngẫu nhiên . Chúng không nên được sử dụng làm cơ sở để tạo bất kỳ thứ gì mà bạn mong đợi là hoàn toàn ngẫu nhiên (xem http://en.wikipedia.org/wiki/Globally_Unique_Identifier ):
Phân tích mật mã của trình tạo GUID WinAPI cho thấy rằng, vì chuỗi các GUID của V4 là giả ngẫu nhiên, với trạng thái ban đầu, người ta có thể dự đoán lên đến 250 000 GUID tiếp theo được trả về bởi hàm UuidCreate. Đây là lý do tại sao GUID không nên được sử dụng trong mật mã, chẳng hạn như khóa ngẫu nhiên.
Thay vào đó, chỉ cần sử dụng phương pháp C # Random. Một cái gì đó như thế này ( mã được tìm thấy ở đây ):
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 là tốt nếu bạn muốn một cái gì đó độc đáo (như một tên tệp hoặc khóa duy nhất trong cơ sở dữ liệu), nhưng chúng không tốt cho một cái gì đó bạn muốn ngẫu nhiên (như mật khẩu hoặc khóa mã hóa). Vì vậy, nó phụ thuộc vào ứng dụng của bạn.
Chỉnh sửa . Microsoft nói rằng Random cũng không phải là tuyệt vời ( http://msdn.microsoft.com/en-us/library/system.random(VS.71).aspx ):
Ví dụ, để tạo một số ngẫu nhiên an toàn bằng mật mã phù hợp để tạo mật khẩu ngẫu nhiên, hãy sử dụng một lớp có nguồn gốc từ System.Security.Cryptography.RandomNumberGenerator như System.Security.Cryptography.RNGCryptoServiceProvider.
Tôi đã đơn giản hóa giải pháp @Michael Kropats và tạo phiên bản 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();
}
}
Tôi không nghĩ rằng chúng thực sự là ngẫu nhiên, nhưng tôi đoán đó là một số hàm băm.
Bất cứ khi nào tôi cần một số nhận dạng ngẫu nhiên, tôi thường sử dụng GUID và chuyển đổi nó thành biểu diễn "trần trụi" của nó:
Guid.NewGuid().ToString("n");
Tôi ngạc nhiên tại sao không có giải pháp CrytpoGraphic tại chỗ. GUID là duy nhất nhưng không an toàn về mặt mật mã . Xem Dotnet Fiddle này.
var bytes = new byte[40]; // byte size
using (var crypto = new RNGCryptoServiceProvider())
crypto.GetBytes(bytes);
var base64 = Convert.ToBase64String(bytes);
Console.WriteLine(base64);
Trong trường hợp bạn muốn Thêm trước bằng Hướng dẫn:
var result = Guid.NewGuid().ToString("N") + base64;
Console.WriteLine(result);
Một chuỗi chữ và số rõ ràng hơn:
result = Regex.Replace(result,"[^A-Za-z0-9]","");
Console.WriteLine(result);
Giải pháp Michael Kropats trong 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
Điều này đã được yêu cầu cho các ngôn ngữ khác nhau. Đây là một câu hỏi về mật khẩu cũng nên được áp dụng ở đây.
Nếu bạn muốn sử dụng các chuỗi để rút ngắn URL, bạn cũng sẽ cần kiểm tra Từ điển <> hoặc cơ sở dữ liệu để xem liệu ID được tạo đã được sử dụng chưa.
Nếu bạn muốn một chuỗi chữ và số với các ký tự viết thường và viết hoa ([a-zA-Z0-9]), bạn có thể sử dụng Convert.ToBase64String () để có một giải pháp nhanh chóng và đơn giản.
Đối với tính duy nhất, hãy kiểm tra bài toán ngày sinh để tính toán khả năng một collission được cung cấp (A) độ dài của các chuỗi được tạo và (B) số lượng chuỗi được tạo.
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)
Nhận Khóa duy nhất bằng mã Hash 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);
}
string randoms = Guid.NewGuid().ToString().Replace("-", string.Empty).Replace("+", string.Empty).Substring(0, 4);
hơn có thể được tìm thấy ở đây