小编典典

如何生成长引导?

algorithm

我想生成一个长的UUID-
类似于gmail使用的会话密钥。它应该至少为256个字符,并且不超过512个字符。它可以包含所有字母数字字符和一些特殊字符(键盘上功能键下方的字符)。这已经完成了吗?还是有样品?

C ++或C#

更新:GUID是不够的。我们已经遇到了冲突,需要对此进行补救。512是目前的最大值,因为它将阻止我们更改已经发货的东西。

更新2:对于坚持GUID的独特性的人来说,如果有人想猜测您的下一个会话ID,则不必计算未来1万亿年的组合。他们所要做的就是限制时间因素,并且将在数小时内完成。


阅读 252

收藏
2020-07-28

共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);
}
2020-07-28