summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathaniel Catchpole2016-03-07 02:24:46 (GMT)
committerNathaniel Catchpole2016-03-07 02:25:21 (GMT)
commit424515ef183a39b6a6ddfeebc4ff0982d34a3868 (patch)
tree7bbf3904aaa9d51fecceec4e63e3e60744d836c1
parent0fa19e0a2c4457155a8c0e685846d4e19a55dc56 (diff)
Issue #2179537 by jweowu, alexpott: Drupal 8 has a broken UUID generator
-rw-r--r--core/lib/Drupal/Component/Uuid/Php.php55
1 files changed, 33 insertions, 22 deletions
diff --git a/core/lib/Drupal/Component/Uuid/Php.php b/core/lib/Drupal/Component/Uuid/Php.php
index 08c5261..c56f6b4 100644
--- a/core/lib/Drupal/Component/Uuid/Php.php
+++ b/core/lib/Drupal/Component/Uuid/Php.php
@@ -10,11 +10,10 @@ namespace Drupal\Component\Uuid;
use Drupal\Component\Utility\Crypt;
/**
- * Generates a UUID v4 using PHP code.
+ * Generates a UUID v4 (RFC 4122 section 4.4) using PHP code.
*
- * Loosely based on Ruby's UUIDTools generate_random logic.
- *
- * @see http://uuidtools.rubyforge.org/api/classes/UUIDTools/UUID.html
+ * @see http://www.rfc-editor.org/rfc/rfc4122.txt
+ * @see http://www.rfc-editor.org/errata_search.php?rfc=4122&eid=3546
*/
class Php implements UuidInterface {
@@ -22,27 +21,39 @@ class Php implements UuidInterface {
* {@inheritdoc}
*/
public function generate() {
- $hex = substr(hash('sha256', Crypt::randomBytes(16)), 0, 32);
-
- // The field names refer to RFC 4122 section 4.1.2.
+ // Obtain a random string of 32 hex characters.
+ $hex = bin2hex(Crypt::randomBytes(16));
+
+ // The variable names $time_low, $time_mid, $time_hi_and_version,
+ // $clock_seq_hi_and_reserved, $clock_seq_low, and $node correlate to
+ // the fields defined in RFC 4122 section 4.1.2.
+ //
+ // Use characters 0-11 to generate 32-bit $time_low and 16-bit $time_mid.
$time_low = substr($hex, 0, 8);
$time_mid = substr($hex, 8, 4);
- $time_hi_and_version = base_convert(substr($hex, 12, 4), 16, 10);
- $time_hi_and_version &= 0x0FFF;
- $time_hi_and_version |= (4 << 12);
-
- $clock_seq_hi_and_reserved = base_convert(substr($hex, 16, 4), 16, 10);
- $clock_seq_hi_and_reserved &= 0x3F;
- $clock_seq_hi_and_reserved |= 0x80;
-
- $clock_seq_low = substr($hex, 20, 2);
- $nodes = substr($hex, 20);
-
- $uuid = sprintf('%s-%s-%04x-%02x%02x-%s',
- $time_low, $time_mid,
- $time_hi_and_version, $clock_seq_hi_and_reserved,
- $clock_seq_low, $nodes);
+ // Use characters 12-15 to generate 16-bit $time_hi_and_version.
+ // The 4 most significant bits are the version number (0100 == 0x4).
+ // We simply skip character 12 from $hex, and concatenate the strings.
+ $time_hi_and_version = '4' . substr($hex, 13, 3);
+
+ // Use characters 16-17 to generate 8-bit $clock_seq_hi_and_reserved.
+ // The 2 most significant bits are set to one and zero respectively.
+ $clock_seq_hi_and_reserved = base_convert(substr($hex, 16, 2), 16, 10);
+ $clock_seq_hi_and_reserved &= 0b00111111;
+ $clock_seq_hi_and_reserved |= 0b10000000;
+
+ // Use characters 18-19 to generate 8-bit $clock_seq_low.
+ $clock_seq_low = substr($hex, 18, 2);
+ // Use characters 20-31 to generate 48-bit $node.
+ $node = substr($hex, 20);
+
+ // Re-combine as a UUID. $clock_seq_hi_and_reserved is still an integer.
+ $uuid = sprintf('%s-%s-%s-%02x%s-%s',
+ $time_low, $time_mid, $time_hi_and_version,
+ $clock_seq_hi_and_reserved, $clock_seq_low,
+ $node
+ );
return $uuid;
}