Java随机UUID是可预测的吗?

2022-09-01 00:39:54

我想对数据库中的敏感数据使用加密安全的主键 - 这不能是可猜测/可预测的,也不能由数据库生成(在对象持久化之前我需要密钥)。

我知道Java使用带有加密安全随机数生成器的4类UUID,但是我知道UUID不是完全随机的,所以我的问题是假设uuid不能从一组现有中预测有多安全?


答案 1

好吧,如果你想知道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。因此,如果您想将其隐藏在其他随机数据中,这将不起作用...


答案 2

如果你想生成一个安全的随机密钥,我建议你使用SecureRandom。这可以生成您需要的任意位数的密钥。它比随机慢,但更安全。