|
53 | 53 | import java.net.http.HttpClient;
|
54 | 54 | import java.net.http.HttpRequest;
|
55 | 55 | import java.net.http.HttpResponse;
|
| 56 | +import java.nio.ByteBuffer; |
56 | 57 | import java.nio.charset.Charset;
|
57 | 58 | import java.nio.charset.StandardCharsets;
|
58 | 59 | import java.nio.file.Files;
|
59 | 60 | import java.security.MessageDigest;
|
| 61 | +import java.security.SecureRandom; |
60 | 62 | import java.time.Duration;
|
61 | 63 | import java.util.*;
|
62 | 64 | import java.util.List;
|
|
76 | 78 | * </ul>
|
77 | 79 | */
|
78 | 80 | public class SecurityUtils {
|
79 |
| - |
80 | 81 | /**
|
81 | 82 | * Default constructor: Not needed as the class only provides static methods.
|
82 | 83 | */
|
@@ -1328,4 +1329,54 @@ public static boolean isRegexSafe(String regex, String data, Optional<Integer> m
|
1328 | 1329 | }
|
1329 | 1330 | return isSafe;
|
1330 | 1331 | }
|
| 1332 | + |
| 1333 | + /** |
| 1334 | + * Compute a UUID version 7 without using any external dependency.<br><br> |
| 1335 | + * <b>Below are my personal point of view and perhaps I'm totally wrong!</b> |
| 1336 | + * <br><br> |
| 1337 | + * Why such method? |
| 1338 | + * <ul> |
| 1339 | + * <li>Java <= 21 does not supports natively the generation of an UUID version 7.</li> |
| 1340 | + * <li>Import a library just to generate such value is overkill for me.</li> |
| 1341 | + * <li>Library that I have found, generating such version of an UUID, are not provided by entities commonly used in the java world, such as the SPRING framework provider.</li> |
| 1342 | + * </ul> |
| 1343 | + * <br> |
| 1344 | + * <b>Full credits for this implementation goes to the authors and contributors of the <a href="https://github.com/nalgeon/uuidv7">UUIDv7</a> project.</b> |
| 1345 | + * <br><br> |
| 1346 | + * Below are the java libraries that I have found but, for which, I do not trust enough the provider to use them directly: |
| 1347 | + * <ul> |
| 1348 | + * <li><a href="https://github.com/cowtowncoder/java-uuid-generator">java-uuid-generator</a></li> |
| 1349 | + * <li><a href="https://github.com/f4b6a3/uuid-creator">uuid-creator</a></li> |
| 1350 | + * </ul> |
| 1351 | + * |
| 1352 | + * @return A UUID object representing the UUID v7. |
| 1353 | + * @see "https://uuid7.com/" |
| 1354 | + * @see "https://antonz.org/uuidv7/" |
| 1355 | + * @see "https://mccue.dev/pages/3-11-25-life-altering-postgresql-patterns" |
| 1356 | + * @see "https://www.ietf.org/archive/id/draft-peabody-dispatch-new-uuid-format-04.html#name-uuid-version-7" |
| 1357 | + * @see "https://www.baeldung.com/java-generating-time-based-uuids" |
| 1358 | + * @see "https://en.wikipedia.org/wiki/Universally_unique_identifier" |
| 1359 | + * @see "https://buildkite.com/resources/blog/goodbye-integers-hello-uuids/" |
| 1360 | + */ |
| 1361 | + public static UUID computeUUIDv7() { |
| 1362 | + SecureRandom secureRandom = new SecureRandom(); |
| 1363 | + // Generate truly random bytes |
| 1364 | + byte[] value = new byte[16]; |
| 1365 | + secureRandom.nextBytes(value); |
| 1366 | + // Get current timestamp in milliseconds |
| 1367 | + ByteBuffer timestamp = ByteBuffer.allocate(Long.BYTES); |
| 1368 | + timestamp.putLong(System.currentTimeMillis()); |
| 1369 | + // Create the TIMESTAMP part of the UUID |
| 1370 | + System.arraycopy(timestamp.array(), 2, value, 0, 6); |
| 1371 | + // Create the VERSION and the VARIANT parts of the UUID |
| 1372 | + value[6] = (byte) ((value[6] & 0x0F) | 0x70); |
| 1373 | + value[8] = (byte) ((value[8] & 0x3F) | 0x80); |
| 1374 | + //Create the HIGH and LOW parts of the UUID |
| 1375 | + ByteBuffer buf = ByteBuffer.wrap(value); |
| 1376 | + long high = buf.getLong(); |
| 1377 | + long low = buf.getLong(); |
| 1378 | + //Create and return the UUID object |
| 1379 | + UUID uuidv7 = new UUID(high, low); |
| 1380 | + return uuidv7; |
| 1381 | + } |
1331 | 1382 | }
|
0 commit comments