1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.asuite.clearcut.junit.listener; 18 import java.nio.charset.Charset; 19 import java.security.MessageDigest; 20 import java.security.NoSuchAlgorithmException; 21 import java.util.Objects; 22 import java.util.UUID; 23 24 public class UUID5 { 25 private static final Charset UTF8 = Charset.forName("UTF-8"); 26 public static final UUID NAMESPACE_DNS = UUID.fromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8"); 27 public static final UUID NAMESPACE_URL = UUID.fromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8"); 28 public static final UUID NAMESPACE_OID = UUID.fromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8"); 29 public static final UUID NAMESPACE_X500 = UUID.fromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8"); 30 uuidOf(UUID namespace, String name)31 public static UUID uuidOf(UUID namespace, String name) { 32 return uuidOf(namespace, Objects.requireNonNull(name, "name == null").getBytes(UTF8)); 33 } 34 uuidOf(UUID namespace, byte[] name)35 public static UUID uuidOf(UUID namespace, byte[] name) { 36 MessageDigest md; 37 try { 38 md = MessageDigest.getInstance("SHA-1"); 39 } catch (NoSuchAlgorithmException nsae) { 40 throw new InternalError("SHA-1 not supported"); 41 } 42 md.update(toBytes(Objects.requireNonNull(namespace, "namespace is null"))); 43 md.update(Objects.requireNonNull(name, "name is null")); 44 byte[] sha1Bytes = md.digest(); 45 sha1Bytes[6] &= 0x0f; /* clear version */ 46 sha1Bytes[6] |= 0x50; /* set to version 5 */ 47 sha1Bytes[8] &= 0x3f; /* clear variant */ 48 sha1Bytes[8] |= 0x80; /* set to IETF variant */ 49 return fromBytes(sha1Bytes); 50 } 51 fromBytes(byte[] data)52 private static UUID fromBytes(byte[] data) { 53 // Based on the private UUID(bytes[]) constructor 54 long msb = 0; 55 long lsb = 0; 56 assert data.length >= 16; 57 for (int i = 0; i < 8; i++) 58 msb = (msb << 8) | (data[i] & 0xff); 59 for (int i = 8; i < 16; i++) 60 lsb = (lsb << 8) | (data[i] & 0xff); 61 return new UUID(msb, lsb); 62 } 63 toBytes(UUID uuid)64 private static byte[] toBytes(UUID uuid) { 65 // inverted logic of fromBytes() 66 byte[] out = new byte[16]; 67 long msb = uuid.getMostSignificantBits(); 68 long lsb = uuid.getLeastSignificantBits(); 69 for (int i = 0; i < 8; i++) 70 out[i] = (byte) ((msb >> ((7 - i) * 8)) & 0xff); 71 for (int i = 8; i < 16; i++) 72 out[i] = (byte) ((lsb >> ((15 - i) * 8)) & 0xff); 73 return out; 74 } 75 }