CRYPT_GEN_RANDOM 够独特吗?
Is CRYPT_GEN_RANDOM enough unique?
我正在使用这个
生成一个令牌
SET @Token = CAST(CRYPT_GEN_RANDOM(16) AS UNIQUEIDENTIFIER)
令牌将在 URL 中可见,并且应该是唯一的。
使用它是个好主意吗?
您以这种方式生成的"GUID"不是真正的 GUID,因为 GUID 中保留的用于指示 GUID 的变体和版本的位也是随机的。实际上,大多数工具根本不关心或查看 GUID 的位,但可以想象某些系统或未来版本 将 有 GUID 问题无效的位模式。碰撞不是你必须担心的事情,因为剩下的位在你这边是随机的,但这仍然很难看。
对于(加密的)随机 GUID,您需要版本 4、变体 1 的 GUID。四位表示版本,两位表示变体 1,剩下 122 个随机位,应该足够了。在 T-SQL 中正确设置这些位并不直观,但可行:
SELECT CONVERT(UNIQUEIDENTIFIER,
CRYPT_GEN_RANDOM(7) +
-- Set version = 4
CONVERT(BINARY(1), (CRYPT_GEN_RANDOM(1) & 15) | 64) +
-- Set variant = 1
CONVERT(BINARY(1), (CRYPT_GEN_RANDOM(1) & 63) | 128) +
CRYPT_GEN_RANDOM(7)
)
位和字节的位置不直观,因为SQL服务器对它们的编码是weird。
同时考虑以下备选方案:
- 使用简单的
NEWID()
作为令牌,几乎不用担心攻击者可能会猜测下一个值,或者如果他们这样做也不会危及安全性。请记住,这通常至少需要能够随意生成 GUID 块,最坏的情况是访问生成 GUID 的机器的内存。前者可以限制速率,后者意味着它可能已经结束了。
- 使用随机字节,不假装它是 GUID,并将它们转换为十六进制字符串,如通过(例如)
SELECT CONVERT(CHAR(32), CRYPT_GEN_RANDOM(16), 2)
获得的(使用 SELECT CONVERT(BINARY(16), @s, 2)
转换回来)。字符串比 GUID 更容易传递,因此很难理解为什么您在这里绝对需要 GUID。您还可以获得 6 个完整的随机性位。 BINARY(16)
列的大小与 UNIQUEIDENTIFIER
相同,因此存储也不是问题。 (但您可能还是希望考虑使用字符串列,以便在将来为新的标记格式留出空间。)
我正在使用这个
生成一个令牌SET @Token = CAST(CRYPT_GEN_RANDOM(16) AS UNIQUEIDENTIFIER)
令牌将在 URL 中可见,并且应该是唯一的。
使用它是个好主意吗?
您以这种方式生成的"GUID"不是真正的 GUID,因为 GUID 中保留的用于指示 GUID 的变体和版本的位也是随机的。实际上,大多数工具根本不关心或查看 GUID 的位,但可以想象某些系统或未来版本 将 有 GUID 问题无效的位模式。碰撞不是你必须担心的事情,因为剩下的位在你这边是随机的,但这仍然很难看。
对于(加密的)随机 GUID,您需要版本 4、变体 1 的 GUID。四位表示版本,两位表示变体 1,剩下 122 个随机位,应该足够了。在 T-SQL 中正确设置这些位并不直观,但可行:
SELECT CONVERT(UNIQUEIDENTIFIER,
CRYPT_GEN_RANDOM(7) +
-- Set version = 4
CONVERT(BINARY(1), (CRYPT_GEN_RANDOM(1) & 15) | 64) +
-- Set variant = 1
CONVERT(BINARY(1), (CRYPT_GEN_RANDOM(1) & 63) | 128) +
CRYPT_GEN_RANDOM(7)
)
位和字节的位置不直观,因为SQL服务器对它们的编码是weird。
同时考虑以下备选方案:
- 使用简单的
NEWID()
作为令牌,几乎不用担心攻击者可能会猜测下一个值,或者如果他们这样做也不会危及安全性。请记住,这通常至少需要能够随意生成 GUID 块,最坏的情况是访问生成 GUID 的机器的内存。前者可以限制速率,后者意味着它可能已经结束了。 - 使用随机字节,不假装它是 GUID,并将它们转换为十六进制字符串,如通过(例如)
SELECT CONVERT(CHAR(32), CRYPT_GEN_RANDOM(16), 2)
获得的(使用SELECT CONVERT(BINARY(16), @s, 2)
转换回来)。字符串比 GUID 更容易传递,因此很难理解为什么您在这里绝对需要 GUID。您还可以获得 6 个完整的随机性位。BINARY(16)
列的大小与UNIQUEIDENTIFIER
相同,因此存储也不是问题。 (但您可能还是希望考虑使用字符串列,以便在将来为新的标记格式留出空间。)