Java随机UUID是可预测的吗?
我想对数据库中的敏感数据使用加密安全的主键 - 这不能是可猜测/可预测的,也不能由数据库生成(在对象持久化之前我需要密钥)。
我知道Java使用带有加密安全随机数生成器的4类UUID,但是我知道UUID不是完全随机的,所以我的问题是假设uuid不能从一组现有中预测有多安全?
我想对数据库中的敏感数据使用加密安全的主键 - 这不能是可猜测/可预测的,也不能由数据库生成(在对象持久化之前我需要密钥)。
我知道Java使用带有加密安全随机数生成器的4类UUID,但是我知道UUID不是完全随机的,所以我的问题是假设uuid不能从一组现有中预测有多安全?
好吧,如果你想知道UUID的随机性有多大,你必须看看源代码。
以下代码部分取自 OpenJDK7(在 OpenJDK6 中完全相同):
public static UUID randomUUID() {
SecureRandom ng = numberGenerator;
if (ng == null) {
numberGenerator = ng = new SecureRandom();
}
byte[] randomBytes = new byte[16];
ng.nextBytes(randomBytes);
randomBytes[6] &= 0x0f; /* clear version (set highest 4 bits to zero) */
randomBytes[6] |= 0x40; /* set to version 4 */
randomBytes[8] &= 0x3f; /* clear variant (set highest 2 bits to zero) */
randomBytes[8] |= 0x80; /* set to IETF variant */
return new UUID(randomBytes);
}
如您所见,16个字节中只有2个不是完全随机的。在第六个字节中,您丢失了8位中的4位,而在字节8上,您丢失了2位随机性。
因此,您将获得一个 128 位值,具有 122 位随机性。
操作可能产生的唯一问题是,您的数据很有可能被识别为UUID。因此,如果您想将其隐藏在其他随机数据中,这将不起作用...
如果你想生成一个安全的随机密钥,我建议你使用SecureRandom。这可以生成您需要的任意位数的密钥。它比随机慢,但更安全。