it-swarm.com.de

PHP Funktion zum Erzeugen von UUID der Version 4

Ich habe also etwas herumgraben und versucht, eine Funktion zusammenzustellen, die eine gültige v4-UUID in PHP generiert. Dies ist das nähste, zu dem ich gekommen bin. Mein Wissen in Hex, Dezimal, Binär, den bitweisen Operatoren von PHP und ähnlichem ist fast nicht vorhanden. Diese Funktion generiert eine gültige v4-UUID bis zu einem Bereich. Eine v4-UUID sollte folgende Form haben:

xxxxxxxx-xxxx - 4 xxx - y xxx-xxxxxxxxxxxx

wobei y 8, 9, A oder B ist. Hier versagen die Funktionen, da sie sich nicht daran halten.

Ich hatte gehofft, dass jemand mit mehr Wissen als ich in diesem Bereich mir helfen kann und mir helfen kann, diese Funktion zu korrigieren, damit diese Regel eingehalten wird.

Die Funktion ist wie folgt:

<?php

function gen_uuid() {
 $uuid = array(
  'time_low'  => 0,
  'time_mid'  => 0,
  'time_hi'  => 0,
  'clock_seq_hi' => 0,
  'clock_seq_low' => 0,
  'node'   => array()
 );

 $uuid['time_low'] = mt_Rand(0, 0xffff) + (mt_Rand(0, 0xffff) << 16);
 $uuid['time_mid'] = mt_Rand(0, 0xffff);
 $uuid['time_hi'] = (4 << 12) | (mt_Rand(0, 0x1000));
 $uuid['clock_seq_hi'] = (1 << 7) | (mt_Rand(0, 128));
 $uuid['clock_seq_low'] = mt_Rand(0, 255);

 for ($i = 0; $i < 6; $i++) {
  $uuid['node'][$i] = mt_Rand(0, 255);
 }

 $uuid = sprintf('%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x',
  $uuid['time_low'],
  $uuid['time_mid'],
  $uuid['time_hi'],
  $uuid['clock_seq_hi'],
  $uuid['clock_seq_low'],
  $uuid['node'][0],
  $uuid['node'][1],
  $uuid['node'][2],
  $uuid['node'][3],
  $uuid['node'][4],
  $uuid['node'][5]
 );

 return $uuid;
}

?>

Danke an alle, die mir helfen können.

186
anomareh

Aus this Kommentar zum Handbuch PHP entnommen, könnten Sie Folgendes verwenden:

function gen_uuid() {
    return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
        // 32 bits for "time_low"
        mt_Rand( 0, 0xffff ), mt_Rand( 0, 0xffff ),

        // 16 bits for "time_mid"
        mt_Rand( 0, 0xffff ),

        // 16 bits for "time_hi_and_version",
        // four most significant bits holds version number 4
        mt_Rand( 0, 0x0fff ) | 0x4000,

        // 16 bits, 8 bits for "clk_seq_hi_res",
        // 8 bits for "clk_seq_low",
        // two most significant bits holds zero and one for variant DCE1.1
        mt_Rand( 0, 0x3fff ) | 0x8000,

        // 48 bits for "node"
        mt_Rand( 0, 0xffff ), mt_Rand( 0, 0xffff ), mt_Rand( 0, 0xffff )
    );
}
248
William

Anstatt ihn in einzelne Felder aufzuteilen, ist es einfacher, einen zufälligen Datenblock zu generieren und die einzelnen Bytepositionen zu ändern. Sie sollten auch einen besseren Zufallszahlengenerator als mt_Rand () verwenden.

Nach RFC 4122 - Abschnitt 4.4 müssen Sie folgende Felder ändern:

  1. time_hi_and_version (Bits 4-7 des 7. Oktetts),
  2. clock_seq_hi_and_reserved (Bit 6 und 7 des 9. Oktetts)

Alle anderen 122 Bits sollten ausreichend zufällig sein. 

Der folgende Ansatz erzeugt 128 Bits von Zufallsdaten unter Verwendung von openssl_random_pseudo_bytes() , nimmt die Permutationen für die Oktette vor und verwendet dann bin2hex() und vsprintf() , um die endgültige Formatierung vorzunehmen.

function guidv4($data)
{
    assert(strlen($data) == 16);

    $data[6] = chr(ord($data[6]) & 0x0f | 0x40); // set version to 0100
    $data[8] = chr(ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10

    return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}

echo guidv4(openssl_random_pseudo_bytes(16));

Mit PHP 7 ist die Generierung von zufälligen Bytefolgen noch einfacher mit random_bytes() :

echo guidv4(random_bytes(16));
310
Ja͢ck

Jeder, der composer - Abhängigkeiten verwendet, sollte diese Bibliothek in Betracht ziehen: https://github.com/ramsey/uuid

Einfacher geht es nicht:

Uuid::uuid4();
102
djule5

verwenden Sie auf Unix-Systemen den Systemkern, um eine UUID für Sie zu generieren.

file_get_contents('/proc/sys/kernel/random/uuid')

Kredit Samveen auf https://serverfault.com/a/529319/210994

Note !: Mit dieser Methode erschöpft sich der Entropie-Pool sehr schnell! Ich würde es vermeiden, es dort zu verwenden, wo es häufig aufgerufen würde. 

16
ThorSummoner

Bei meiner Suche nach einer v4-Uuid bin ich zuerst auf diese Seite gekommen und habe diese dann auf http://php.net/manual/de/function.com-create-guid.php gefunden.

function guidv4()
{
    if (function_exists('com_create_guid') === true)
        return trim(com_create_guid(), '{}');

    $data = openssl_random_pseudo_bytes(16);
    $data[6] = chr(ord($data[6]) & 0x0f | 0x40); // set version to 0100
    $data[8] = chr(ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10
    return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}

kredit: pavel.volyntsev

Edit: Zur Verdeutlichung gibt diese Funktion immer eine v4-Uuid (PHP> = 5.3.0).

Wenn die Funktion com_create_guid verfügbar ist (normalerweise nur unter Windows), wird sie verwendet und die geschweiften Klammern entfernt.

Falls nicht vorhanden (Linux), wird auf diese starke Zufallsfunktion openssl_random_pseudo_bytes zurückgegriffen. Anschließend wird sie mit vsprintf in v4 uuid formatiert.

8
Arie

Inspiriert von broofa s Antwort hier .

preg_replace_callback('/[xy]/', function ($matches)
{
  return dechex('x' == $matches[0] ? mt_Rand(0, 15) : (mt_Rand(0, 15) & 0x3 | 0x8));
}
, 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx');

Oder wenn Sie keine anonymen Funktionen verwenden können.

preg_replace_callback('/[xy]/', create_function(
  '$matches',
  'return dechex("x" == $matches[0] ? mt_Rand(0, 15) : (mt_Rand(0, 15) & 0x3 | 0x8));'
)
, 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx');
5
MichaelRushton

Meine Antwort basiert auf Kommentar uniqid Benutzerkommentar , aber es verwendet openssl_random_pseudo_bytes Funktion, um zufällige Zeichenfolgen zu generieren, anstatt aus /dev/urandom

function guid()
{
    $randomString = openssl_random_pseudo_bytes(16);
    $time_low = bin2hex(substr($randomString, 0, 4));
    $time_mid = bin2hex(substr($randomString, 4, 2));
    $time_hi_and_version = bin2hex(substr($randomString, 6, 2));
    $clock_seq_hi_and_reserved = bin2hex(substr($randomString, 8, 2));
    $node = bin2hex(substr($randomString, 10, 6));

    /**
     * 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 = $time_hi_and_version >> 4;
    $time_hi_and_version = $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 = $clock_seq_hi_and_reserved >> 2;
    $clock_seq_hi_and_reserved = $clock_seq_hi_and_reserved | 0x8000;

    return sprintf('%08s-%04s-%04x-%04x-%012s', $time_low, $time_mid, $time_hi_and_version, $clock_seq_hi_and_reserved, $node);
} // guid
5
Victor Smirnov

Nachdem ich genau das Gleiche gesucht und fast eine Version davon selbst implementiert hatte, hielt ich es für erwähnenswert, wenn Sie dies in einem tun. WordPress Framework, WP) hat eine eigene super-praktische Funktion für genau dies:

$myUUID = wp_generate_uuid4();

Sie können die Beschreibung und die Quelle lesen hier .

2
indextwo

Wenn Sie CakePHP verwenden, können Sie die Methode CakeText::uuid(); der Klasse CakeText verwenden, um eine RFC4122-Uuid zu generieren.

2
bish

Eine kleine Variation von Jacks Antwort , um Unterstützung für PHP <7 hinzuzufügen:

// Get an RFC-4122 compliant globaly unique identifier
function get_guid() {
    $data = PHP_MAJOR_VERSION < 7 ? openssl_random_pseudo_bytes(16) : random_bytes(16);
    $data[6] = chr(ord($data[6]) & 0x0f | 0x40);    // Set version to 0100
    $data[8] = chr(ord($data[8]) & 0x3f | 0x80);    // Set bits 6-7 to 10
    return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}
1
Danny Beckett

Wie wäre es, wenn Sie mit mysql die uuid für Sie generieren?

$conn = new mysqli($servername, $username, $password, $dbname, $port);

$query = 'SELECT UUID()';
echo $conn->query($query)->fetch_row()[0];
1
Hoan

Von Tom auf http://www.php.net/manual/de/function.uniqid.php

$r = unpack('v*', fread(fopen('/dev/random', 'r'),16));
$uuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
    $r[1], $r[2], $r[3], $r[4] & 0x0fff | 0x4000,
    $r[5] & 0x3fff | 0x8000, $r[6], $r[7], $r[8])
1
amgine

Ich bin mir sicher, dass es eine elegantere Möglichkeit gibt, die Umwandlung von binär in dezimal für die 4xxx- und yxxx-Teile vorzunehmen. Wenn Sie jedoch openssl_random_pseudo_bytes als crytographisch sicheren Nummerngenerator verwenden möchten, verwende ich Folgendes:

return sprintf('%s-%s-%04x-%04x-%s',
    bin2hex(openssl_random_pseudo_bytes(4)),
    bin2hex(openssl_random_pseudo_bytes(2)),
    hexdec(bin2hex(openssl_random_pseudo_bytes(2))) & 0x0fff | 0x4000,
    hexdec(bin2hex(openssl_random_pseudo_bytes(2))) & 0x3fff | 0x8000,
    bin2hex(openssl_random_pseudo_bytes(6))
    );
0
Baracus