The GUID generation algorithm is recorded in the GUID itself, checking the variant and (optionally) the version. Wikipedia gives a good rundown: first, GUID Variants.
Variant is indicated by the initial bits of the 9th octet, "pinned" to 0
, 10
, 110
or 111
. Using
string show(Guid g) => $"{g}: fam {Convert.ToString(g.ToByteArray()[8], 2)}";
show(Guid.NewGuid())
we might get "1b579ecd-b72c-4550-b10b-f8dd41699ac1: fam 10110001"
. The family is pinned to 10
, OSF DCE UUID or variant 2. This variant defines a version, held in the more significant "nibble" of the 7th octet.
BUT, variant 2, being an MS format is little-endian. Let's take a look with another quick method:
void SeeOrder(Guid g) => Console.WriteLine($"{g}\n{g:N}\n{string.Join("", g.ToByteArray().Select(b => $"{b:x2}"))}");
shows something like
dd3f9bdf-ba47-4411-84c8-6cfcc5d39bb5
dd3f9bdfba47441184c86cfcc5d39bb5
df9b3fdd47ba114484c86cfcc5d39bb5
The first three integer groups are transposed—two for time, one reserved; 32, 16 and 16 bits respectively. The last two groups are not, because the last 8 octets are a "string": 1 reserved octet (where the "family" is represented) and 7 "node" octets. So the 7th version octet is actually encoded as the 8th (index 7).
Expanding show
to highlight the version:
string show(Guid g) => $"{g}: fam {Convert.ToString(g.ToByteArray()[8], 2)}, ver {g.ToByteArray()[7].ToString("x")}";
We'll get "154573de-d420-433b-bb25-aff50590038b: fam 10111011, ver 43"
. The nibble in question is the 4
, thus version 4: pseudo-random generation.