3

我想知道是否有一种方法可以生成有效的 GUID/UUID,其中第一个(或任何部分)部分是用户选择的前缀。

即,GUID 的格式为 AAAAAAAAA-BBBB-CCCC-DDDD-DDDDDDDDDDDD,我想将任何部分设置为预定义的值(最好是 AAA)。目标是让 GUID 仍然是全球唯一的,但它们不需要是加密安全的。

4

6 回答 6

5

抱歉,您对 GUID 的要求太多了。从您的问题和您自己的答案/更新中总结,您希望它

  • 1 是一个 GUID
  • 2 不与任何其他 GUID 冲突(全局唯一)
  • 3 忽略关于第一位解释的标准,使用保留值
  • 4 对剩余位使用个人方案

这是不可能的,证明:如果可能的话,我可以生成一个 GUID G1,而您可以生成另一个 GUID G2。由于我们都忽略了标准并使用相同的保留前缀,而且我对其他位的个人方案超出了您的控制范围,因此我的 GUID G1 可能与您的 GUID G2 发生冲突。GUID 的非冲突属性遵循 GUID 标准。

防止冲突的机制本质上是对隐私敏感的。如果我随机生成一个 GUID G1,如果满足两个条件,我可以保证随机 GUID 是唯一的:

  • 1 它是我控制下的 GUID 子集的成员,并且
  • 2 我之前没有生成 GUID。

对于您控制的子集之外的 GUID,您不能保证 (2)。但是如何将不重叠的 GUID 子集分配给一个人呢?使用网卡的 MAC 是一种简单有效的方法。其他方式也是可能的。但无论如何,仅仅存在这样一个子集就涉及隐私。它必须属于某个人,我必须能够确定那是我还是其他人。证明两个随机 GUID G1 和 G2 是否属于同一子集(即人)有点困难,但当前方案(您反对)并没有试图隐藏这一点。

于 2008-12-09T14:35:45.567 回答
5

嗯...所以,您基本上想要一个 12 字节的 GUID?因为,一旦你删除了前 4 个字节(你的 AAA)的唯一性,你就破坏了现有的算法——你需要想出自己的算法。

根据相关RFC,GUID 格式分解为:

  UUID                   = time-low "-" time-mid "-"
                           time-high-and-version "-"
                           clock-seq-and-reserved
                           clock-seq-low "-" node
  time-low               = 4hexOctet
  time-mid               = 2hexOctet
  time-high-and-version  = 2hexOctet
  clock-seq-and-reserved = hexOctet
  clock-seq-low          = hexOctet
  node                   = 6hexOctet
  hexOctet               = hexDigit hexDigit
  hexDigit =
        "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" /
        "a" / "b" / "c" / "d" / "e" / "f" /
        "A" / "B" / "C" / "D" / "E" / "F"

唯一的静态数据是版本(4 位)和保留/变体(2-3 位)。我没有看到他们允许任何“用户指定”的版本,但我想说如果您使用 1111 作为您的版本标识符,那么在可预见的未来您将是安全的。现有版本在第 4.1.3 节中,但到目前为止只定义了 5 个……在碰撞之前为您提供了 11 个更多的修订。

因此,如果您可以忍受 6 或 7 位的区别,那么Guid.NewGuid().ToByteArray()的组合和在您的位摆弄之后创建一个新的 Guid应该可以让您到达那里。

于 2008-12-09T14:41:57.583 回答
2

无法创建第一个(或任何部分)部分是用户选择的前缀的 GUID/UUID,而您可以编写自己的函数来创建具有相同数量(36/38)字符的唯一 ID...

于 2008-12-09T13:24:02.280 回答
1

您可以简单地创建一个 Guid,并将前缀更改为您希望的样子。在 OS-Project 中看到了这一点,通过生成如此多的 guid 直到一个匹配所需的前缀(啊!),抛出并解决了同样的问题。

Guid g = Guid.NewGuid(); string gs = g.ToString(); Guid f = new Guid(string.Format("{0}-{1}", "AAAAAAAA", gs.Substring(gs.IndexOf('-') + 1)));

不好,但有效。

这个主题的其他帖子让我感到困扰的是,一个 guid 应该是全局唯一的,这在所有情况下都是错误的,它有足够的空间来生成唯一的 guid,但不能保证全局唯一。在生成指南时甚至不考虑时间。

于 2008-12-09T14:01:50.723 回答
1

我最近也有类似的需求——我需要一个 GUID:

  • 由标准 guid 算法创建,因此有机会成为全球唯一
  • 有一个定义的前缀。

正如你可能想象的那样,我正在做我不应该做的事情。

您在其中一条评论中提到,您可以让 GUID 生成器运行,直到它碰巧遇到带有您需要的前缀的 guid。这就是我采取的策略。这是代码:

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string target_prefix = "dead";

            while (true)
            {
                Guid g = Guid.NewGuid();
                string gs = g.ToString();
                if (gs.Substring(0, target_prefix.Length) == target_prefix)
                {
                    Console.WriteLine("Match: " + gs);
                }
                else
                {
                    //Console.WriteLine("Mismatch: " + gs);
                }
            }
        }
    }
}

对于较小的前缀,它会更快地产生匹配。我敢打赌,目标前缀的每个数字都是 16 倍。

于 2011-02-09T18:33:35.880 回答
0

谢谢。正如Raymond Chen所指出的,我对这些尝试的问题是它们不能保证是全球唯一的。我想知道是否有另一种算法可以生成唯一的 GUID。我记得曾经有使用时间戳和/或 NIC MAC 地址的实现,但它们不再使用,因为它们不是加密强和/或存在隐私问题。

我想知道:如果我自己编,我应该没问题吗?根据维基百科

数据 4 中第二个字节的一到三个最高有效位定义了 GUID 的类型变体:

模式描述
0 网络计算系统向后兼容
10 标准
110 微软组件对象模型向后兼容;这包括 IUnknown 和 IDispatch 等重要接口的 GUID。
111 保留供将来使用。

Data3 的最高有效四位定义版本号和使用的算法。

因此,如果我在 Data3/Data4 中编造一些东西,我通常会创建自己的实现,该实现不应与任何其他 GUID 冲突,但当然总是存在一些与之相关的风险,所以在我这样做之前,我想检查一下如果有一个旧的/不再使用的算法可以生成真正的唯一 ID。

于 2008-12-09T14:17:45.433 回答