我想知道是否有一种方法可以基于一个字符串
生成相同的UUID。我尝试使用UUID,但它似乎没有提供此功能。
String aString="JUST_A_TEST_STRING";
String result = UUID.nameUUIDFromBytes(aString.getBytes()).toString();
UUID.nameUUIDFromBytes()
只会生成MD5 UUID。然而,如果不需要向后兼容,建议使用SHA1而非MD5。
下面的实用类可以生成MD5 UUID和SHA-1 UUID。欢迎使用和分享。
package com.example;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;
/**
* Generates UUIDv3 (MD5) and UUIDv5 (SHA1).
*
* It is fully compliant with RFC-4122.
*/
public class HashUuid {
private static final int V3 = 3; // MD5
private static final int V5 = 5; // SHA-1
private static final String HASH_V3 = "MD5";
private static final String HASH_V5 = "SHA-1";
public static final UUID NAMESPACE_DNS = new UUID(0x6ba7b8109dad11d1L, 0x80b400c04fd430c8L);
public static final UUID NAMESPACE_URL = new UUID(0x6ba7b8119dad11d1L, 0x80b400c04fd430c8L);
public static final UUID NAMESPACE_OID = new UUID(0x6ba7b8129dad11d1L, 0x80b400c04fd430c8L);
public static final UUID NAMESPACE_X500 = new UUID(0x6ba7b8149dad11d1L, 0x80b400c04fd430c8L);
public static UUID v3(String name) {
return generate(V3, HASH_V3, null, name);
}
public static UUID v5(String name) {
return generate(V5, HASH_V5, null, name);
}
public static UUID v3(UUID namespace, String name) {
return generate(V3, HASH_V3, namespace, name);
}
public static UUID v5(UUID namespace, String name) {
return generate(V5, HASH_V5, namespace, name);
}
private static UUID generate(int version, String algorithm, UUID namespace, String name) {
MessageDigest hasher = hasher(algorithm);
if (namespace != null) {
ByteBuffer ns = ByteBuffer.allocate(16);
ns.putLong(namespace.getMostSignificantBits());
ns.putLong(namespace.getLeastSignificantBits());
hasher.update(ns.array());
}
hasher.update(name.getBytes(StandardCharsets.UTF_8));
ByteBuffer hash = ByteBuffer.wrap(hasher.digest());
final long msb = (hash.getLong() & 0xffffffffffff0fffL) | (version & 0x0f) << 12;
final long lsb = (hash.getLong() & 0x3fffffffffffffffL) | 0x8000000000000000L;
return new UUID(msb, lsb);
}
private static MessageDigest hasher(String algorithm) {
try {
return MessageDigest.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(String.format("%s not supported.", algorithm));
}
}
/**
* For tests!
*/
public static void main(String[] args) {
UUID namespace = UUID.randomUUID();
String name = "JUST_A_TEST_STRING";
System.out.println(String.format("UUID.nameUUIDFromBytes(): '%s'", UUID.nameUUIDFromBytes(name.getBytes())));
System.out.println();
System.out.println(String.format("HashUuid.v3(name): '%s'", HashUuid.v3(name)));
System.out.println(String.format("HashUuid.v5(name): '%s'", HashUuid.v5(name)));
System.out.println(String.format("HashUuid.v3(namespace, name): '%s'", HashUuid.v3(namespace, name)));
System.out.println(String.format("HashUuid.v5(namespace, name): '%s'", HashUuid.v5(namespace, name)));
}
}
这是输出结果:
UUID.nameUUIDFromBytes(): '9e120341-627f-32be-8393-58b5d655b751'
HashUuid.v3(name): '9e120341-627f-32be-8393-58b5d655b751'
HashUuid.v5(name): 'e4586bed-032a-5ae6-9883-331cd94c4ffa'
HashUuid.v3(namespace, name): 'f0043437-723b-308f-a6c0-74ec36ddf9c2'
HashUuid.v5(namespace, name): '18a45fd8-8fab-5647-aad7-1d3264932180'
或者,您也可以使用uuid-creator
。请参考以下示例:
// Create a UUIDv5 (SHA1)
String name = "JUST_A_TEST_STRING";
UUID uuid = UuidCreator.getNameBasedSha1(name);
建议使用UUID v5。
版本3和版本5的UUID是通过对命名空间标识符和名称进行哈希生成的。版本3使用MD5作为哈希算法,而版本5使用SHA-1。1 - wikipedia
UUID v5需要一个命名空间。该命名空间应该是一个UUID v4,你可以在线生成它。在这里生成。命名空间确保了对于给定的输入,输出将始终相同。
UUID v5的一个可能的实现可以在这里找到:
<!-- https://search.maven.org/artifact/com.github.f4b6a3/uuid-creator -->
<dependency>
<groupId>com.github.f4b6a3</groupId>
<artifactId>uuid-creator</artifactId>
<version>3.6.0</version>
</dependency>
以下是使用方法:
UUID namespace = ; // todo generate a UUID v4.
String input = "input";
UUID uuid = UuidCreator.getNameBasedSha1(namespace, input);
< p > < em >(某种程度上,命名空间的作用类似于种子对于随机数生成器的作用。相比之下,虽然种子应该是随机的,但我们的命名空间是一个常量。这迫使我们的生成器始终为给定的输入产生相同的值。)