Getting an UUID on a *NIX System edit
There are some problems with getting the UUID (type 4) on *NIX systems. For one they are not really random.Because of this I created the following function:proc getUUIDNix {{secure False}} {
set fortyeightBits [expr {2 ** 48 - 1}]
set sixteenBits [expr {2 ** 16 - 1}]
set thirtytwoBits [expr {2 ** 32 - 1}]
set twelfBits [expr {2 ** 12 - 1}]
format %.8x-%.4x-4%.3x-%x%.3x-%.12x \
[getRandomIntInRangeNix 0 $thirtytwoBits] \
[getRandomIntInRangeNix 0 $sixteenBits] \
[getRandomIntInRangeNix 0 $twelfBits] \
[getRandomIntInRangeNix 8 11] \
[getRandomIntInRangeNix 0 $twelfBits] \
[getRandomIntInRangeNix 0 $fortyeightBits False True]
}It uses getRandomIntInRangeNix from Random Integers.A Better wayThe above version is a straight implementation. But a more efficient implementation is:# An UUID is built from 5 hex strings connected by a '-'.
# Their lengths are 8, 4, 4, 4 and 12.
# With version 4 the folowing is necessary:
# - The first digit from the third string is a 4
# - The first digit from the fourth string is 8, 9, A or B.
# The five random hex strings are generated.
# The first digits of the third and fourth strings are changed.
# The UUID is build from the five strings and returned.
# Because binary scan returns lowercase letters toupper is used.
proc getUUIDNix {} {
binary scan [getRandomBytesNix 16] H8H4H4H4H12 hex1 hex2 hex3 hex4 hex5
set hex3 [string replace $hex3 0 0 4]
set oldVal [scan [string index $hex4 0] %x]
set newVal [format %X [expr {($oldVal & 3) | 8}]]
set hex4 [string replace $hex4 0 0 $newVal]
string toupper $hex1-$hex2-$hex3-$hex4-$hex5
}This uses getRandomBytesNix from Get Random Bytes on *NIX.As always: comments, tips and questions are appreciated.
See also edit
- UUID for other implementations

