From f66bfa5088c996465d5e6729f61b0185badbcd8e Mon Sep 17 00:00:00 2001 From: Diego Torres Date: Thu, 24 Jun 2021 16:10:31 -0400 Subject: [PATCH] [uuid] Added method to generate UUID identifiers for version 5 (#10948) Signed-off-by: Diego Torres --- .../java/com/baeldung/uuid/UUIDGenerator.java | 56 ++++++++++++++++--- .../baeldung/uuid/UUIDGeneratorUnitTest.java | 10 ++++ 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java b/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java index cb43a26929..49d43c38a2 100644 --- a/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java +++ b/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java @@ -1,6 +1,8 @@ package com.baeldung.uuid; import java.io.UnsupportedEncodingException; +import java.nio.ByteOrder; +import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.time.Duration; @@ -132,21 +134,21 @@ public class UUIDGenerator { } private static byte[] bytesFromUUID(String uuidHexString) { - String normalizedUUIDHexString = uuidHexString.replace("-",""); + String normalizedUUIDHexString = uuidHexString.replace("-", ""); assert normalizedUUIDHexString.length() == 32; byte[] bytes = new byte[16]; for (int i = 0; i < 16; i++) { - byte b = hexToByte(normalizedUUIDHexString.substring(i*2, i*2+2)); + byte b = hexToByte(normalizedUUIDHexString.substring(i * 2, i * 2 + 2)); bytes[i] = b; } return bytes; } public static byte hexToByte(String hexString) { - int firstDigit = Character.digit(hexString.charAt(0),16); - int secondDigit = Character.digit(hexString.charAt(1),16); + int firstDigit = Character.digit(hexString.charAt(0), 16); + int secondDigit = Character.digit(hexString.charAt(1), 16); return (byte) ((firstDigit << 4) + secondDigit); } @@ -154,14 +156,54 @@ public class UUIDGenerator { int finalLength = byteArray1.length + byteArray2.length; byte[] result = new byte[finalLength]; - for(int i = 0; i < byteArray1.length; i++) { + for (int i = 0; i < byteArray1.length; i++) { result[i] = byteArray1[i]; } - for(int i = 0; i < byteArray2.length; i++) { - result[byteArray1.length+i] = byteArray2[i]; + for (int i = 0; i < byteArray2.length; i++) { + result[byteArray1.length + i] = byteArray2[i]; } return result; } + + public static UUID generateType5UUID(String name) { + + try { + + byte[] bytes = name.getBytes(StandardCharsets.UTF_8); + MessageDigest md = MessageDigest.getInstance("SHA-1"); + + byte[] hash = md.digest(bytes); + + long msb = peekLong(hash, 0, ByteOrder.BIG_ENDIAN); + long lsb = peekLong(hash, 8, ByteOrder.BIG_ENDIAN); + // Set the version field + msb &= ~(0xfL << 12); + msb |= ((long) 5) << 12; + // Set the variant field to 2 + lsb &= ~(0x3L << 62); + lsb |= 2L << 62; + return new UUID(msb, lsb); + + } catch (NoSuchAlgorithmException e) { + throw new AssertionError(e); + } + } + + private static long peekLong(final byte[] src, final int offset, final ByteOrder order) { + long ans = 0; + if (order == ByteOrder.BIG_ENDIAN) { + for (int i = offset; i < offset + 8; i += 1) { + ans <<= 8; + ans |= src[i] & 0xffL; + } + } else { + for (int i = offset + 7; i >= offset; i -= 1) { + ans <<= 8; + ans |= src[i] & 0xffL; + } + } + return ans; + } } \ No newline at end of file diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/uuid/UUIDGeneratorUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/uuid/UUIDGeneratorUnitTest.java index 9e08363a63..b2ca979c83 100644 --- a/core-java-modules/core-java/src/test/java/com/baeldung/uuid/UUIDGeneratorUnitTest.java +++ b/core-java-modules/core-java/src/test/java/com/baeldung/uuid/UUIDGeneratorUnitTest.java @@ -61,4 +61,14 @@ class UUIDGeneratorUnitTest { assertEquals(5, uuid.version()); assertEquals(2, uuid.variant()); } + + @Test + public void version_5_UUID_is_correctly_generated_for_domain_baeldung_com_without_namespace() throws UnsupportedEncodingException { + + UUID uuid = UUIDGenerator.generateType5UUID("baeldung.com"); + + assertEquals("a3c27ab0-2b46-55ef-b50e-0e5c57bfea94", uuid.toString()); + assertEquals(5, uuid.version()); + assertEquals(2, uuid.variant()); + } } \ No newline at end of file