Universally Unique Identifiers (UUIDs), also known as GUIDs, are essential for creating unique identifiers in various software applications. Version 4 UUIDs are particularly valuable as they rely on cryptographically secure random numbers, ensuring a high degree of uniqueness. This article provides a robust Apex class, GuidUtil
, along with a test class, to effectively Generate Guid strings that adhere to UUID version 4 standards within the Salesforce environment.
Many approaches to generating GUIDs may fall short by either not using cryptographically secure random number generators or by failing to fully comply with the UUID v4 specifications. The GuidUtil
class addresses these shortcomings, offering a reliable method for developers needing to generate GUID values in Apex.
/* How to generate a version 4 GUID (random) 1. Generate 128 random bits 2. Set the version: Take the 7th byte perform an AND operation with 0x0f followed by an OR operation of 0x40. 3. Set the variant: Take the 9th byte perform an AND operation with 0x3f followed by an OR operation of 0x80. 4. Convert the data to hex and add dashes */ public class GuidUtil { static List<String> hexMap = new List<String> { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; public static String NewGuid() { String randomStringAsHex = EncodingUtil.ConvertTohex(Crypto.GenerateAESKey(128)); String versionHexBits = randomStringAsHex.SubString(14,16); // 7th bit String variantHexBits = randomStringAsHex.SubString(18,20); // 9th bit Integer versionIntBits = convertHexToInt(versionHexBits); Integer variantIntBits = convertHexToInt(variantHexBits); Integer versionShiftedIntBits = versionIntBits & 15 | 64; // (i & 0x0f) | 0x40 Integer variantShiftedIntBits = variantIntBits & 63 | 128; // (i & 0x3f) | 0x80 String versionShiftedHexBits = convertIntToHex(versionShiftedIntBits); // Always begins with 4 String variantShiftedHexBits = convertIntToHex(variantShiftedIntBits); // Always begins with one of 8,9,a,b String guid = randomStringAsHex.SubString(0,8) + '-' + randomStringAsHex.SubString(8,12) + '-' + versionShiftedHexBits + randomStringAsHex.SubString(14,16) + '-' + variantShiftedHexBits + randomStringAsHex.SubString(18,20) + '-' + randomStringAsHex.substring(20); return guid; } static Integer convertHexToInt(String hex) { Integer d0 = hexMap.IndexOf(hex.Substring(1,2)); Integer d1 = hexMap.IndexOf(hex.Substring(0,1)); Integer intval = d0 + (d1*16); return intval; } static String convertIntToHex(Integer intval) { // https://stackoverflow.com/a/13465128 String hs0 = hexMap.Get(intval & 15); // i & 0x0f String hs1 = hexMap.Get(((intval >> 4) & 15)); //(i >> 4) & 0x0f return hs1+hs0; } }
This GuidUtil
class provides the NewGuid()
method, which is the core function to generate GUID. Let’s break down how it works step by step, aligning with the UUID v4 generation process:
-
Generate 128 Random Bits: The process begins by generating 128 bits of cryptographically secure random data using
Crypto.GenerateAESKey(128)
. This ensures a high level of unpredictability, a cornerstone of UUID v4. This random data is then converted into a hexadecimal string representation usingEncodingUtil.ConvertTohex()
. -
Set the Version: For a UUID to be version 4 compliant, specific bits need to indicate the version. The code extracts the 7th byte (characters 14-16 in the hex string) and performs a bitwise AND operation with
0x0f
followed by a bitwise OR operation with0x40
. This operation sets the version bits to ‘0100’, which is the designated pattern for version 4 UUIDs. -
Set the Variant: Similar to the version, the variant field also requires specific bit settings. The 9th byte (characters 18-20 in the hex string) is extracted, and a bitwise AND operation with
0x3f
and a subsequent bitwise OR with0x80
are performed. This sets the variant bits to ’10xx’, as defined for the most common UUID variant (variant 1, also known as the Leach-Salz variant). -
Convert to Hex and Add Dashes: The final step involves assembling the GUID string in the standard UUID format. The code takes substrings from the random hex string, incorporating the modified version and variant hex bits, and inserts hyphens at the conventional positions to produce a UUID string in the format “xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx”, where ‘y’ is determined by the variant bits.
Supporting helper methods, convertHexToInt(String hex)
and convertIntToHex(Integer intval)
, facilitate the bit manipulation by converting between hexadecimal string representations and integer values as needed for setting the version and variant bits.
To ensure the GuidUtil
class correctly generate GUID values that conform to the UUID version 4 standard, a test class GuidUtilSpec
is provided.
@isTest public class GuidUtilSpec { private static testmethod void GuidIsV4() { Pattern p = Pattern.compile('[\w]{8}-[\w]{4}-4[\w]{3}-[89ab][\w]{3}-[\w]{12}'); for(Integer x = 0; x < 100; x++) { Matcher m = p.matcher(GuidUtil.NewGuid()); System.assert(m.matches() == true); } } }
The GuidIsV4()
test method utilizes a regular expression [\w]{8}-[\w]{4}-4[\w]{3}-[89ab][\w]{3}-[\w]{12}
to validate the format of the generated GUID strings. This regex specifically checks for:
- The presence of hyphens in the correct positions.
- That the version character is ‘4’ (enforced by
-4[\w]{3}-
). - That the variant character is one of ‘8’, ‘9’, ‘a’, or ‘b’ (enforced by
-[89ab][\w]{3}-
).
The test iterates 100 times, generating a new GUID in each iteration and asserting that it matches the UUID v4 pattern. This provides a statistically significant verification that the GuidUtil
class reliably generate GUID strings compliant with the version 4 standard.
In conclusion, the GuidUtil
class and its accompanying test offer a complete and verified solution for developers who need to generate GUID values within their Apex code. By leveraging cryptographically secure random number generation and meticulously adhering to the UUID version 4 specifications, this code ensures the creation of unique and standard-compliant identifiers for various application requirements in Salesforce.