UUID v4
128ビットの数値
通常は16進数でxxxxxxxx-xxxx-xxxx-Nxxx-xxxxxxxxxxxxの形式で表現される
バージョン4は乱数によって生成される
データレイアウト
4.1.2項にレイアウトの仕様が書かれている。
table:レイアウト
Field Data Type Octet Note
time_low unsigned32 0-3 The low field of the bit integer timestamp
time_mid unsigned16 4-5 The middle field of the bit integer timestamp
time_hi_and_version unsigned16 6-7 The high field of the bit integer timestamp multiplexed with the version number
clock_seq_hi_and_reserved unsigned8 8 The high field of the bit integer clock sequence multiplexed with the variant
clock_seq_low unsigned8 9 The low field of the clock sequence
node unsigned8 10-15 The spatially unique bit integer node identifier
これをCの構造体にしたのが次
code:c
struct UUID {
uint32_t time_low;
uint16_t time_mid;
uint16_t time_hi_and_version;
uint8_t clock_seq_hi_and_reserved;
uint8_t clock_seq_low;
};
アルゴリズム
4.4項にアルゴリズムが説明されている。
clock_seq_hi_and_reservedの上位2ビットに01をセット
time_hi_and_versionの上位4ビットに4.1.3項に記述されている4ビットのバージョン番号(0100)をセット
その他の全てのビットは乱数をセットする
要するに、128ビット(16バイト)の乱数を生成して、6オクテット目の上位4ビットに0100、8オクテット目の上位2ビットに01をセットすれば良い。
C実装
code:c
void
uuid_generate_random(uuid_t out)
{
read_random(out, sizeof(uuid_t));
out6 = (out6 & 0x0F) | 0x40; out8 = (out8 & 0x3F) | 0x80; }
code:c
typedef __darwin_uuid_t uuid_t;
code:c
typedef unsigned char __darwin_uuid_t16; 6オクテット目と8オクテット目のビット操作をしているだけなのがわかる。
JS実装
JavaScriptでランダムなバイト列を生成は、window.crypto.getRandomValues(typedArray) を使うのがはやい
code:js
function uuid4() {
var uu = new Uint8Array(16);
window.crypto.getRandomValues(uu);
uu6 = (uu6 & 0x0F) | 0x40; uu8 = (uu8 & 0x3F) | 0x80; return uu;
};
これだとUint8Arrayなので、文字列に変換するのが次の関数
code:js
var ascii = '0123456789abcdef';
var hex = new Array(256);
for (var i = 0; i < 256; i++) {
}
function unparse(uu) {
var i = 0;
return [
].join('');
};