如何在 Java 中制作 Type 5 UUID?
How to make a Type 5 UUID in Java?
在 python 中,要创建 Type 5 UUID,我们可以简单地执行以下操作:
import uuid
print uuid.uuid5(uuid.NAMESPACE_URL, 'my string')
查看 java documentation for java.util.UUID,我不知道该怎么做。首先,没有提到类型 5。他们确实有 Type 3,但签名是:
nameUUIDFromBytes(byte[] name)
Static factory to retrieve a type 3 (name based) UUID based on the specified byte array.
我们如何在 Java 中创建 Type 5 UUID?
您可以按照中提出的代码自行实现。
然而,这确实需要一些摆弄,因为 j.u.UUID 构造函数需要很长时间。
从 Java 8
开始,标准库似乎不支持类型 5。但是像“Apache Commons Id”这样的第三方库有支持它的 UUID 实现。
编辑:这是一个功能齐全的实现:
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;
}
}
为了验证它是否有效,我 运行 下面的代码:
public static void main(String[] args) {
UUID test = UUIDType5.nameUUIDFromNamespaceAndString(NAMESPACE_URL, "google.com");
System.out.println(test);
System.out.println(test.version());
}
这创建了输出:
fedb2fa3-8f5c-5189-80e6-f563dd1cb8f9
5
根据官方 python 实现验证:
>>> print(uuid.uuid5(uuid.NAMESPACE_URL, 'google.com'))
fedb2fa3-8f5c-5189-80e6-f563dd1cb8f9
如果其他人需要生成版本 5 UUID 的库。
UUID uuid = UuidCreator.getNameBasedSha1("google.com");
UUID uuid = UuidCreator.getNameBasedSha1(UuidCreator.NAMESPACE_URL, "google.com");
在 python 中,要创建 Type 5 UUID,我们可以简单地执行以下操作:
import uuid
print uuid.uuid5(uuid.NAMESPACE_URL, 'my string')
查看 java documentation for java.util.UUID,我不知道该怎么做。首先,没有提到类型 5。他们确实有 Type 3,但签名是:
nameUUIDFromBytes(byte[] name)
Static factory to retrieve a type 3 (name based) UUID based on the specified byte array.
我们如何在 Java 中创建 Type 5 UUID?
您可以按照中提出的代码自行实现。 然而,这确实需要一些摆弄,因为 j.u.UUID 构造函数需要很长时间。
从 Java 8
开始,标准库似乎不支持类型 5。但是像“Apache Commons Id”这样的第三方库有支持它的 UUID 实现。
编辑:这是一个功能齐全的实现:
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;
}
}
为了验证它是否有效,我 运行 下面的代码:
public static void main(String[] args) {
UUID test = UUIDType5.nameUUIDFromNamespaceAndString(NAMESPACE_URL, "google.com");
System.out.println(test);
System.out.println(test.version());
}
这创建了输出:
fedb2fa3-8f5c-5189-80e6-f563dd1cb8f9
5
根据官方 python 实现验证:
>>> print(uuid.uuid5(uuid.NAMESPACE_URL, 'google.com'))
fedb2fa3-8f5c-5189-80e6-f563dd1cb8f9
如果其他人需要生成版本 5 UUID 的库。
UUID uuid = UuidCreator.getNameBasedSha1("google.com");
UUID uuid = UuidCreator.getNameBasedSha1(UuidCreator.NAMESPACE_URL, "google.com");