たとえば、MSDNライブラリ(エラーオブジェクト)によって生成されるようなランダムな一意の文字列を生成したいのですが。't9zk6eay'のような文字列が生成されます。
たとえば、MSDNライブラリ(エラーオブジェクト)によって生成されるようなランダムな一意の文字列を生成したいのですが。't9zk6eay'のような文字列が生成されます。
回答:
Guidを使用するのはかなり良い方法ですが、例のようなものを取得するには、おそらくそれをBase64文字列に変換する必要があります。
Guid g = Guid.NewGuid();
string GuidString = Convert.ToBase64String(g.ToByteArray());
GuidString = GuidString.Replace("=","");
GuidString = GuidString.Replace("+","");
「=」と「+」を取り除いて、例に少し近づけます。そうしないと、文字列の最後に「==」が入り、中央に「+」が入ります。次に出力文字列の例を示します。
「OZVV5TpP4U6wJthaCORZEQ」
Convert.ToBase64String
については、こちらをご覧ください。
new Guid()
「ハッキング」(時計や内部Windowsデータ構造を改ざん)せずに使用すると衝突が発生するアプリケーションを実際に作成できる場合は、ビールに招待します。好きなだけコア、スレッド、同期プリミティブなどを自由に使用してください。
2016/1/23アップデート
この回答が役に立った場合は、私が公開したシンプルな(〜500 SLOC)パスワード生成ライブラリに興味があるかもしれません。
Install-Package MlkPwgen
次に、以下の答えのようにランダムな文字列を生成できます。
var str = PasswordGenerator.Generate(length: 10, allowed: Sets.Alphanumerics);
ライブラリの利点の1つは、コードをより効率的に除外できるため、文字列を生成するだけではなく、安全なランダム性を使用できることです。チェックアウトプロジェクトサイトの詳細については。
安全なコードはまだ誰も提供していないので、誰かが便利だと思った場合に備えて、以下を投稿します。
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 Coreでコードを機能させる方法を指摘してくれたAhmadに感謝します。
.netcore
:交換するvar rng = new RNGCryptoServiceProvider()
とvar rng = RandomNumberGenerator.Create()
GUIDは乱数ではないことに注意してください。完全にランダムであると予想されるものを生成するための基礎として使用しないでください(http://en.wikipedia.org/wiki/Globally_Unique_Identifierを参照):
WinAPI GUIDジェネレーターの暗号解析は、V4 GUIDのシーケンスが疑似ランダムであるため、初期状態が与えられると、関数UuidCreateによって返される次の250 000 GUIDまで予測できることを示しています。これが、GUIDを暗号化で、たとえばランダムキーとして使用してはならない理由です。
代わりに、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();
}
あなたが何かしたい場合はGUIDが細かいですユニーク(データベース内で一意のファイル名やキーなど)を、彼らはあなたがなりたいもののために良いものではありませんランダム(パスワードや暗号化キーなど)。したがって、アプリケーションによって異なります。
編集。マイクロソフトは、ランダムもそれほど良くないと言っています(http://msdn.microsoft.com/en-us/library/system.random(VS.71).aspx):
たとえば、ランダムパスワードの作成に適した暗号で保護された乱数を生成するには、System.Security.Cryptography.RNGCryptoServiceProviderなどのSystem.Security.Cryptography.RandomNumberGeneratorから派生したクラスを使用します。
@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();
}
}
それらが本当にランダムであるとは思わないが、私はそれらがいくつかのハッシュであると思う。
ランダムな識別子が必要なときはいつでも、私は通常GUIDを使用して、それを「裸の」表現に変換します。
Guid.NewGuid().ToString("n");
CrytpoGraphicソリューションが導入されていない理由に驚いています。GUIDは一意ですが、暗号的に安全ではありません。このDotnetフィドルを参照してください。
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);
VB.netのMichael Kropatsソリューション
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
これはさまざまな言語で求められています。ここでも同様に適用できるパスワードに関する質問があります。
URLの短縮に文字列を使用する場合は、生成されたIDがすでに使用されているかどうかを確認するために、Dictionary <>またはデータベースのチェックも必要です。
小文字と大文字の英数字文字列([a-zA-Z0-9])が必要な場合は、Convert.ToBase64String()を使用すると、高速でシンプルなソリューションを実現できます。
一意性については、誕生日の問題を確認して、(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)
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);
もっと試してみてください