Skip to content

Instantly share code, notes, and snippets.

@ACatThatPrograms
Last active February 2, 2022 21:08
Show Gist options
  • Save ACatThatPrograms/e767c943fdfa2e265632c1202c471447 to your computer and use it in GitHub Desktop.
Save ACatThatPrograms/e767c943fdfa2e265632c1202c471447 to your computer and use it in GitHub Desktop.
Generate RFC 4122 compliant UUIDv4
/**
* Generate an RFC 4122 compliant v4uuid using window.crypto.getRandomValues
* @returns {String} - A newly generated v4uuid
*/
export function genUuidv4() {
let hex = window.crypto.getRandomValues(new Uint8Array(128 / 8)); // Or your crypto lib of choice -- Slice off the 0x if lib provides it.
let bytes = Buffer.from(hex, 'hex');
// Force byte 7 and 9 to unsigned and pad to 8 bits
let byte7asBin = (bytes[6] >>> 0).toString(2).padStart(8, "0"); // Get byte 7 as binary
let byte9asBin = (bytes[8] >>> 0).toString(2).padStart(8, "0"); // Get byte 9 as binary
// Set High nibble of byte7 to 0100 | 0x04 //
let byte7Bits = byte7asBin.split('');
byte7Bits[0] = "0";
byte7Bits[1] = "1";
byte7Bits[2] = "0";
byte7Bits[3] = "0";
byte7asBin = byte7Bits.join("");
// Set 2 most significant bits of byte9 to 10 //
let byte9Bits = byte9asBin.split('');
byte9Bits[0] = "1";
byte9Bits[1] = "0";
byte9asBin = byte9Bits.join("");
// Inject new bytes //
bytes[6] = parseInt(byte7asBin, 2); // Byte 7 inject
bytes[8] = parseInt(byte9asBin, 2); // Byte 9 inject
let finalHex = bytes.toString('hex');
// Add hyphens for blocks of 8-4-4-4-12 before returning v4uuid
let block1 = finalHex.slice(0, 8);
let block2 = finalHex.slice(8, 12);
let block3 = finalHex.slice(12, 16);
let block4 = finalHex.slice(16, 20);
let block5 = finalHex.slice(20, finalHex.length);
let v4uuid = [block1, block2, block3, block4, block5].join("-").toLowerCase();
return v4uuid;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment