1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/**
 * Generates a Universally Unique IDentifier, version 4.
 * 
 * This function generates a truly random UUID. The built in CakePHP function String::uuid()
 * is not cryptographically secure. You should uses this function instead.
 * 
 * @see http://tools.ietf.org/html/rfc4122#section-4.4
 * @see http://en.wikipedia.org/wiki/UUID
 * @return string A UUID, made up of 32 hex digits and 4 hyphens.
 */
public function uuidSecure() {
	
	$pr_bits = null;
	$fp = @fopen('/dev/urandom','rb');
	if ($fp !== false) {
		$pr_bits = @fread($fp, 16);
		@fclose($fp);
	} else {
		$this->cakeError('randomNumber');
	}
	
	/*
	 * To minimize confusion about bit assignments within octets, the UUID
	 * record definition is defined only in terms of fields that are
	 * integral numbers of octets. The fields are presented with the most
	 * significant one first.
	 * @see http://tools.ietf.org/html/rfc4122#section-4.1.2
	 */
	$time_low = bin2hex(substr($pr_bits, 0, 4)); // Octet 0-3
	$time_mid = bin2hex(substr($pr_bits, 4, 2)); // Octet 4-5
	$time_hi_and_version = bin2hex(substr($pr_bits, 6, 2)); // Octet 6-7
	$clock_seq_hi_and_reserved = bin2hex(substr($pr_bits, 8, 1)); // Octet 8
	$clock_seq_low = bin2hex(substr($pr_bits, 9, 1)); // Octet 9
	$node = bin2hex(substr($pr_bits, 10, 6)); // Octet 10-15
	
	/*
	 * Set the four most significant bits (bits 12 through 15) of the
	 * time_hi_and_version field to the 4-bit version number from
	 * Section 4.1.3.
	 * @see http://tools.ietf.org/html/rfc4122#section-4.1.3
	 */
	$time_hi_and_version = hexdec($time_hi_and_version);
	$time_hi_and_version >>= 4;
	$time_hi_and_version |= 0x4000;
	
	/*
	 * Set the two most significant bits (bits 6 and 7) of the
	 * clock_seq_hi_and_reserved to zero and one, respectively.
	 */
	$clock_seq_hi_and_reserved = hexdec($clock_seq_hi_and_reserved);
	$clock_seq_hi_and_reserved >>= 2;
	$clock_seq_hi_and_reserved |= 0x80;
	
	return sprintf('%08s-%04s-%04x-%02x%02s-%012s',
		$time_low, $time_mid, $time_hi_and_version, $clock_seq_hi_and_reserved, $clock_seq_low, $node);
}