ভুলে যাওয়া পাসওয়ার্ডের জন্য এলোমেলো টোকেন তৈরি করার জন্য সেরা অনুশীলন


96

আমি ভুলে যাওয়া পাসওয়ার্ডের জন্য সনাক্তকারী তৈরি করতে চাই। আমি পড়লাম আমি mt_rand () দিয়ে টাইমস্ট্যাম্প ব্যবহার করে এটি করতে পারি, তবে কিছু লোক বলছেন যে টাইম স্ট্যাম্প প্রতিবারই অনন্য হতে পারে না। তাই আমি এখানে বিভ্রান্ত কিছুটা। আমি কি এটি দিয়ে টাইম স্ট্যাম্প ব্যবহার করে এটি করতে পারি?

প্রশ্ন
কাস্টম দৈর্ঘ্যের এলোমেলো / অনন্য টোকেন উত্পন্ন করার জন্য সেরা অনুশীলন কোনটি?

আমি জানি এখানে চারপাশে প্রচুর প্রশ্ন করা হয় তবে বিভিন্ন লোকের কাছ থেকে বিভিন্ন মতামত পড়ে আমি আরও বিভ্রান্ত হয়ে পড়ছি।


@ আলমাডোমুন্ডো: একটি কম্পিউটার সময় সীমাহীনভাবে ভাগ করতে পারে না।
জুয়ার্জেন d

@ জর্জ্যান্ড - দুঃখিত, এটি পাবেন না।
আলমা ডো

আপনি উদাহরণস্বরূপ দ্বিতীয়টি বাদে একটি ন্যানো কল করলে আপনি একই টাইমস্ট্যাম্পটি পাবেন। উদাহরণস্বরূপ কিছু সময় ফাংশন কেবল 100ns ধাপে সময় ফিরতে পারে, কিছু কেবলমাত্র সেকেন্ডের ধাপে।
জুয়ারজেন d

@ জর্জ্যান্ড আহ, যে। হ্যাঁ. আমি কেবলমাত্র কয়েক সেকেন্ডের সাথে 'ক্লাসিক' টাইমস্ট্যাম্পের উল্লেখ করেছি। তবে আপনি যদি বলেছেন তার মতো কাজ করে - হ্যাঁ (যা আমাদেরকে অনন্য-অনন্য টাইমস্ট্যাম্প পাওয়ার জন্য টাইম মেশিনের সাথে একটি বিকল্প দেয়)
আলমা ডো

উত্তর:


151

পিএইচপি-তে, ব্যবহার করুন random_bytes()। কারণ: আপনি একটি পাসওয়ার্ড অনুস্মারক টোকেন পাওয়ার উপায় সন্ধান করছেন এবং এটি যদি এককালীন লগইন শংসাপত্রগুলি হয় তবে আপনার কাছে সুরক্ষার জন্য আসলে একটি ডেটা রয়েছে (যা - পুরো ব্যবহারকারীর অ্যাকাউন্ট)

সুতরাং কোডটি নিম্নরূপ হবে:

//$length = 78 etc
$token = bin2hex(random_bytes($length));

আপডেট : এই উত্তরের পূর্ববর্তী সংস্করণগুলি উল্লেখ করা হয়েছিল uniqid()এবং সুরক্ষার কোনও সমস্যা থাকলে এবং কেবল স্বতন্ত্রতা না থাকলে তা ভুল। uniqid()মূলত microtime()কিছু এনকোডিং সহ। microtime()আপনার সার্ভারে নির্ভুল পূর্বাভাস পাওয়ার সহজ উপায় রয়েছে । একজন আক্রমণকারী পাসওয়ার্ড পুনরায় সেট করার অনুরোধ জানাতে পারে এবং তারপরে বেশ কয়েকটি সম্ভাব্য টোকেন চেষ্টা করে। এটি আরও সম্ভব যদি আরও_এন্ট্রপি ব্যবহার করা হয়, কারণ অতিরিক্ত এনট্রপি একইভাবে দুর্বল। এটি প্রকাশ করার জন্য @ নিকিসি এবং @ স্কটআরাকিসজেউসকিকে ধন্যবাদ ।

আরও তথ্যের জন্য দেখুন


21
দ্রষ্টব্য যে random_bytes()কেবল পিএইচপি 7 হিসাবে উপলব্ধ। পুরানো সংস্করণগুলির জন্য, @yesitsme এর উত্তরটি সেরা বিকল্প বলে মনে হচ্ছে।
জেরাল্ড স্নাইডার

4
@ জেরাল্ডশিনিডার বা র্যান্ডম_কম্প্যাট , যা এই বৈশিষ্ট্যগুলির জন্য পলিফিল যা সবচেয়ে বেশি সমালোচনা পর্যালোচনা পেয়েছে;)
স্কট আর্কিসজেউস্কি

এই টোকেনটি সঞ্চয় করার জন্য আমি আমার স্ক্যুয়াল ডাটাবেসে একটি ভার্চার (64) ক্ষেত্র তৈরি করেছি। আমি $ দৈর্ঘ্য 64 এ সেট করেছিলাম তবে স্ট্রিংটি 128 অক্ষর দীর্ঘ। আমি কীভাবে একটি স্থির আকারের সাথে স্ট্রিং পেতে পারি (এখানে, তখন 64)?
গর্ডি

4
@ গর্ডি দৈর্ঘ্যটি 32 এ সেট করুন, প্রতিটি বাইট 2 হেক্স অক্ষর
জনহোল্ডারক

কি হওয়া উচিত $length? ব্যবহারকারীর আইডি? অথবা কি?
স্ট্যাক

72

এটি 'সেরা র্যান্ডম' অনুরোধটির উত্তর দেয়:

সুরক্ষা.স্ট্যাকএক্সচেঞ্জ থেকে আদির উত্তর 1 এর এর সমাধান রয়েছে:

আপনার ওপেনএসএসএল সমর্থন রয়েছে তা নিশ্চিত করুন এবং আপনি এই ওয়ান-লাইনারের সাথে কখনও ভুল পাবেন না

$token = bin2hex(openssl_random_pseudo_bytes(16));

1. আদি, সোম 12 নভেম্বর 2018, সেল্রিটিস, "কনফার্মেশন ইমেইলগুলির জন্য একটি অদম্য টোকেন তৈরি করা হচ্ছে", সেপ্টেম্বর 20 '13 এ 7:06, https://security.stackexchange.com/a/40314/


25
openssl_random_pseudo_bytes($length)- সমর্থন: পিএইচপি 5> = 5.3.0, ....................................... ................... (পিএইচপি 7 এবং ততোধিকের জন্য ব্যবহার করুন random_bytes($length)) ...................... .................... (পিএইচপি 5.3 এর নীচে - পিএইচপি 5.3 এর নীচে ব্যবহার করবেন না)
jave.web

54

স্বীকৃত উত্তরের পূর্ববর্তী সংস্করণটি md5(uniqid(mt_rand(), true))অনিরাপদ এবং কেবলমাত্র প্রায় 2 ^ 60 সম্ভাব্য আউটপুট সরবরাহ করে - স্বল্প বাজেটের আক্রমণকারীর জন্য প্রায় এক সপ্তাহের সময় ধরে নিরপেক্ষ বাহিনীর অনুসন্ধানের সীমার মধ্যে:

যেহেতু একটি 56-বিট ডিইএস কী প্রায় 24 ঘন্টার মধ্যে নৃশংসভাবে জোর করা যেতে পারে , এবং একটি গড় ক্ষেত্রে প্রায় 59 বিট এনট্রপি থাকবে, তাই আমরা 2 ^ 59/2 ^ 56 = প্রায় 8 দিনের জন্য গণনা করতে পারি। এই টোকেন যাচাইকরণ কীভাবে বাস্তবায়িত হয় তার উপর নির্ভর করে, কার্যকরভাবে সময় সম্পর্কিত তথ্য ফাঁস এবং বৈধ পুনরায় সেট টোকেনের প্রথম এন বাইটগুলি নির্ধারণ করা সম্ভব হতে পারে

যেহেতু প্রশ্নটি "সেরা অনুশীলনগুলি" সম্পর্কে এবং এর সাথে খোলে ...

আমি ভুলে যাওয়া পাসওয়ার্ডের জন্য সনাক্তকারী তৈরি করতে চাই

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


একটি সিএসপিআরএনজি ব্যবহার করে

পিএইচপি 7 এ, আপনি ব্যবহার করতে পারেন bin2hex(random_bytes($n))(যেখানে $n15 এর চেয়ে বেশি পূর্ণসংখ্যা রয়েছে)।

পিএইচপি 5 এ, আপনি random_compatএকই এপিআই প্রকাশ করতে ব্যবহার করতে পারেন ।

বিকল্পভাবে, bin2hex(mcrypt_create_iv($n, MCRYPT_DEV_URANDOM))আপনি ext/mcryptইনস্টল করা থাকলে। আর একটি ভাল ওয়ান-লাইনার bin2hex(openssl_random_pseudo_bytes($n))

মূল্যায়নকারী থেকে চেহারা আলাদা করা

আমার পিএইচপি-র সুরক্ষিত "আমাকে মনে রাখুন" কুকিগুলিতে আমার পূর্ববর্তী কাজ থেকে সরে আসা , পূর্বোক্ত সময় লিক (সাধারণত ডাটাবেস ক্যোয়ারী দ্বারা প্রবর্তিত) প্রশমিত করার একমাত্র কার্যকর উপায় হ'ল বৈধতা থেকে লুককে আলাদা করা।

আপনার টেবিলটি যদি এইরকম লাগে (মাইএসকিউএল) ...

CREATE TABLE account_recovery (
    id INTEGER(11) UNSIGNED NOT NULL AUTO_INCREMENT 
    userid INTEGER(11) UNSIGNED NOT NULL,
    token CHAR(64),
    expires DATETIME,
    PRIMARY KEY(id)
);

... আপনাকে আরও একটি কলাম যুক্ত করতে হবে selector, এর মতো:

CREATE TABLE account_recovery (
    id INTEGER(11) UNSIGNED NOT NULL AUTO_INCREMENT 
    userid INTEGER(11) UNSIGNED NOT NULL,
    selector CHAR(16),
    token CHAR(64),
    expires DATETIME,
    PRIMARY KEY(id),
    KEY(selector)
);

একটি সিএসপিআরএনজি ব্যবহার করুন যখন কোনও পাসওয়ার্ড পুনরায় সেট করার টোকেন জারি করা হয়, তখন ব্যবহারকারীকে উভয় মান প্রেরণ করুন, নির্বাচক এবং ডাটাবেসে র্যান্ডম টোকেনের একটি SHA-256 হ্যাশ সংরক্ষণ করুন। নির্বাচকটি হ্যাশ এবং ব্যবহারকারী আইডি দখল করতে ব্যবহার করুন, ব্যবহারকারীর ডাটাবেজে সংরক্ষিত থাকা টোকেনটির SHA-256 হ্যাশ গণনা করুন hash_equals()

উদাহরণ কোড

পিডিও দিয়ে পিএইচপি 7 (বা 5.6 এলোমেলো_কম্প্যাট সহ) একটি রিসেট টোকন তৈরি করা:

$selector = bin2hex(random_bytes(8));
$token = random_bytes(32);

$urlToEmail = 'http://example.com/reset.php?'.http_build_query([
    'selector' => $selector,
    'validator' => bin2hex($token)
]);

$expires = new DateTime('NOW');
$expires->add(new DateInterval('PT01H')); // 1 hour

$stmt = $pdo->prepare("INSERT INTO account_recovery (userid, selector, token, expires) VALUES (:userid, :selector, :token, :expires);");
$stmt->execute([
    'userid' => $userId, // define this elsewhere!
    'selector' => $selector,
    'token' => hash('sha256', $token),
    'expires' => $expires->format('Y-m-d\TH:i:s')
]);

ব্যবহারকারী দ্বারা সরবরাহিত রিসেট টোকন যাচাই করা হচ্ছে:

$stmt = $pdo->prepare("SELECT * FROM account_recovery WHERE selector = ? AND expires >= NOW()");
$stmt->execute([$selector]);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (!empty($results)) {
    $calc = hash('sha256', hex2bin($validator));
    if (hash_equals($calc, $results[0]['token'])) {
        // The reset token is valid. Authenticate the user.
    }
    // Remove the token from the DB regardless of success or failure.
}

এই কোড স্নিপেটগুলি সম্পূর্ণ সমাধান নয় (আমি ইনপুট বৈধতা এবং কাঠামোর একীকরণগুলি এচু করেছি) তবে তাদের কী করা উচিত তার উদাহরণ হিসাবে পরিবেশন করা উচিত।


আপনি যখন ব্যবহারকারী দ্বারা সরবরাহিত রিসেট টোকেন যাচাই করেন, আপনি কেন এলোমেলো টোকেনের বাইনারি উপস্থাপনা ব্যবহার করবেন? আপনি কি ভাবেন যে এটি সম্ভব (এবং সুরক্ষিত?) থেকে: 1) ডিবিতে টোকেনের হ্যাশ হেক্স মান hash('sha256', bin2hex($token)), 2) দিয়ে যাচাই করবেন if (hash_equals(hash('sha256', $validator), $results[0]['token'])) {...? ধন্যবাদ!
গুইচারা

হ্যাঁ, হেক্স স্ট্রিংগুলির তুলনা করাও নিরাপদ। এটি সত্যই পছন্দসই বিষয়। আমি কাঁচা বাইনারিগুলিতে সমস্ত ক্রিপ্টো অপারেশন করতে পছন্দ করি এবং কেবল কখনও সংক্রমণ বা সঞ্চয়ের জন্য হেক্স / বেস 64 তে রূপান্তর করি।
স্কট আর্কিসজেউস্কি

হাই স্কট, এটি মূলত আপনার উত্তরের জন্যই নয়, "আমাকে মনে রাখুন" বৈশিষ্ট্যটি সম্পর্কে সম্পূর্ণ নিবন্ধের জন্য একটি প্রশ্ন। idনির্বাচক হিসাবে অনন্য ব্যবহার করবেন না কেন ? আমি বলতে চাইছি, account_recoveryটেবিলের প্রাথমিক কী । আমাদের নির্বাচনের জন্য অতিরিক্ত স্তরের সুরক্ষার দরকার নেই, তাই না? ধন্যবাদ!
আন্দ্রে পলিকানাইন

id:secretঠিক আছে। selector:secretঠিক আছে। secretনিজেই হয় না। প্রমাণীকরণ প্রোটোকল (যা ধ্রুব সময় হওয়া উচিত) থেকে ডাটাবেস ক্যোয়ারী (যা টাইমিং-ফাঁস হয়) আলাদা করার লক্ষ্য।
স্কট আর্কিসজেউস্কি

openssl_random_pseudo_bytesপরিবর্তে random_bytesযদি পিএইচপি 5.6 চালাচ্ছে তবে এটি ব্যবহারে কোনও ক্ষতি আছে ? এছাড়াও, আপনি কি কেবল নির্বাচককে সংযুক্ত করবেন না এবং লিঙ্কটির ক্যোরিস্ট্রিংয়ে বৈধকরণকারী নয়?
গ্রেগ

7

আপনি DEV_RANDOM ব্যবহার করতে পারেন, যেখানে উত্পাদিত টোকেন দৈর্ঘ্য 128 = 1/2। নীচের কোড 256 টোকেন উত্পন্ন করে।

$token = bin2hex(mcrypt_create_iv(128, MCRYPT_DEV_RANDOM));

4
আমি পরামর্শ দিতে MCRYPT_DEV_URANDOMহবে MCRYPT_DEV_RANDOM
স্কট আর্কিসজেউসকি

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