我遇到了以下问题:从受限制的字母表中生成N个唯一的字母数字字符串。这是我在C#中的解决方案:
string Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random generator = new Random();
const int ToGenerate = 10000;
const int CharactersCount = 4;
ArrayList generatedStrings = new ArrayList();
while( generatedStrings.Count < ToGenerate ) {
string newString = "Prefix";
for( int i = 0; i < CharactersCount; i++ ) {
int index = generator.Next( Alphabet.Length );
char character = Alphabet[index];
newString += character;
}
if( !generatedStrings.Contains( newString ) ) {
generatedStrings.Add( newString );
}
}
for( int i = 0; i < generatedStrings.Count; i++ ) {
System.Console.Out.WriteLine( generatedStrings[i] );
}
它生成以“前缀”开头的10K字符串,否则由大写字母和数字组成。输出看起来不错。
现在我看到以下问题。生成的字符串用于不太可能被任何人预测的情况。在我的计划中,种子是时间依赖的。一旦有人知道种子值,他就可以运行相同的代码并获得完全相同的字符串。如果他知道任何两个字符串,他可以很容易地找出我的算法(因为它真的很天真)并尝试暴力破坏种子值 - 只需枚举所有可能的种子值,直到他看到输出中的两个已知字符串。
是否可以对我的代码进行一些简单的更改,以减少所描述的攻击?
答案 0 :(得分:7)
System.Security.Cryptography.RandomNumberGenerator.Create
创建加密强大的随机数 - 例如:
var rng = System.Security.Cryptography.RandomNumberGenerator.Create();
byte[] buffer = new byte[4];
char[] chars = new char[CharactersCount];
for(int i = 0 ; i < chars.Length ; i++)
{
rng.GetBytes(buffer);
int nxt = BitConverter.ToInt32(buffer, 0);
int index = nxt % Alphabet.Length;
if(index < 0) index += Alphabet.Length;
chars[i] = Alphabet[index];
}
string s = new string(chars);
答案 1 :(得分:5)
嗯,这取决于你认为“简单”。
您可以使用“真实”的随机数源“解决”您的问题。您可以尝试免费的(random.org,fourmilab hotbits等)或buy one,具体取决于您正在运行的操作类型。
或者(也许更好)是不提前生成,而是按需生成。但这可能是对您的业务流程/模型的重大改变。