Fix RandomNodeProvider behavior on 32-bit systems

The 6 bytes obtained from `random_bytes()` is a 48-bit integer, which
cannot be converted to decimal on a 32-bit system, without being
implicitly cast to a float by PHP. This was causing problems with
setting the multicast bit, and it led to non-random node values.

This new approach splits the 6 bytes up into two 3-byte values, each a
24-bit integer, and applies the multicast bit to the most significant
bits before re-combining the bytes as a string.
This commit is contained in:
Ben Ramsey
2019-11-30 20:26:42 -08:00
parent 8fde15adcc
commit 692175901d
2 changed files with 45 additions and 22 deletions
+17 -3
View File
@@ -33,11 +33,25 @@ class RandomNodeProvider implements NodeProviderInterface
*/
public function getNode()
{
$node = hexdec(bin2hex(random_bytes(6)));
$nodeBytes = random_bytes(6);
// Split the node bytes for math on 32-bit systems.
$nodeMsb = substr($nodeBytes, 0, 3);
$nodeLsb = substr($nodeBytes, 3);
// Set the multicast bit; see RFC 4122, section 4.5.
$node = $node | 0x010000000000;
$nodeMsb = hex2bin(
str_pad(
dechex(hexdec(bin2hex($nodeMsb)) | 0x010000),
6,
'0',
STR_PAD_LEFT
)
);
return str_pad(dechex($node), 12, '0', STR_PAD_LEFT);
// Recombine the node bytes.
$node = $nodeMsb . $nodeLsb;
return str_pad(bin2hex($node), 12, '0', STR_PAD_LEFT);
}
}