如何生成的LONG GUID?LONG、GUID

2023-09-11 02:08:49 作者:抹茶夢境

我想生成一个长的UUID - 像使用Gmail的会话密钥。它应该至少为256个字符并且不超过512可以包含所有字母数字字符和一些特殊字符(功能键下方的那些键盘上)。这种情形已经已经完成或者是有一个样本出来吗?

I would like to generate a long UUID - something like the session key used by gmail. It should be at least 256 chars and no more than 512. It can contain all alpha-numeric chars and a few special chars (the ones below the function keys on the keyboard). Has this been done already or is there a sample out there?

C ++或C#

更新:GUID是远远不够的。我们已经看到了碰撞,需要尽快解决这个问题。 512是最高截至目前为止,因为它会$ P $更改的东西,已经被运pvent我们。

Update: A GUID is not enough. We already have been seeing collisions and need to remedy this ASAP. 512 is the max as of now because it will prevent us from changing stuff that was already shipped.

更新2:谁是坚持对GUID如何独特的是球员,如果有人想猜测你的下一个会话ID,他们没有计算组合在未来万亿年。他们所要做的就是限制使用时间因素,他们将在数小时之内完成。

Update 2: For the guys who are insisting about how unique the GUID is, if someone wants to guess your next session ID, they don't have to compute the combinations for the next 1 trillion years. All they have to do is use constrain the time factor and they will be done in hours.

推荐答案

根据您的UPDATE2你在正确的GUID甚至在MSDN引用了predicable。这里是使用crptographicly强随机数生成器来创建所述ID的方法

As per your update2 you are correct on Guids are predicable even the msdn references that. here is a method that uses a crptographicly strong random number generator to create the 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整除,则可以摆脱偏见扔掉,并得到一个新的随机数如果它的土地中的无芒-土地的其余部分。

EDIT I know there is some biasing because allowedCharCount is not evenly divisible by 255, you can get rid of the bias throwing away and getting a new random number if it lands in the no-mans-land of the remainder.

EDIT2 - 这是不能保证是独一无二的,你可以持有一个静态64位(或更高版本如果需要的话)单调计数器EN $ C C是$以base46并具有成为第一个4-5个字符ID号。

更新 - 现在保证是唯一

UPDATE - Now guaranteed to be unique

更新2:算法是目前速度较慢,但​​去除偏置

UPDATE 2: Algorithm is now slower but removed biasing.

编辑:我只是跑一个测试,我想让你知道,ToBase64String可以返回非字母数字的字数(如1 CN codeS到AQAAAAAAAAA = ),只是让你知道。

I just ran a test, I wanted to let you know that ToBase64String can return non alphnumeric charaters (like 1 encodes to "AQAAAAAAAAA=") just so you are aware.

新版本:

拍摄此页面上,如果你没有这么担心,你可以做这样的密钥空间这样,它会跑快了很多。

Taking from Matt Dotson's answer on this page, if you are no so worried about the keyspace you can do it this way and it will run a LOT faster.

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);
}