Skip to content
Next Next commit
crypto: decompose randomuuid implementation
  • Loading branch information
rangoo94 committed Feb 24, 2021
commit e75bdc25fa461150be9d1abca5093285b9676ec0
124 changes: 61 additions & 63 deletions lib/internal/crypto/random.js
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,56 @@ let uuidNotBuffered;
let uuid;
let uuidBatch = 0;

function serializeUUID(buf) {
if (uuid === undefined) {
uuid = Buffer.alloc(36, '-');
uuid[14] = 52; // '4', identifies the UUID version
}

// This function is structured the way it is for performance.
// The uuid buffer stores the serialization of the random
// bytes from uuidData.
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
uuid[0] = kHexDigits[buf[0] >> 4];
uuid[1] = kHexDigits[buf[0] & 0xf];
uuid[2] = kHexDigits[buf[1] >> 4];
uuid[3] = kHexDigits[buf[1] & 0xf];
uuid[4] = kHexDigits[buf[2] >> 4];
uuid[5] = kHexDigits[buf[2] & 0xf];
uuid[6] = kHexDigits[buf[3] >> 4];
uuid[7] = kHexDigits[buf[3] & 0xf];
// -
uuid[9] = kHexDigits[buf[4] >> 4];
uuid[10] = kHexDigits[buf[4] & 0xf];
uuid[11] = kHexDigits[buf[5] >> 4];
uuid[12] = kHexDigits[buf[5] & 0xf];
// -
// 4, uuid[14] is set already...
uuid[15] = kHexDigits[buf[6] & 0xf];
uuid[16] = kHexDigits[buf[7] >> 4];
uuid[17] = kHexDigits[buf[7] & 0xf];
// -
uuid[19] = kHexDigits[((buf[8] & 0x3f) | 0x80) >> 4]; // Variant byte: 10xxxxxx (variant 1)
uuid[20] = kHexDigits[((buf[8] & 0x3f) | 0x80) & 0xf]; // Variant byte: 10xxxxxx (variant 1)
uuid[21] = kHexDigits[buf[9] >> 4];
uuid[22] = kHexDigits[buf[9] & 0xf];
// -
uuid[24] = kHexDigits[buf[10] >> 4];
uuid[25] = kHexDigits[buf[10] & 0xf];
uuid[26] = kHexDigits[buf[11] >> 4];
uuid[27] = kHexDigits[buf[11] & 0xf];
uuid[28] = kHexDigits[buf[12] >> 4];
uuid[29] = kHexDigits[buf[12] & 0xf];
uuid[30] = kHexDigits[buf[13] >> 4];
uuid[31] = kHexDigits[buf[13] & 0xf];
uuid[32] = kHexDigits[buf[14] >> 4];
uuid[33] = kHexDigits[buf[14] & 0xf];
uuid[34] = kHexDigits[buf[15] >> 4];
uuid[35] = kHexDigits[buf[15] & 0xf];

return uuid.latin1Slice(0, 36);
}

function getBufferedUUID() {
if (uuidData === undefined) {
uuidData = secureBuffer(16 * kBatchSize);
Comment thread
rangoo94 marked this conversation as resolved.
Outdated
Expand All @@ -317,6 +367,16 @@ function getBufferedUUID() {
return uuidData.slice(uuidBatch * 16, (uuidBatch * 16) + 16);
}

function getUnbufferedUUID() {
let uuidBuf = uuidNotBuffered;
if (uuidBuf === undefined)
uuidBuf = uuidNotBuffered = secureBuffer(16);
Comment thread
aduh95 marked this conversation as resolved.
Outdated
if (uuidBuf === undefined)
throw new ERR_OPERATION_FAILED('Out of memory');
randomFillSync(uuidBuf);
return uuidBuf;
}

function randomUUID(options) {
if (options !== undefined)
validateObject(options, 'options');
Expand All @@ -326,69 +386,7 @@ function randomUUID(options) {

validateBoolean(disableEntropyCache, 'options.disableEntropyCache');

if (uuid === undefined) {
uuid = Buffer.alloc(36, '-');
uuid[14] = 52; // '4', identifies the UUID version
}

let uuidBuf;
if (!disableEntropyCache) {
uuidBuf = getBufferedUUID();
} else {
uuidBuf = uuidNotBuffered;
if (uuidBuf === undefined)
uuidBuf = uuidNotBuffered = secureBuffer(16);
if (uuidBuf === undefined)
throw new ERR_OPERATION_FAILED('Out of memory');
randomFillSync(uuidBuf);
}

// Variant byte: 10xxxxxx (variant 1)
uuidBuf[8] = (uuidBuf[8] & 0x3f) | 0x80;

// This function is structured the way it is for performance.
// The uuid buffer stores the serialization of the random
// bytes from uuidData.
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
let n = 0;
uuid[0] = kHexDigits[uuidBuf[n] >> 4];
uuid[1] = kHexDigits[uuidBuf[n++] & 0xf];
uuid[2] = kHexDigits[uuidBuf[n] >> 4];
uuid[3] = kHexDigits[uuidBuf[n++] & 0xf];
uuid[4] = kHexDigits[uuidBuf[n] >> 4];
uuid[5] = kHexDigits[uuidBuf[n++] & 0xf];
uuid[6] = kHexDigits[uuidBuf[n] >> 4];
uuid[7] = kHexDigits[uuidBuf[n++] & 0xf];
// -
uuid[9] = kHexDigits[uuidBuf[n] >> 4];
uuid[10] = kHexDigits[uuidBuf[n++] & 0xf];
uuid[11] = kHexDigits[uuidBuf[n] >> 4];
uuid[12] = kHexDigits[uuidBuf[n++] & 0xf];
// -
// 4, uuid[14] is set already...
uuid[15] = kHexDigits[uuidBuf[n++] & 0xf];
uuid[16] = kHexDigits[uuidBuf[n] >> 4];
uuid[17] = kHexDigits[uuidBuf[n++] & 0xf];
// -
uuid[19] = kHexDigits[uuidBuf[n] >> 4];
uuid[20] = kHexDigits[uuidBuf[n++] & 0xf];
uuid[21] = kHexDigits[uuidBuf[n] >> 4];
uuid[22] = kHexDigits[uuidBuf[n++] & 0xf];
// -
uuid[24] = kHexDigits[uuidBuf[n] >> 4];
uuid[25] = kHexDigits[uuidBuf[n++] & 0xf];
uuid[26] = kHexDigits[uuidBuf[n] >> 4];
uuid[27] = kHexDigits[uuidBuf[n++] & 0xf];
uuid[28] = kHexDigits[uuidBuf[n] >> 4];
uuid[29] = kHexDigits[uuidBuf[n++] & 0xf];
uuid[30] = kHexDigits[uuidBuf[n] >> 4];
uuid[31] = kHexDigits[uuidBuf[n++] & 0xf];
uuid[32] = kHexDigits[uuidBuf[n] >> 4];
uuid[33] = kHexDigits[uuidBuf[n++] & 0xf];
uuid[34] = kHexDigits[uuidBuf[n] >> 4];
uuid[35] = kHexDigits[uuidBuf[n] & 0xf];

return uuid.latin1Slice(0, 36);
return serializeUUID(disableEntropyCache ? getUnbufferedUUID() : getBufferedUUID());
}

function createRandomPrimeJob(type, size, options) {
Expand Down