How to make a Type 5 UUID in Java?

前端 未结 2 1842
南方客
南方客 2020-12-30 07:06

In python, to make a Type 5 UUID we can simply do:

import uuid
print uuid.uuid5(uuid.NAMESPACE_URL, \'my string\')

Looking through the java

相关标签:
2条回答
  • 2020-12-30 07:56

    In the case someone else needs a library that generates version 5 UUIDs.

    UUID uuid = UuidCreator.getNameBasedSha1("google.com");
    

    https://github.com/f4b6a3/uuid-creator

    0 讨论(0)
  • 2020-12-30 08:00

    You can implement it yourself by following the code proposed in https://stackoverflow.com/a/28776880/1452094. However this does require some fiddling since the j.u.UUID constructor takes longs.

    As of Java 8 the standard library does not seem to support type 5. But third party libraries like "Apache Commons Id" have UUID implementations that do support it.

    EDIT: Here is a fully functional implementation:

    import java.nio.charset.Charset;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.util.Objects;
    import java.util.UUID;
    
    public class UUIDType5 {
        private static final Charset UTF8 = Charset.forName("UTF-8");
        public static final UUID NAMESPACE_DNS = UUID.fromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8");
        public static final UUID NAMESPACE_URL = UUID.fromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8");
        public static final UUID NAMESPACE_OID = UUID.fromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8");
        public static final UUID NAMESPACE_X500 = UUID.fromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8");
    
        public static UUID nameUUIDFromNamespaceAndString(UUID namespace, String name) {
            return nameUUIDFromNamespaceAndBytes(namespace, Objects.requireNonNull(name, "name == null").getBytes(UTF8));
        }
    
        public static UUID nameUUIDFromNamespaceAndBytes(UUID namespace, byte[] name) {
            MessageDigest md;
            try {
                md = MessageDigest.getInstance("SHA-1");
            } catch (NoSuchAlgorithmException nsae) {
                throw new InternalError("SHA-1 not supported");
            }
            md.update(toBytes(Objects.requireNonNull(namespace, "namespace is null")));
            md.update(Objects.requireNonNull(name, "name is null"));
            byte[] sha1Bytes = md.digest();
            sha1Bytes[6] &= 0x0f;  /* clear version        */
            sha1Bytes[6] |= 0x50;  /* set to version 5     */
            sha1Bytes[8] &= 0x3f;  /* clear variant        */
            sha1Bytes[8] |= 0x80;  /* set to IETF variant  */
            return fromBytes(sha1Bytes);
        }
    
        private static UUID fromBytes(byte[] data) {
            // Based on the private UUID(bytes[]) constructor
            long msb = 0;
            long lsb = 0;
            assert data.length >= 16;
            for (int i = 0; i < 8; i++)
                msb = (msb << 8) | (data[i] & 0xff);
            for (int i = 8; i < 16; i++)
                lsb = (lsb << 8) | (data[i] & 0xff);
            return new UUID(msb, lsb);
        }
    
        private static byte[] toBytes(UUID uuid) {
            // inverted logic of fromBytes()
            byte[] out = new byte[16];
            long msb = uuid.getMostSignificantBits();
            long lsb = uuid.getLeastSignificantBits();
            for (int i = 0; i < 8; i++)
                out[i] = (byte) ((msb >> ((7 - i) * 8)) & 0xff);
            for (int i = 8; i < 16; i++)
                out[i] = (byte) ((lsb >> ((15 - i) * 8)) & 0xff);
            return out;
        }
    }
    

    To verify it works I ran the following code:

    public static void main(String[] args) {
        UUID test = UUIDType5.nameUUIDFromNamespaceAndString(NAMESPACE_URL, "google.com");
        System.out.println(test);
        System.out.println(test.version());
    }
    

    This created the output:

    fedb2fa3-8f5c-5189-80e6-f563dd1cb8f9

    5

    Verified against the official python implementation:

    >>> print(uuid.uuid5(uuid.NAMESPACE_URL, 'google.com'))

    fedb2fa3-8f5c-5189-80e6-f563dd1cb8f9

    0 讨论(0)
提交回复
热议问题