পিএইচপি ফাংশন ভি 4 ইউআইডি জেনারেট করে


233

সুতরাং আমি কাছাকাছি কিছু খনন করছি এবং আমি পিএইচপি মধ্যে একটি বৈধ v4 ইউআইডি উত্পন্ন যে একটি ফাংশন একসাথে টুকরা চেষ্টা করা হয়েছে। এটি আমি আসতে সক্ষম হয়েছি এটিই সবচেয়ে কাছের। হেক্স, দশমিক, বাইনারি, পিএইচপি-র বিটওয়াইস অপারেটর এবং এর মতো আমার জ্ঞান প্রায় অরক্ষিত। এই ফাংশনটি এক অঞ্চল অবধি বৈধ v4 ইউআইডি উত্পন্ন করে। একটি ভি 4 ইউআইডি আকারে হওয়া উচিত:

XXXXXXXX-xxxx- 4 xxx- Y XXX-xxxxxxxxxxxx

যেখানে y 8, 9, A, বা B. হয় এখানে এটি ফাংশনগুলি ব্যর্থ হয় কারণ এটি মেনে চলে না।

আমি আশা করছিলাম যে এই অঞ্চলে আমার চেয়ে আরও বেশি জ্ঞানযুক্ত কেউ আমাকে একটি হাত ধার দিতে এবং এই ফাংশনটি ঠিক করতে আমাকে সহায়তা করতে পারে যাতে এটি সেই নিয়মের সাথে মেনে চলে।

ফাংশনটি নিম্নরূপ:

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

?>

যে কেউ আমাকে সাহায্য করতে পারে ধন্যবাদ।


5
আপনি যদি লিনাক্সে থাকেন এবং আপনি যদি কিছুটা অলস হন তবে আপনি এগুলি তৈরি করতে পারেন$newId = exec('uuidgen -r');
জর্জেগার্জা

উত্তর:


282

পিএইচপি ম্যানুয়ালটিতে এই মন্তব্য থেকে নেওয়া , আপনি এটি ব্যবহার করতে পারেন:

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

43
এই ফাংশনটি সদৃশ তৈরি করবে , সুতরাং যখন আপনার অনন্য মানগুলির প্রয়োজন হবে তখন এটিকে এড়িয়ে চলুন। নোট করুন যে mt_rand () সর্বদা একই বীজ প্রদত্ত এলোমেলো সংখ্যার একই ক্রম উত্পাদন করে। সুতরাং প্রতিবার কোনও বীজ পুনরাবৃত্তি করা হলে একই সঠিক ইউআইডি উত্পন্ন হয়। এটি পেতে, আপনাকে সময় এবং ম্যাক ঠিকানা ব্যবহার করে এটি বীজ করতে হবে তবে আপনি কীভাবে এটি করবেন তা নিশ্চিত নই, যেহেতু এমটি_স্রান্ড () এর জন্য একটি পূর্ণসংখ্যার প্রয়োজন হয়।
পাভলে প্রেডিক

12
@ পাভেলপ্রেডিক এমটি_স্রান্ড (সিআরসি 32 (সিরিয়ালাইজ ([মাইক্রোটাইম (সত্য), 'ইউএসআইপিআইপি', 'ইসটিসি'])))); (আমি অন্য উইলিয়াম: পি)
উইলিয়াম

13
পিএইচপি ডক্স স্পষ্টভাবে সাবধান করে যে mt_rand () ক্রিপ্টোগ্রাফিকভাবে সুরক্ষিত মান উত্পন্ন করে না। অন্য কথায়, এই ফাংশন দ্বারা উত্পন্ন মানগুলি অনুমানযোগ্য হতে পারে। আপনার যদি ইউআইডিগুলি অনুমানযোগ্য না হয় তা নিশ্চিত করার প্রয়োজন হয় তবে আপনার নীচে জ্যাকের সমাধানটি ব্যবহার করা উচিত, যা ওপেনসেল_আরন্ডম_সেসডো_বাইটেস () ফাংশনটি ব্যবহার করে।
রিচার্ড কেলার

7
আপনি যদি প্রতিটি ক্ষেত্রকে ময়লা-আবর্জনা দিয়ে ভরাট করেন তবে পৃথিবীতে ইউআইডি তৈরির বিষয়টি কী?
ইভি

1
পিএইচপি 7.0+ র্যান্ডম_বাইটস () ফাংশনটি সংজ্ঞায়িত করে যা সর্বদা ক্রিপ্টোগ্রাফিকভাবে র্যান্ডম বাইটগুলি সুরক্ষিত করতে সক্ষম হয় বা যদি ব্যর্থ হয় তবে ব্যতিক্রম ছুঁড়ে ফেলবে। এটি এমনকি ওপেনএসএল_আরেন্ডম_পিউসোডো_বাইটস () এর চেয়ে ভাল যাঁর আউটপুটটি কখনও কখনও কিছু পরিস্থিতিতে ক্রিপ্টোগ্রাফিকভাবে সুরক্ষিত থাকে না।
থোমাস্রুটার

365

এটিকে পৃথক ক্ষেত্রগুলিতে বিভক্ত করার পরিবর্তে, এলোমেলো ডেটা ডেটা তৈরি করা এবং স্বতন্ত্র বাইট অবস্থান পরিবর্তন করা সহজ। আপনার mt_rand () এর চেয়ে আরও ভাল এলোমেলো নম্বর জেনারেটর ব্যবহার করা উচিত।

আরএফসি 4122 - বিভাগ 4.4 অনুযায়ী আপনার এই ক্ষেত্রগুলি পরিবর্তন করতে হবে:

  1. time_hi_and_version (7 ম অক্টেটের 4-7 বিট),
  2. clock_seq_hi_and_reserved (9 ম অক্টেটের বিট 6 এবং 7)

অন্যান্য 122 বিটের সমস্তগুলি যথাযথভাবে এলোমেলো হওয়া উচিত।

নিম্নলিখিত পদ্ধতিটি ব্যবহার করে এলোমেলো তথ্যগুলির 128 বিট উত্পন্ন করে openssl_random_pseudo_bytes(), অক্টেটগুলিতে অনুমতি দেয় এবং তারপরে চূড়ান্ত বিন্যাসটি ব্যবহার করে bin2hex()এবং vsprintf()করতে পারে।

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

পিএইচপি 7 এর সাথে, এলোমেলো বাইট সিকোয়েন্সগুলি তৈরি করা ব্যবহার করে আরও সহজ random_bytes():

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

9
$data = file_get_contents('/dev/urandom', NULL, NULL, 0, 16);
ওপেনসেল

5
এছাড়াও, আমি ওপেনটিএসএলকে এমটি_র্যান্ডের চেয়ে অনেক বেশি বিশ্বাস করব।
অধ্যাপক ফ্যালকেন

3
@ ব্রুনো অগাস্টো এটি এলোমেলো, এবং অনুলিপি পাওয়ার পক্ষে এটি খুব সম্ভব নয় (একটি ভাল এলোমেলো উত্স সহ) তবে এটি ডাটাবেস পর্যায়ে প্রয়োগ করা ভাল অভ্যাস।
জ্যাক

9
গাইডভ 4 ফাংশনের অভ্যন্তরে এলোমেলো_বাইটস (16) কল না দেওয়ার কোনও কারণ আছে এবং এভাবে গাইডভি 4-তে কোনও প্যারামিটার পাস করতে হবে না?
স্টিফেন আর

7
ছোট উন্নতি: $ ডেটার জন্য একটি ন্যূনু ডিফল্ট সেট করুন, এবং তারপরে ফাংশনটির প্রথম লাইনটি হ'ল: $data = $data ?? random_bytes( 16 ); এখন আপনি আপনার নিজের এলোমেলো ডেটা উত্স নির্দিষ্ট করতে পারেন, বা ফাংশনটি এটি আপনার জন্য করতে দিন। :-)
স্টিফেন আর

118

সুরকার নির্ভরতা ব্যবহার করে যে কেউ , আপনি এই গ্রন্থাগারটি বিবেচনা করতে চাইতে পারেন: https://github.com/ramsey/uuid

এটি এর চেয়ে সহজ আর কিছু পায় না:

Uuid::uuid4();

32
ওহ, আমি জানি না .... পাঁচ লাইন কোড বনাম নির্ভরতা সহ একটি লাইব্রেরি লোড হচ্ছে? আমি জ্যাক এর কাজ পছন্দ। ওয়াইএমএমভি
স্টিফেন আর

7
+1 স্টিফেন। রামসে ইউইডের কেবল uuid4 এর চেয়ে অনেক বেশি কার্যকারিতা রয়েছে। আমি কলা চাই না! এখানে আপনার পুরো জঙ্গল আছে!
lcjury

26
ইউআইডিগুলি কেবল এলোমেলো স্ট্রিং নয়। এটি কীভাবে কাজ করে তা নিয়ে একটি অনুমান রয়েছে। যথাযথ র্যান্ডম ইউআইডি তৈরি করতে যা আমাকে পরে প্রত্যাখ্যান করার বিষয়ে চিন্তা করতে হবে না, আমি বরং আমার নিজের প্রয়োগটি রোল করার চেয়ে পরীক্ষিত লাইব্রেরি ব্যবহার করব।
ব্র্যান্ডন

3
এটি একটি ইউআইডিভি 4। এটি (বেশিরভাগ ক্ষেত্রে, তবে কয়েকটি বিটের জন্য) এলোমেলো। এটি ক্রিপ্টোগ্রাফি নয়। "নিজের নিজের ঘূর্ণায়মান" এর বিপরীতে প্যারানোইয়া বোকা।
গর্ডন

23

ইউনিক্স সিস্টেমে, আপনার জন্য ইউইড তৈরি করতে সিস্টেম কার্নেলটি ব্যবহার করুন।

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

ক্রেডিট Samveen https://serverfault.com/a/529319/210994

নোট !: একটি ইউইড পেতে এই পদ্ধতিটি ব্যবহার করে বাস্তবে খুব দ্রুত এনট্রপি পুলটি নিষ্ক্রিয় করা হয়! আমি এটি ব্যবহার করা এড়িয়ে চলতাম যেখানে এটি প্রায়শই ডাকা হত।


2
বহনযোগ্যতার পাশাপাশি, নোট করুন যে /dev/randomএন্টারোপি পুলটি অবসন্ন হলে র্যান্ডম উত্সটি কোনটি ব্লক করে।
জ্যাক

@ জ্যাক আপনি ইউনিক্স সিস্টেমে এনট্রপি পুল অবসন্নতার বিষয়টিতে দয়া করে কিছু ডকুমেন্টেশন যুক্ত করবেন? আমি এমন বাস্তববাদী ব্যবহারের ক্ষেত্রে আরও জানতে আগ্রহী যেখানে এই পদ্ধতিটি ভেঙে যায়।
থারস্মমনার

আমি এই বিশেষ কার্নেল ফাইল উত্সটি তৈরি করার তথ্য খুঁজে পাচ্ছিলাম না /dev/urandom, যা আমার বোঝার মধ্যে দিয়ে নিঃশেষ হবে না, তবে ডুপ্লিকেট ইউইডগুলি ফেরত ঝুঁকিপূর্ণ। আমার ধারণা এটি একটি বাণিজ্য; আপনার আসলেই কি সিস্টেম এনট্রপি দ্বারা প্রভাবিত একটি অনন্য আইডি দরকার?
থারস্মমনার

13

একটি ভি 4 ইউইড তৈরি করার জন্য আমার অনুসন্ধানে, আমি এই পৃষ্ঠায় প্রথম এসেছি, তারপরে এটি http://php.net/manual/en/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));
}

ক্রেডিট: প্যাভেল.ভলিয়েন্টসেভ

সম্পাদনা করুন: স্পষ্ট করার জন্য, এই ফাংশনটি আপনাকে সর্বদা একটি ভি 4 ইউইড (পিএইচপি> = 5.3.0) দেবে।

যখন com_create_guid ফাংশন উপলব্ধ থাকে (সাধারণত কেবল উইন্ডোজ থাকে), এটি এটি ব্যবহার করবে এবং কোঁকড়া ধনুর্বন্ধনীগুলি ছাঁটাই করবে।

যদি উপস্থিত না (লিনাক্স), এটি শক্তিশালী এলোমেলো ওপেনস্ল_আরন্ডম_সপোডো_বাইটস ফাংশনটিতে ফিরে আসবে, তবে এটি v4 uuid এ ফর্ম্যাট করার জন্য vsprintf ব্যবহার করবে।


5

আমার উত্তরটি মন্তব্য অবিচ্ছিন্ন ব্যবহারকারী মন্তব্যের উপর ভিত্তি করে তবে এটি থেকে পড়ার পরিবর্তে এলোমেলো স্ট্রিং উত্পন্ন করতে ওপসএসএল_আরন্ডম_পসিউডো_বাইটস ফাংশন ব্যবহার করে/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

পিএইচপি <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));
}

4

এখানে ব্রুফার উত্তর দ্বারা অনুপ্রাণিত ।

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

বা বেনামে ফাংশন ব্যবহার করতে অক্ষম হলে।

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

1
আপনি যদি অন্য উত্তরে মন্তব্যগুলি লক্ষ্য করেন তবে আপনি দেখতে পাবেন যে লোকেরা mt_rand()এলোমেলোভাবে গ্যারান্টিযুক্ত নয়।
ড্যানিয়েল চেউং

3

সঠিক একই জিনিস অনুসন্ধান এবং হচ্ছে প্রায় নিজেকে এই একটি সংস্করণ বাস্তবায়ন, আমি মনে করাটা যে উল্লেখ, যদি আপনি একটি মধ্যে এই করছেন ছিল ওয়ার্ডপ্রেস ফ্রেমওয়ার্ক, ডাব্লু ঠিক এই জন্য নিজস্ব সুপার-কুশলী ফাংশন আছে:

$myUUID = wp_generate_uuid4();

আপনি এখানে বর্ণনা এবং উত্স পড়তে পারেন ।


1
ডাব্লুপি ফাংশন এককভাবে mt_rand ব্যবহার করে। সুতরাং পর্যাপ্ত এলোমেলোতা নাও থাকতে পারে
হারবার্ট পিটার্স

@ হারবার্টপিটার্স আপনি ঠিক বলেছেন আমি কেবল এটি উল্লেখ করেছি কারণ এটি ওয়ান লাইনার। আমি বলছিলাম যে এটি ঝরঝরে হবে যদি তারা এর জন্য একটি ফিল্টার যুক্ত করে থাকে তবে আপনি আরও সুরক্ষিত / গ্যারান্টিযুক্ত-এলোমেলো নম্বরটি ফিরে আসতে পারেন; তবে তার উল্টাপাল্টাটি হ'ল, যদি আপনি এত ঝোঁক falseথাকতেন তবে আপনিও ফিরে আসতে পারেন 🤷
অনির্দিষ্ট 2

2

আপনার জন্য ইউইডি তৈরি করতে কীভাবে mysql ব্যবহার করবেন?

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

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

2
মাইএসকিউএল এর UUID()ফাংশন v1 uuids তৈরি করে।
স্ট্যাটিক্সন

2
$uuid = vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex(random_bytes(16)), 4));

2
এটি অন্যদের কী করে তা বুঝতে সহায়তা করার জন্য দয়া করে আপনার কোডটিতে একটি ব্যাখ্যা যুক্ত করুন।
কেফুবার

- এই আসলে Symfony polyfil দ্বারা সম্পন্ন হয় github.com/symfony/polyfill-uuid/blob/master/Uuid.php#L320
Serhii Polishchuk

1

টম থেকে, 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])

3
যদি তারা ইউনিক্স বা লিনাক্স / জিএনইউ চালাচ্ছে না? এই কোডটি কাজ করবে না।
কোল জনসন

4
/ ডি / র্যান্ডম ফাঁকা থাকলে এবং আরও এনট্রপির পুনরায় লোডের জন্য অপেক্ষা করা থাকলে এটি খুব ধীরে ধীরে চলার সম্ভাবনাও রয়েছে।
ObsidianX

1
/dev/urandomভাল হতে হবে - /dev/randomশুধুমাত্র দীর্ঘমেয়াদী ক্রিপ্টোগ্রাফিক কী তৈরির জন্য ব্যবহার করা উচিত।
আইরিডন

যে উপর ভিত্তি করে, আমি নিয়ে এসেছেন এই - এটা seeding পড়ে-চিত্ যেমন যদৃচ্ছতা বিভিন্ন সম্ভব উত্স, এবং রিসর্ট ব্যবহার mt_rand()যদি কিছুই কল্পনাকারী পাওয়া যায়।
mindplay.dk

1
এখনই, কেবল random_bytes()পিএইচপি 7 এ ব্যবহার করুন এবং আপনি যান :-)
mindplay.dk

1

আমি নিশ্চিত যে বাইনারি থেকে দশমিক 4xxxএবং yxxxরূপগুলির জন্য রূপান্তর করার আরও একটি দুর্দান্ত উপায় আছে । তবে আপনি যদি openssl_random_pseudo_bytesনিজের ক্রিটোগ্রাফিকভাবে সুরক্ষিত নম্বর জেনারেটর হিসাবে ব্যবহার করতে চান তবে এটি আমি ব্যবহার করি:

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

সিমফনি পলিফিল / ইউইড ব্যবহার করুন
তারপরে আপনি কেবল ইউইইডি দেশীয় পিএইচপি ফাংশন হিসাবে তৈরি করতে পারেন:

$uuid = uuid_create(UUID_TYPE_RANDOM);

এটি সম্পর্কে আরও জানুন, সরকারী সিমফনি ব্লপ পোস্টে পড়ুন - https://symfony.com/blog/introducing-the-new-symfony-uuid-polyfill

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.