我想知道是否有一种方法可以生成有效的 GUID/UUID,其中第一个(或任何部分)部分是用户选择的前缀。
即,GUID 的格式为 AAAAAAAAA-BBBB-CCCC-DDDD-DDDDDDDDDDDD,我想将任何部分设置为预定义的值(最好是 AAA)。目标是让 GUID 仍然是全球唯一的,但它们不需要是加密安全的。
抱歉,您对 GUID 的要求太多了。从您的问题和您自己的答案/更新中总结,您希望它
这是不可能的,证明:如果可能的话,我可以生成一个 GUID G1,而您可以生成另一个 GUID G2。由于我们都忽略了标准并使用相同的保留前缀,而且我对其他位的个人方案超出了您的控制范围,因此我的 GUID G1 可能与您的 GUID G2 发生冲突。GUID 的非冲突属性遵循 GUID 标准。
防止冲突的机制本质上是对隐私敏感的。如果我随机生成一个 GUID G1,如果满足两个条件,我可以保证随机 GUID 是唯一的:
对于您控制的子集之外的 GUID,您不能保证 (2)。但是如何将不重叠的 GUID 子集分配给一个人呢?使用网卡的 MAC 是一种简单有效的方法。其他方式也是可能的。但无论如何,仅仅存在这样一个子集就涉及隐私。它必须属于某个人,我必须能够确定那是我还是其他人。证明两个随机 GUID G1 和 G2 是否属于同一子集(即人)有点困难,但当前方案(您反对)并没有试图隐藏这一点。
嗯...所以,您基本上想要一个 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应该可以让您到达那里。
无法创建第一个(或任何部分)部分是用户选择的前缀的 GUID/UUID,而您可以编写自己的函数来创建具有相同数量(36/38)字符的唯一 ID...
您可以简单地创建一个 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,但不能保证全局唯一。在生成指南时甚至不考虑时间。
我最近也有类似的需求——我需要一个 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 倍。
谢谢。正如Raymond Chen所指出的,我对这些尝试的问题是它们不能保证是全球唯一的。我想知道是否有另一种算法可以生成唯一的 GUID。我记得曾经有使用时间戳和/或 NIC MAC 地址的实现,但它们不再使用,因为它们不是加密强和/或存在隐私问题。
我想知道:如果我自己编,我应该没问题吗?根据维基百科:
数据 4 中第二个字节的一到三个最高有效位定义了 GUID 的类型变体:
模式描述
0 网络计算系统向后兼容
10 标准
110 微软组件对象模型向后兼容;这包括 IUnknown 和 IDispatch 等重要接口的 GUID。
111 保留供将来使用。Data3 的最高有效四位定义版本号和使用的算法。
因此,如果我在 Data3/Data4 中编造一些东西,我通常会创建自己的实现,该实现不应与任何其他 GUID 冲突,但当然总是存在一些与之相关的风险,所以在我这样做之前,我想检查一下如果有一个旧的/不再使用的算法可以生成真正的唯一 ID。