不久前,我开发了一个网络应用程序,用户可以在其中购买门票。由于我们客户流程的工作方式,您在购买后实际上得到的是一个包含票号的 URL。
这些是在中东购买房产的门票,每张门票的潜在价值约为 3,000,000 美元。显然,给出连续整数是一个坏主意。我们使用 GUID,因为它们基本上是无法猜测的,但我的问题是:它们足够安全吗?
据我了解,.NET 生成的 GUID 完全是伪随机的(除了一些不变的位)。但是,我不知道使用什么算法来生成它们。
MSDN 文档告诉我们Random http://msdn.microsoft.com/en-us/library/system.random.aspx快速且不安全,并且RNGCryptoServiceProvider http://msdn.microsoft.com/en-us/library/system.security.cryptography.rngcryptoserviceprovider.aspx缓慢而安全。也就是说,假设某人可以付出足够的努力来预测结果是合理的Random
,但不属于RNGCryptoServiceProvider
.
如果您看到足够长的 GUID 序列,是否可以预测未来的 GUID?如果是这样,您需要看多少个?
[在我们的特殊情况下,后来进行了物理安全检查 - 你必须出示用于购买机票的护照 - 所以它不会too如果有人猜到了别人的 GUID,那就糟糕了,所以我们当时并没有担心。使用 GUID 作为数据库密钥的便利性使其成为一种有用的数据类型。]
Edit:
所以答案是“不够”。
Using 0xA3 https://stackoverflow.com/users/40347/0xa3下面的答案,以及以下链接question https://stackoverflow.com/questions/2621563/how-random-is-system-guid-newguid-take-two他链接到,以下代码将生成一个加密随机 GUID,该 GUID 通过以下方式有效RFC 4122 第 4.4 节 https://www.rfc-editor.org/rfc/rfc4122#section-4.4:
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 的速度比Guid.NewGuid()
,但对于 122 位“非常随机”的数据,它们是安全不可预测的。
当然,任何加密随机文本都可以作为票号,但 GUID 非常方便。 :-)
与其他版本 4 GUID 一样,不能绝对保证唯一性,但可能性令人印象深刻。只要您的数量少于 326,915,130,069,135,865(即sqrt(-22^122ln(0.99)) http://www.wolframalpha.com/input/?i=sqrt(-2*2%5E122*ln(0.99))) GUID 同时运行,您可以 99% 以上确定不会发生冲突。换句话说:如果像我一样,如果您的应用程序有超过int.MaxValue
几乎任何事情,你都可以有超过 99.9999999999999999% 的把握不会发生碰撞(即e^-(((2^31-1)^2)/(2*2^122)) http://www.wolframalpha.com/input/?i=e%5E-(((2%5E31-1)%5E2)/(2*2%5E122)))。这比您确信陨石不会在应用程序上线后一秒内消灭地球上的大部分生命(即,更确定)大约一千倍。每一亿年就有一个 http://en.wikipedia.org/wiki/Impact_event#Mass_extinctions_and_impacts).