如何生成长引导?
问题内容:
我想生成一个长的UUID-
类似于gmail使用的会话密钥。它应该至少为256个字符,并且不超过512个字符。它可以包含所有字母数字字符和一些特殊字符(键盘上功能键下方的字符)。这已经完成了吗?还是有样品?
C ++或C#
更新:GUID是不够的。我们已经遇到了冲突,需要对此进行补救。512是目前的最大值,因为它将阻止我们更改已经发货的东西。
更新2:对于坚持GUID的独特性的人来说,如果有人想猜测您的下一个会话ID,则不必计算未来1万亿年的组合。他们所要做的就是限制时间因素,并且将在数小时内完成。
问题答案:
根据您的update2,即使msdn引用了Guid,也可以断定它是正确的。这是一种使用具有加密功能的随机数生成器来创建ID的方法。
static long counter; //store and load the counter from persistent storage every time the program loads or closes.
public static string CreateRandomString(int length)
{
long count = System.Threading.Interlocked.Increment(ref counter);
int PasswordLength = length;
String _allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ23456789";
Byte[] randomBytes = new Byte[PasswordLength];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(randomBytes);
char[] chars = new char[PasswordLength];
int allowedCharCount = _allowedChars.Length;
for (int i = 0; i < PasswordLength; i++)
{
while(randomBytes[i] > byte.MaxValue - (byte.MaxValue % allowedCharCount))
{
byte[] tmp = new byte[1];
rng.GetBytes(tmp);
randomBytes[i] = tmp[0];
}
chars[i] = _allowedChars[(int)randomBytes[i] % allowedCharCount];
}
byte[] buf = new byte[8];
buf[0] = (byte) count;
buf[1] = (byte) (count >> 8);
buf[2] = (byte) (count >> 16);
buf[3] = (byte) (count >> 24);
buf[4] = (byte) (count >> 32);
buf[5] = (byte) (count >> 40);
buf[6] = (byte) (count >> 48);
buf[7] = (byte) (count >> 56);
return Convert.ToBase64String(buf) + new string(chars);
}
编辑我知道有一些偏差,因为allowedCharCount
不能被255整除,如果该偏差落在其余部分的无芒数中,您可以摆脱偏差并获得一个新的随机数。
EDIT2-这不能保证唯一,您可以持有一个静态的64位(或更高,如果需要)单调计数器,将其编码为base46,并将其作为id的前4-5个字符。
更新-现在保证是唯一的
更新2:算法现在速度较慢,但消除了偏差。
编辑:我刚刚运行了一个测试,我想让您知道ToBase64String可以返回非字母数字字符(例如1编码为"AQAAAAAAAAA="
),以便您知道。
新版本:
从本页上的MattDotson的答案中得出的结论,如果您不太担心键空间,可以采用这种方式进行操作,这样可以更快地运行很多。
public static string CreateRandomString(int length)
{
length -= 12; //12 digits are the counter
if (length <= 0)
throw new ArgumentOutOfRangeException("length");
long count = System.Threading.Interlocked.Increment(ref counter);
Byte[] randomBytes = new Byte[length * 3 / 4];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(randomBytes);
byte[] buf = new byte[8];
buf[0] = (byte)count;
buf[1] = (byte)(count >> 8);
buf[2] = (byte)(count >> 16);
buf[3] = (byte)(count >> 24);
buf[4] = (byte)(count >> 32);
buf[5] = (byte)(count >> 40);
buf[6] = (byte)(count >> 48);
buf[7] = (byte)(count >> 56);
return Convert.ToBase64String(buf) + Convert.ToBase64String(randomBytes);
}