Sql server CRYPT_GEN_RANDOM足够独特吗?
我正在使用以下内容生成一个令牌Sql server CRYPT_GEN_RANDOM足够独特吗?,sql-server,uniqueidentifier,Sql Server,Uniqueidentifier,我正在使用以下内容生成一个令牌 SET @Token = CAST(CRYPT_GEN_RANDOM(16) AS UNIQUEIDENTIFIER) 令牌将在URL中可见,并且应该是唯一的 使用它是个好主意吗?以这种方式生成的“GUID”不是真正的GUID,因为GUID中保留的用于指示GUID的变体和版本的位也是随机的。实际上,大多数工具根本不关心或查看GUID的位,但可以想象的是,某些系统或未来版本的GUID位模式存在无效问题。你不必担心冲突,因为剩下的部分是随机的,但这仍然很难看 对于(
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)
)
位和字节的位置不是直观的,因为SQLServer对它们的编码是错误的
也可考虑以下备选方案:
selectconvert(CHAR(32)、CRYPT\u GEN\u random(16)、2)
(使用selectconvert(BINARY(16)、@s,2)
获得的。字符串比GUID更容易传递,所以很难理解为什么这里绝对需要GUID。你还得到了6个完整的随机性。二进制(16)列的大小与UNIQUEIDENTIFIER的大小相同,因此存储也不是问题。(但您可能希望考虑使用String列,以在将来留出新的令牌格式的开放空间))好主意很广泛。您提出的唯一真正的问题是它是否唯一。我在这里看到的问题是您没有控制GUID的类型。应该只随机生成类型4的guid,但是您的值可以声明为其他类型,因此会与已经使用的值发生冲突。换句话说,可以生成16个随机字节。一般来说,将结果强制转换为带有附加语义的GUID/uniqueidentifier是不好的。这将无法获得有效的GUID。特别是,GUID的“类型”位将随机填充。如果您想要16个安全的随机字节,那么就获得16个随机字节,但不要假装它们是GUID。只需将令牌作为十六进制字符串传递,这样就不会出现混淆(
CONVERT(VARCHAR(32),CRYPT\u GEN\u RANDOM(16),2)
)。假装它是一个GUID的问题是,不可避免地,有人会在某个地方实际使用NEWID()
,认为这没问题,因为GUID不应该是安全的。在这种情况下使用合适的类型。如果您想要一个既随机又唯一的GUID,并且您不介意生成一个GUID的时间比使用NEWID()
要长一点,那么您仍然可以使用CRYPT\u GEN\u random()
生成随机位,然后正确设置“type”和“version”位。这将为您提供122位加密安全性,这可能就足够了。阅读血淋淋的细节。如果您不想要或不需要该结构,请使用16个字节,但不要强制转换为uniqueidentifier
/guid
,并声明您实际上没有遵守的结构。