V4 UUID oluşturmak için PHP işlevi

6 Cevap php

Yani etrafta kazma bazı yapıyor oldum ve ben PHP geçerli v4 UUID üreten bir işlevi bir araya getirmek için çalışıyorum. Bu benim gelmek mümkün oldum yakın. Onaltılık, onluk, ikili, PHP'nin bitsel operatörleri ve benzeri bilgim neredeyse olmayan. Bu fonksiyon bir alana kadar geçerli bir v4 UUID yukarı oluşturur. A v4 UUID şeklinde olması gerekir:

xxxxxxxx-xxxx-4 xxx-y xxx-xxxxxxxxxxxx

y 8, 9, A, B ya da bu yapışmayan olarak işlev başarısız budur olduğu.

Ben bu alanda benden daha fazla bilgiye sahip birisi bana bir el ödünç ve bu kurala uymak bu yüzden bana bu fonksiyonu düzeltmek yardımcı olabilir umuyordum.

Aşağıdaki gibi fonksiyon:

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

?>

Bana yardımcı olabilecek herkese teşekkürler.

6 Cevap

PHP kılavuzda this Yorumlarınız alınan, bu kullanabilirsiniz:

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

Bunun yerine bireysel alanlara aşağı kırma, bu veri rastgele bir blok oluşturmak ve bireysel bayt pozisyonları değiştirmek daha kolay. Ayrıca mt_rand daha iyi bir rasgele sayı üreteci () kullanmalısınız.

Göre RFC 4122 - Section 4.4, bu alanları değiştirmek gerekir:

  1. time_hi_and_version (bit 7 sekizlisinin 4-7),
  2. clock_seq_hi_and_reserved (bit 6 ve 9 sekizlisinin 7)

Diğer 122 bit her yeterince rastgele olmalıdır.

Aşağıdaki yaklaşım son biçimlendirme yapmak openssl_random_pseudo_bytes() , makes the permutations on the octets and then uses bin2hex() and vsprintf() kullanarak rasgele veri 128 bit üretir.

function guidv4()
{
    $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));
}

Benim cevabım Yorumlarınız uniqid user comment dayalı, ancak bunun yerine /dev/urandom okuma rasgele dize oluşturmak için openssl_random_pseudo_bytes işlevini kullanır

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

broofa 's cevap esinlenerek here.

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

Veya anonim fonksiyonları kullanmak mümkün eğer.

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

Tom itibaren, 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])

Unix sistemleri sizin için bir uuid üretilemedi sistemini kernal kullanın.

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

http://serverfault.com/a/529319/210994 Kredi Samveen

Note!: Using this method to get a uuid does in fact exhaust the entropy pool, very quickly! I would avoid using this where it would be called frequently.