GUID是多少安全的不可预测?

64
不久前,我参与了一个网络应用程序的开发,用户可以购买门票。由于我们客户的流程方式,实际上您购买的结果是一个带有门票号码的URL。
这些门票是用于购买中东地区的房产,每张门票的价值可能高达300万美元。显然,分配顺序整数将是一个糟糕的想法。我们使用GUID作为它们基本上是无法猜测的,但我的问题是:它们足够安全吗?
据我所知,.NET生成的GUID是完全伪随机的(除了一些不变的位)。但我不知道用于生成它们的算法是什么。
MSDN文档告诉我们,Random快速但不安全,RNGCryptoServiceProvider慢但安全。也就是说,可以合理地假设某人可以付出足够的努力来预测Random的结果,但不能预测RNGCryptoServiceProvider的结果。
如果您看到足够长的GUID序列,是否可能预测未来的GUID?如果是,需要看多少个?
[在我们的特定情况下,后来进行了物理安全检查 - 您必须提供用于购买门票的护照 - 因此,如果有人猜测了别人的GUID,情况也不会太糟糕,因此我们当时并没有担心。使用GUID作为数据库键的方便性使其成为一种有用的数据类型。]

编辑:

所以答案是"不够"。

使用0xA3下面的答案,并从他链接的问题中跟随链接,以下代码将生成一个在RFC 4122的4.4节有效的加密随机GUID:

static Guid MakeCryptoGuid()
{
    // Get 16 cryptographically random bytes
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    byte[] data = new byte[16];
    rng.GetBytes(data);

    // Mark it as a version 4 GUID
    data[7] = (byte)((data[7] | (byte)0x40) & (byte)0x4f);
    data[8] = (byte)((data[8] | (byte)0x80) & (byte)0xbf);

    return new Guid(data);
}

这比Guid.NewGuid()生成GUID要慢得多,但是由于有122位"非常随机"的数据,因此它们是安全不可预测的。

当然,任何加密随机文本都可以用作票据号码,但GUID非常方便。 :-)

与其他版本4 GUID一样,没有绝对的唯一性保证,但概率相当高。只要您同时拥有少于326,915,130,069,135,865(即sqrt(-22^122ln(0.99)))个GUID在使用中,您就可以超过99%确信没有冲突。换句话说:如果像我的应用程序一样,如果您有超过int.MaxValue的几乎任何内容,您就会在各个地方遇到溢出错误,那么您可以超过99.9999999999999999%确信没有冲突(即e^-(((2^31-1)^2)/(2*2^122)))。这比您确信陨石不会在应用程序上线后的一秒钟内摧毁地球上大部分生命的可能性高出约一千倍(即每1亿年发生一次)。


10
当涉及到如此巨额的资金时,你需要找一个人来承担责任,当彩票受到破坏时。你会聘请一位安全顾问。 - Hans Passant
2
有一个与某些放射性元素和探测器相连的网络服务。它将辐射转换为数字并将其发送给您。这可以被认为是“随机”的。Schrödinger也赞同。 - Andrey
2
简单来说:在.NET中,GUID不是真正的UID,当然也不是全局唯一的。它符合v4标准,但我们实际上不能称其为UID,更别提全局唯一的ID了。其中128位中有6位是固定位,留下一个容量为2^122的随机数。这个随机数不是唯一的,当然也不是全局唯一的,并且其生成方式也不安全。换句话说:如果您真的非常关心安全,最好不要使用它们。 - Stefan Steiger
1
在 https://news.ycombinator.com/item?id=10631806 上有一个很好的讨论。总结起来,一些GUID/UUID生成器是具有密码学安全性的,而另一些则不是。 - Elroy Flynn
4个回答

35

UUIDs/GUIDs 是由 RFC4122 规定的。尽管 Version 4 UUIDs 是由随机数生成的,但是在第6节中明确提出了安全性问题:

不要假设 UUIDs 很难被猜测;它们不应该用作安全能力(仅凭其拥有权就可访问的标识符),例如。可预测的随机数源会加剧情况。

对 GUID 的随机性的良好讨论也可以在以下问题中找到:

System.Guid.NewGuid() 有多随机?(第二版)


14

这是一个不正确的安全问题处理方式的完美例子。不幸的是,大多数开发人员都以这种方式思考安全问题...

...可能价值约300万美元...它们是否足够安全?...

不是的。对于可能赢得每张彩票3百万美元的问题,可以动用大量资源来解决。那样的钱会吸引拥有大量资源的人...其中一些人非常严肃。使用依赖于通用随机数生成器的任何东西都不是非常随机...因此不是非常安全。这更像是混淆而不是加密。

...进行了物理安全检查...必须出示使用的护照...

同样,在这条线上有那么多钱的情况下...我可以帮你获得任何你想要的护照。

...是否可能预测未来的密码?...

是的。问题是...需要多长时间?...每个单位的处理工作。

...如果可以,需要观察多少个?...

这取决于我对它们的创建所知道的信息...操作系统、CPU等...我相信我可以找到你公司内部的某个人愿意提供一些信息,以换取100,000美元或更少的报酬。

-- 这一切可能看起来有点过于夸张,但你谈论的是大量的钱,它应该受到严格的安全保护。你需要一家安全咨询公司,他们可以帮助你选择购买的加密包。你的客户应该能够通过其风险管理部门或保险公司提供帮助...如果没有,那就自己找律师...你应该已经有一个律师了

当然,GUID方案出问题的可能性非常小,但如果确实出了问题......你将如何告诉那些律师你的安全计划是一流的,他们应该去寻找别的地方?相信我,如果发生了什么意外情况,你不想 背黑锅。这对你来说真的很糟糕。

编辑:根据teedyay的评论...

从客户那里获得一张“走出牢笼”的卡片总是一个好主意。如果你告诉他们“我们可以在轻微攻击的情况下使其更加安全......但我们不是一家安全或密码公司。” 那么你的任务就完成了,客户会 承担风险


的确。像往常一样,客户希望以尽可能少的代价获得尽可能多的服务,因此不愿意为专业安全顾问支付足够的费用。这有些让人失望,但事实就是如此,所以我们必须尽力而为。他们意识到存在的风险,并满意于自己的物理安全检查能够应对任何之前发生的问题。不过我明白你的观点——如果责任能够由我们来承担,我们会更加小心谨慎。 - teedyay
@teedyay 很好,你和客户进行了那次谈话...他们知道得越多越好。 - Rusty

8

GUID是由一个非常著名的算法生成的。它们没有内置随机性,而是使用已知值,如网络卡ID和时间戳来生成。

它们绝不能被用作安全手段。

编辑

新版本的GUID/UUID算法似乎不再使用硬件地址来产生部分值,而是使用伪随机数。但这些数字并非真正随机,仍然不应用于安全关键应用程序。


6
我模糊地记得听说MAC地址组件由于某些漏洞被替换了......我会查一下。 - Paul Ruane
2
好的,显然对 System.Guid 的调用最终会通过调用 CoCreateGuid 转化为对 UuidCreate 的调用,后者不再包含网络适配器信息。 - Paul Ruane
3
自Windows 2000以来,Windows(和.NET)使用版本4的UUID,即GUID不再基于MAC地址或时间戳,这是为了安全原因。 - Dirk Vollmar
1
我想一个人总是有自由创建自己的 GUID,由加密随机数组成。性能方面可以通过预先计算数字来解决一些问题。 - Paul Ruane
2
这条评论已经过时18年了。自Windows 2000以来,Windows一直在使用带有加密随机数生成器的UUID v4。 - PRMan
显示剩余2条评论

1

从功能上讲

有人说GUID / UUID不安全。这是真的吗?

C#的GUID是一个128位整数,意味着有很多组合:170,141,183,460,469,231,731,687,303,715,884,105,727

但假设我们的攻击者使用暴力破解,每次尝试需要0.1秒,你知道我们在谈论很长时间,所以没有人会冒险这样做。

但是假设GUID不是“安全”的,因此熵降低到32位(2,147,483,647),这意味着暴力破解攻击可能持续

2,147,483,647 x 0.1秒/60/60/24 = 2400天。因此,即使32位GUID是安全的(但可能会产生冲突)。

我们可以争论说GPU或超级计算机可以在几秒钟内生成那么多组合数字。是的,但是如果无法测试生成的值列表就毫无意义。

此外,暴力攻击很容易识别,这就是我们所说的DDOS,并且有几种方法可以减轻它。

从数学上讲,GUID是安全的,但数学世界和现实世界有很大不同。


序列的可预测性是一个重要的考虑因素。传统的伪随机数遵循可预测的模式。如果攻击者能够获取足够多的生成数以找出这个模式,他就可以预测所有随后生成的数。无需使用蛮力攻击。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接