J'ai donc fouillé un peu et essayé de rassembler une fonction générant un UUID v4 valide en PHP. C'est le plus proche que j'ai pu venir. Mes connaissances en hexadécimal, décimal, binaire, les opérateurs de bits au format PHP et autres sont presque inexistantes. Cette fonction génère un UUID v4 valide jusqu'à une zone. Un UUID v4 devrait être sous la forme de:
xxxxxxxx-xxxx - 4 xxx - y xxx-xxxxxxxxxxxx
où y est égal à 8, 9, A ou B. Les fonctions échouent car elles n'adhèrent pas à cela.
J'espérais que quelqu'un ayant plus de connaissances que moi dans ce domaine pourrait me donner un coup de main et m'aider à réparer 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.
Tiré de this commentez le manuel de 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 )
);
}
Au lieu de les décomposer en champs individuels, il est plus facile de générer un bloc de données aléatoire et de modifier les positions des octets individuels. Vous devriez également utiliser un meilleur générateur de nombres aléatoires que mt_Rand ().
Selon RFC 4122 - Section 4.4 , vous devez modifier ces champs:
time_hi_and_version
(bits 4 à 7 du 7ème octet),clock_seq_hi_and_reserved
(bits 6 et 7 du 9ème octet)Les 122 autres bits doivent être suffisamment aléatoires.
L'approche suivante génère 128 bits de données aléatoires à l'aide de openssl_random_pseudo_bytes()
, effectue les permutations sur les octets, puis utilise bin2hex()
et vsprintf()
pour effectuer 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 avec random_bytes()
:
echo guidv4(random_bytes(16));
Si vous utilisez des dépendances composer, vous pouvez envisager cette bibliothèque: https://github.com/ramsey/uuid
Cela ne devient pas plus facile que cela:
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édit Samveen sur https://serverfault.com/a/529319/210994
Note !: L'utilisation de cette méthode pour obtenir un uuid épuise le pool d'entropie très rapidement! Je voudrais éviter d'utiliser ceci où il serait appelé fréquemment.
Dans ma recherche d’une création de vuid u4, j’ai commencé par cette page, puis j’ai trouvé ceci sur http://php.net/manual/fr/function.com-create-guid.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 uuid v4 (PHP> = 5.3.0).
Lorsque la fonction com_create_guid est disponible (généralement sous Windows), elle l'utilise et supprime les accolades.
S'il n'est pas présent (Linux), il aura recours à cette fonction aléatoire fort openssl_random_pseudo_bytes, il utilisera ensuite vsprintf pour le formater en v4 uuid.
Inspiré par la réponse de broofa _ { 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 si impossible 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');
Ma réponse est basée sur comment commentaire utilisateur uniqid mais il utilise openssl_random_pseudo_bytes function pour générer une chaîne aléatoire au lieu de lire /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 vous utilisez CakePHP
, vous pouvez utiliser leur méthode CakeText::uuid();
à partir de CakeText class pour générer un RFU4122 uuid.
Une légère variation sur La réponse de Jack pour ajouter le support pour 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));
}
Pourquoi ne pas 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];
De tom, sur http://www.php.net/manual/en/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])
Je suis sûr qu'il existe un moyen plus élégant de convertir les valeurs binaires en décimales pour les portions 4xxx
et yxxx
. Mais si vous voulez utiliser openssl_random_pseudo_bytes
comme générateur de nombre sécurisé sur le plan de la cryptographie, voici 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))
);