.NET GUIDs有多少确定性?

13
昨天我问了一个问题:Windows 2003生成的GUID作为会话ID是否安全?,答案结合这篇文章GUID是全球唯一的,但GUID的子字符串不是促使我考虑用GUID作为cookie中的会话ID的当前机制进行替换。
因为更改需要一些工作,所以我决定在我的Vista PC上运行快速的GUID测试,看看GUID序列是否明显具有确定性(我担心的是,如果攻击者能够获得由我的服务器生成的GUID序列,他们将能够生成新的匹配项)。
根据Raymond Chen的文章(引用自1998年的UUID和GUID规范),GUID由以下组成:
  • 60位时间戳,
  • 48位计算机标识符,
  • 14位唯一标识符,
  • 六位固定值
按照这个规则,如果我生成10个GUID,则前15个ASCII字符(不包括'-')是时间戳,接下来的12个ASCII字符是计算机标识符,接下来的3.5个ASCII字符是随机的,最后的1.5个字符是固定的。
使用.Net System.Guid.NewGuid()在我的Vista PC上获取10个GUID的结果为:
b4e95ead-3619-4dc2-9102-cf7ab0efd927
a45ee719-decd-46b2-8355-7becbe406f74
9af68d75-35a0-4907-b6ab-f15e33acfe96
bed88fa3-3209-4a19-97dd-85d5428ea5f4
123cb39b-8d81-41c6-8894-f1257a8f7606
e2b1f6b1-5791-4a18-80a9-5dc668574ecb
c52aa660-2629-4659-bb83-5583081e5a1c
76eda32d-ceda-412e-8ade-30c47416e954
cbc4d45e-7281-40d2-9f90-00539b04fe98
be36524c-267c-4791-bc9e-3c20b29d7615

一个快速的视觉检查中唯一可辨别的模式是,第13个ASCII字符始终为4。
我再次想知道,依赖System.Guid生成伪随机会话ID是否足够强大,能够保护一个攻击者最多只可能盗取几千美元价值的网络应用程序?
更新:与其使用GUID,我现在计划使用以下方法生成我的会话ID。我将384位随机数转换为0x00字节字符串,以便在HTTP cookie中使用。
RNGCryptoServiceProvider rngProvider = new RNGCryptoServiceProvider();
byte[] myKey = new byte[48];
rngProvider.GetBytes(myKey);
string sessionID = null;
myKey.ToList().ForEach(b => sessionID += b.ToString("x2"));
Console.WriteLine(sessionID);

一个GUID是完全确定性的,否则它就不能成为G和U,它只能成为一个ID。 - Noon Silk
5
显然,你从未见过我的电脑。它做的一些事情真的是非常、非常随机的。 - FacticiusVir
从数学的角度来看,人类可以比计算机生成更随机的数字。 - user161433
@luke:你从未向人们要求随机数,对吧?;-) - Joey
我喜欢你的新实现。我使用了 StringBuilder 来加速它。 - Evan M
显示剩余2条评论
6个回答

10

这不是一个完整的答案,但我可以告诉你十三进制数码始终为4,因为它表示用于生成GUID(即v4)的算法版本;此外,引用维基百科:

分析 WinAPI GUID 生成器表明,由于V4 GUID序列是伪随机的,鉴于初始状态,人们可以预测函数 UuidCreate 返回的接下来的250000个GUID。 这就是为什么不应该将GUID用于加密,例如作为随机密钥。

文章的其余部分及其参考文献:http://en.wikipedia.org/wiki/Guid

- 编辑 -

从安全角度考虑,我建议您以任何方式生成会话ID,然后进行加密签名;这样,您可以打包想要的任何信息,然后只需在末尾加上签名即可 - 可能的问题在于密钥的大小/强度与cookie的结果大小之间的权衡。 GUID非常有用作为ID,但我只会依赖于专用的加密技术来实现安全性。


7
我建议您使用System.Security.Cryptography.RandomNumberGenerator。它的设计目的是生成不能被逆向工程的数字。GUID的动机在于唯一性。您可以将GUID和安全随机数结合起来,但是128位安全随机数实际上不可能发生碰撞。

1

一些注意事项:

  1. 我怀疑任何GUID的实现都不是为了加密安全而设计的。(这个假设将通过下一个链接的文章得到证实。)
  2. 第13个ASCII字符是用于生成GUID的算法标识符

如果您真的关心拥有强大的会话ID,那么可能最好的方法是使用某些无法从机器外部确定的东西的加密安全哈希。也许从某个内部文档或数据源生成一次性密码本甚至也可以起作用。



0
你想做什么?你只是想要一个随机数的来源吗?
可以查看random.orghotbits。很多年前,我有一个Java库,可以从这些来源收集数字,并将它们组合在一起,得到一个非常美丽的随机序列(尽管它假设这两个网站没有串通)。

我认为你会发现随机数生成要容易得多:http://xkcd.com/221/ - FacticiusVir

-1

简短的回答是,如果您想防止会话 ID 猜测和破解,GUID 不足够强大来生成会话 ID。

出于与不希望使用 GUID 作为 AES 密钥相同的原因,您不希望将它们用于任何类型的敏感标识。

GUID 对于它们设计的目的非常有效:数学上保证唯一的 ID,永远不会重复。

即使破解会话 ID 的价值仅为 1000 美元,想象一下如果这样做了 100 次。现在你谈论的是严重的财富。

我知道使用 GUID 是一种简单的方法,但要抵制并通过采取适当的预防措施充分保护您的应用程序来处理痛苦。您的用户会感激您。


没有人能够预先猜测出GUID是什么,那么为什么在会话中使用GUID不好呢? - user161433
2
重点是,只要知道在同一台机器上短时间内生成的GUID,就可以“猜测”GUID是什么。 - FacticiusVir
@FacticiusVir - 这个有文档资料吗? - user161433

-1

考虑到获取重复的GUID的可能性,几乎是不可能的。以下是一些快速的数学事实:

世界上的沙粒数量为75,000,000,000,000,000,000

GUID数量为340,282,366,920,938,463,463,374,607,431,770,000,000


1
有足够的唯一GUID可分配给已知宇宙中的每颗星星,仍然有绝大多数剩余。然而,如果您从已知宇宙中的每颗星星“画”一条线到其他每颗星星,将没有足够的GUID来唯一标识它们。 - FacticiusVir
1
我相信星星的数量估计是3-7 x10 ^22,这将使它们之间的线条数在9-49 x10 ^44之间;少于一个googol的平方根。googolplex(请注意拼写)是1 x10 ^ googol,或者是一个后面跟着googol个零的数字1。 - FacticiusVir
抱歉,我完全搞砸了那个计算 扶额 - FacticiusVir
1
正确的计算方式是:n_个点之间的连线数为(n-1)!_,即_n-1_的阶乘。这可以简化为_n x ((n-1)/2)_,因此估计的范围在4.5 x 10 ^44和2.45 x 10 ^45之间。然而,重点仍然存在,这已经远离我们的讨论主题。 - FacticiusVir
@FacticiusVir 你说得没错,N个星号之间的行数将会是N*(N-1)/2。然而,遗憾的是,这并不等于(N-1)! = (N-1)(N-2)(N-3)(N-4)... - SteinNorheim
显示剩余2条评论

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