8000 [Uid] make UUIDv6 always return truly random nodes to prevent leaking… · symfony/symfony@86f566e · GitHub
[go: up one dir, main page]

Skip to content

Commit 86f566e

Browse files
[Uid] make UUIDv6 always return truly random nodes to prevent leaking the MAC of the host
1 parent 6349a1b commit 86f566e

File tree

3 files changed

+31
-0
lines changed

3 files changed

+31
-0
lines changed

src/Symfony/Component/Uid/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
5.2.0
5+
-----
6+
7+
* made UUIDv6 always return truly random node fields to prevent leaking the MAC of the host
8+
49
5.1.0
510
-----
611

src/Symfony/Component/Uid/Tests/UuidTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@ public function testV6()
8989
$this->assertSame('3499710062d0', $uuid->getNode());
9090
}
9191

92+
public function testV6IsSeeded()
93+
{
94+
$uuidV1 = Uuid::v1();
95+
$uuidV6 = Uuid::v6();
96+
97+
$this->assertNotSame(substr($uuidV1, 24), substr($uuidV6, 24));
98+
}
99+
92100
public function testBinary()
93101
{
94102
$uuid = new UuidV4(self::A_UUID_V4);

src/Symfony/Component/Uid/UuidV6.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
/**
1515
* A v6 UUID is lexicographically sortable and contains a 60-bit timestamp and 62 extra unique bits.
1616
*
17+
* Unlike UUIDv1, this implementation of UUIDv6 doesn't leak the MAC address of the host.
18+
*
1719
* @experimental in 5.1
1820
*
1921
* @author Nicolas Grekas <p@tchwork.com>
@@ -22,11 +24,27 @@ class UuidV6 extends Uuid
2224
{
2325
protected const TYPE = 6;
2426

27+
private static $seed;
28+
2529
public function __construct(string $uuid = null)
2630
{
2731
if (null === $uuid) {
2832
$uuid = uuid_create(\UUID_TYPE_TIME);
2933
$this->uid = substr($uuid, 15, 3).substr($uuid, 9, 4).$uuid[0].'-'.substr($uuid, 1, 4).'-6'.substr($uuid, 5, 3).substr($uuid, 18);
34+
35+
// uuid_create() returns a stable "node" that can leak the MAC of the host, but
36+
// UUIDv6 prefers a truly random number here, let's XOR both to preserve the entropy
37+
38+
if (null === self::$seed) {
39+
self::$seed = [random_int(0, 0xffffff), random_int(0, 0xffffff)];
40+
}
41+
42+
$node = unpack('N2', hex2bin('00'.substr($uuid, 24, 6)).hex2bin('00'.substr($uuid, 30)));
43+
44+
$this->uid = substr_replace($this->uid, sprintf('%06x%06x',
45+
(self::$seed[0] ^ $node[1]) | 0x010000,
46+
self::$seed[1] ^ $node[2]
47+
), 24);
3048
} else {
3149
parent::__construct($uuid);
3250
}

0 commit comments

Comments
 (0)
0