这些门票是用于购买中东地区的房产,每张门票的价值可能高达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亿年发生一次)。