Question

J'ai donc fait des fouilles et j'ai essayé de reconstituer une fonction qui génère un V4 UUID valide en PHP. C'est le plus proche que j'ai pu venir. Mes connaissances dans les opérateurs hexadécimaux, décimaux, binaires, de PHP, et autres sont presque non existants. Cette fonction génère un V4 UUID valide jusqu'à une zone. Un v4 uuid doit être sous la forme de:

xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxx

y est 8, 9, A ou B. C'est là que les fonctions échouent car elle n'adhère pas à cela.

J'espérais que quelqu'un avec plus de connaissances que moi dans ce domaine pourrait me donner un coup de main et m'aider à régler cette fonction afin qu'elle respecte cette règle.

La fonction est la suivante:

<?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;
}

?>

Merci à tous ceux qui peuvent m'aider.

Était-ce utile?

La solution

Pris à partir de cette Commentez le manuel PHP, vous pouvez utiliser ceci:

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 )
    );
}

Autres conseils

Au lieu de le décomposer en champs individuels, il est plus facile de générer un bloc aléatoire de données et de modifier les positions d'octets individuelles. Vous devez également utiliser un meilleur générateur de nombres aléatoires que mt_rand ().

Selon RFC 4122 - Section 4.4, vous devez changer ces champs:

  1. time_hi_and_version (bits 4-7 du 7e octet),
  2. clock_seq_hi_and_reserved (Bit 6 et 7 du 9e octet)

Tous les 122 autres bits devraient être suffisamment aléatoires.

L'approche suivante génère 128 bits de données aléatoires en utilisant openssl_random_pseudo_bytes(), fait les permutations sur les octets puis utilise bin2hex() et vsprintf() Pour faire le formatage final.

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));

Avec PHP 7, la génération de séquences d'octets aléatoires est encore plus simple en utilisant random_bytes():

function guidv4($data = null)
{
    $data = $data ?? random_bytes(16);
    // ...
}

Quiconque utilise compositeur dépendances, vous voudrez peut-être considérer cette bibliothèque: https://github.com/ramsey/uuid

Cela ne devient pas plus facile que ceci:

Uuid::uuid4();

Sur les systèmes UNIX, utilisez le noyau système pour générer un UUID pour vous.

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

Créditer Samveen sur https://serverfault.com/a/529319/210994

Remarque !: Utilisation de cette méthode pour obtenir un UUID épuise en fait la piscine d'entropie, très rapidement! J'éviterais de l'utiliser là où il serait appelé fréquemment.

Dans ma recherche de création d'un uuid v4, je suis venu d'abord sur cette page, puis j'ai trouvé cela sur http://php.net/manual/en/fonction.com-create-uid.php

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));
}

Crédit: pavel.volyntsev

EDIT: Pour clarifier, cette fonction vous donnera toujours un V4 UUID (php> = 5.3.0).

Lorsque la fonction com_create_guid est disponible (généralement uniquement sous Windows), elle l'utilisera et enlèvera les accolades bouclées.

S'il n'est pas présent (Linux), il se repliera sur cette fonction forte aléatoire OpenSSL_RANDOM_PSEUDO_BYTES, il utilisera alors vsprintf pour le formater en v4 uUID.

Ma réponse est basée sur le commentaire commentaire de l'utilisateur uniqid Mais il utilise openssl_random_pseudo_bytes fonction pour générer une chaîne aléatoire au lieu de lire à partir de /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

Si tu utilises CakePHP vous pouvez utiliser leur méthode CakeText::uuid(); du Caketext classe pour générer un RFC4122 UUID.

Inspiré par broofaLa réponse ici.

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');

Ou s'il est incapable d'utiliser des fonctions anonymes.

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');

Avoir cherché exactement la même chose et presque Implémentant une version de cela moi-même, je pensais que cela valait la peine de le mentionner, si vous faites cela dans un Wordpress Framework, WP a sa propre fonction super-handy pour exactement ceci:

$myUUID = wp_generate_uuid4();

Vous pouvez lire la description et la source ici.

Une légère variation sur La réponse de Jack Pour ajouter la prise en charge de PHP <7:

// 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));
}

De Tom, sur http://www.php.net/manual/en/fonction.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])

Que diriez-vous d'utiliser MySQL pour générer l'UUID pour vous?

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

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

Je suis sûr qu'il existe un moyen plus élégant de faire la conversion du binaire à la décimale pour le 4xxx et yxxx portions. Mais si vous voulez utiliser openssl_random_pseudo_bytes Comme votre générateur de nombres crytographiquement sécurisé, c'est ce que j'utilise:

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))
    );
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top