ভূমিকা
আপনার টেবিল সংজ্ঞা দিয়ে শুরু:
- UserID
- Fname
- Lname
- Email
- Password
- IV
পরিবর্তনগুলি এখানে:
- ক্ষেত্র
Fname
, Lname
এবং Email
একটি প্রতিসম সাইফার, দ্বারা উপলব্ধ ব্যবহার করে এনক্রিপ্ট করা হবে না দ্বারা OpenSSL ,
IV
ক্ষেত্র সংরক্ষণ করবে initialisation ভেক্টর এনক্রিপশন জন্য ব্যবহৃত। স্টোরেজ প্রয়োজনীয়তা ব্যবহৃত সাইফার এবং মোড উপর নির্ভর করে; এই সম্পর্কে আরও পরে।
Password
ক্ষেত্রটিতে কোনও ব্যবহার কুচি-কুচি করিয়া কাটা বস্তু হবে একমুখী , পাসওয়ার্ড হ্যাশ
জোড়া লাগানো
সাইফার এবং মোড
সেরা এনক্রিপশন সাইফার এবং মোড নির্বাচন করা এই উত্তরের ক্ষেত্রের বাইরে, তবে চূড়ান্ত পছন্দটি এনক্রিপশন কী এবং প্রারম্ভিককরণ ভেক্টর উভয়ের আকারকে প্রভাবিত করে; এই পোস্টের জন্য আমরা AES-256-CBC ব্যবহার করব যা 16 বাইটের একটি নির্দিষ্ট আকারের আকার এবং 16, 24 বা 32 বাইটের মূল আকার size
এনক্রিপশন কী
একটি ভাল এনক্রিপশন কী হ'ল একটি বাইনারি ব্লব যা একটি নির্ভরযোগ্য র্যান্ডম নম্বর জেনারেটর থেকে উত্পন্ন হয়। নিম্নলিখিত উদাহরণটি সুপারিশ করা হবে (> = 5.3):
$key_size = 32; // 256 bits
$encryption_key = openssl_random_pseudo_bytes($key_size, $strong);
// $strong will be true if the key is crypto safe
এটি একবার বা একাধিকবার করা যেতে পারে (আপনি যদি এনক্রিপশন কীগুলির একটি শৃঙ্খলা তৈরি করতে চান)। এগুলি যথাসম্ভব ব্যক্তিগত রাখুন।
চতুর্থ
আরম্ভের ভেক্টর এনক্রিপশনে এলোমেলোভাবে যুক্ত করে এবং সিবিসি মোডের জন্য প্রয়োজনীয়। এই মানগুলি আদর্শভাবে কেবল একবার ব্যবহার করা উচিত (প্রযুক্তিগতভাবে একবারে এনক্রিপশন কীতে), সুতরাং একটি সারির যে কোনও অংশে একটি আপডেট এটিকে পুনরায় তৈরি করা উচিত।
আইভি উত্পাদন করতে আপনাকে সহায়তা করার জন্য একটি ফাংশন সরবরাহ করা হয়েছে:
$iv_size = 16; // 128 bits
$iv = openssl_random_pseudo_bytes($iv_size, $strong);
উদাহরণ
পূর্বের $encryption_key
এবং ব্যবহার করে নাম ক্ষেত্রটি এনক্রিপ্ট করা যাক $iv
; এটি করতে, আমাদের ব্লক আকারে আমাদের ডেটা প্যাড করতে হবে:
function pkcs7_pad($data, $size)
{
$length = $size - strlen($data) % $size;
return $data . str_repeat(chr($length), $length);
}
$name = 'Jack';
$enc_name = openssl_encrypt(
pkcs7_pad($name, 16), // padded data
'AES-256-CBC', // cipher and mode
$encryption_key, // secret key
0, // options (not used)
$iv // initialisation vector
);
স্টোরেজ প্রয়োজনীয়তা
আইভির মতো এনক্রিপ্ট করা আউটপুট বাইনারি হয়; ডাটাবেসে এই মানগুলি সংরক্ষণ করে নির্ধারিত কলামের প্রকার যেমন BINARY
বা ব্যবহার করে সম্পন্ন করা যায় VARBINARY
।
IV এর মতো আউটপুট মান বাইনারি হয়; মাইএসকিউএলে এই মানগুলি সঞ্চয় করতে, কলামগুলি ব্যবহার BINARY
বাVARBINARY
বিবেচনা করুন । যদি এটি কোনও বিকল্প না হয় তবে আপনি বাইনারি ডেটাটিকে ব্যবহার করে পাঠ্য উপস্থাপনায় রূপান্তর করতে পারেন base64_encode()
বা bin2hex()
এটির জন্য 33% থেকে 100% বেশি স্টোরেজ স্পেসের প্রয়োজন হয়।
ডিক্রিপশন
সঞ্চিত মানগুলির ডিক্রিপশন একই:
function pkcs7_unpad($data)
{
return substr($data, 0, -ord($data[strlen($data) - 1]));
}
$row = $result->fetch(PDO::FETCH_ASSOC); // read from database result
// $enc_name = base64_decode($row['Name']);
// $enc_name = hex2bin($row['Name']);
$enc_name = $row['Name'];
// $iv = base64_decode($row['IV']);
// $iv = hex2bin($row['IV']);
$iv = $row['IV'];
$name = pkcs7_unpad(openssl_decrypt(
$enc_name,
'AES-256-CBC',
$encryption_key,
0,
$iv
));
প্রমাণীকৃত এনক্রিপশন
আপনি গোপন কী (এনক্রিপশন কী থেকে পৃথক) এবং সাইফার পাঠ্য থেকে উত্পন্ন একটি স্বাক্ষর যুক্ত করে উত্পন্ন সাইফার পাঠ্যের অখণ্ডতাটিকে আরও উন্নত করতে পারেন। সাইফার পাঠ্যটি ডিক্রিপ্ট হওয়ার আগে স্বাক্ষরটি প্রথমে যাচাই করা হয় (অগ্রাধিকার হিসাবে ধ্রুবক-সময় তুলনা পদ্ধতিতে)।
উদাহরণ
// generate once, keep safe
$auth_key = openssl_random_pseudo_bytes(32, $strong);
// authentication
$auth = hash_hmac('sha256', $enc_name, $auth_key, true);
$auth_enc_name = $auth . $enc_name;
// verification
$auth = substr($auth_enc_name, 0, 32);
$enc_name = substr($auth_enc_name, 32);
$actual_auth = hash_hmac('sha256', $enc_name, $auth_key, true);
if (hash_equals($auth, $actual_auth)) {
// perform decryption
}
আরো দেখুন: hash_equals()
হ্যাশ
আপনার ডাটাবেসে একটি বিপরীতমুখী পাসওয়ার্ড সংরক্ষণ যতটা সম্ভব এড়ানো উচিত; আপনি কেবল পাসওয়ার্ডের বিষয়বস্তুগুলি জানার চেয়ে যাচাই করতে চান। যদি কোনও ব্যবহারকারী তাদের পাসওয়ার্ড হারিয়ে ফেলেন তবে তাদের আসল পাসওয়ার্ড না পাঠানোর পরিবর্তে এটিকে পুনরায় সেট করার অনুমতি দেওয়া ভাল (নিশ্চিত করুন যে পাসওয়ার্ড পুনরায় সেট করা কেবলমাত্র সীমিত সময়ের জন্যই করা যেতে পারে)।
হ্যাশ ফাংশন প্রয়োগ করা একমুখী ক্রিয়াকলাপ; এরপরে এটি মূল তথ্যটি প্রকাশ না করেই যাচাইয়ের জন্য নিরাপদে ব্যবহার করা যেতে পারে; পাসওয়ার্ডগুলির জন্য, একটি ব্রুটি ফোর্স পদ্ধতিটি তুলনামূলকভাবে স্বল্প দৈর্ঘ্য এবং অনেক লোকের পাসওয়ার্ডের দুর্বল নির্বাচনের কারণে এটি উদঘাটন করার একটি সম্ভাব্য পন্থা।
MD5 বা SHA1 এর মতো হ্যাশিং অ্যালগরিদমগুলি একটি পরিচিত হ্যাশ মানের বিপরীতে ফাইল সামগ্রী যাচাই করার জন্য তৈরি করা হয়েছিল। তারা যথাযথ থাকা সত্ত্বেও এই ভেরিফিকেশনটিকে যত তাড়াতাড়ি সম্ভব তত্ক্ষণাতিত্বে আনতে ব্যাপকভাবে অনুকূলিত হয়েছেন। তাদের অপেক্ষাকৃত সীমিত আউটপুট স্পেসের কারণে জ্ঞাত পাসওয়ার্ড এবং তাদের সম্পর্কিত হ্যাশ আউটপুট, রংধনু সারণী সহ একটি ডাটাবেস তৈরি করা সহজ ছিল।
হ্যাশ করার আগে পাসওয়ার্ডে একটি লবণ যুক্ত করা এটি একটি রেইনবো টেবিলকে অকেজো করে দেবে, তবে সাম্প্রতিক হার্ডওয়্যার অগ্রগতিতে ব্রুট ফোর্স অনুসন্ধানগুলি একটি কার্যকর পদ্ধতি তৈরি করেছে। এজন্য আপনার একটি হ্যাশিং অ্যালগরিদম প্রয়োজন যা ইচ্ছাকৃতভাবে ধীর এবং অপ্টিমাইজ করা সহজ impossible এটি ভবিষ্যতের প্রমাণ হিসাবে বিদ্যমান পাসওয়ার্ড হ্যাশগুলি যাচাই করার ক্ষমতাকে প্রভাবিত না করে দ্রুত হার্ডওয়্যারের জন্য লোড বাড়িয়ে তুলতে সক্ষম হওয়া উচিত।
বর্তমানে দুটি জনপ্রিয় পছন্দ উপলব্ধ রয়েছে:
- PBKDF2 (পাসওয়ার্ড ভিত্তিক কী ডেরিভেশন ফাংশন v2)
- বিসিআরপিট (ওরফে ব্লোফিশ)
এই উত্তরটি bcrypt সহ একটি উদাহরণ ব্যবহার করবে।
প্রজন্ম
একটি পাসওয়ার্ড হ্যাশ এভাবে তৈরি করা যেতে পারে:
$password = 'my password';
$random = openssl_random_pseudo_bytes(18);
$salt = sprintf('$2y$%02d$%s',
13, // 2^n cost factor
substr(strtr(base64_encode($random), '+', '.'), 0, 22)
);
$hash = crypt($password, $salt);
লবণের সাথে openssl_random_pseudo_bytes()
ডেটা তৈরি করা হয় যা এলোমেলো ব্লবের ডেটা তৈরি করে যা এরপরে চালিত হয় base64_encode()
এবং strtr()
প্রয়োজনীয় বর্ণমালার সাথে মেলে [A-Za-z0-9/.]
।
crypt()
কর্ম সঞ্চালিত আলগোরিদিম (উপর ভিত্তি করে হ্যাশ $2y$
পটকা মাছ জন্য), খরচ ফ্যাক্টর 22 অক্ষরের লবণ (13 একটি গুণক একটি 3GHz মেশিনে মোটামুটিভাবে 0.40s নেয়)।
ভ্যালিডেশন
একবার আপনি ব্যবহারকারীর তথ্য সম্বলিত সারিটি আনার পরে, আপনি এই পদ্ধতিতে পাসওয়ার্ডটি বৈধতা দিন:
$given_password = $_POST['password']; // the submitted password
$db_hash = $row['Password']; // field with the password hash
$given_hash = crypt($given_password, $db_hash);
if (isEqual($given_hash, $db_hash)) {
// user password verified
}
// constant time string compare
function isEqual($str1, $str2)
{
$n1 = strlen($str1);
if (strlen($str2) != $n1) {
return false;
}
for ($i = 0, $diff = 0; $i != $n1; ++$i) {
$diff |= ord($str1[$i]) ^ ord($str2[$i]);
}
return !$diff;
}
একটি পাসওয়ার্ড যাচাই করতে, আপনি crypt()
আবার কল করেন তবে আপনি আগের গণনা করা হ্যাশকে লবণের মান হিসাবে পাস করেন। প্রদত্ত পাসওয়ার্ড হ্যাশের সাথে মিলে গেলে ফেরতের মান একই হ্যাশ দেয় yield হ্যাশ যাচাই করতে, সময় সময় আক্রমণ এড়াতে প্রায়শই একটি ধ্রুবক-সময় তুলনা ফাংশন ব্যবহার করার পরামর্শ দেওয়া হয়।
পিএইচপি 5.5 সহ পাসওয়ার্ড হ্যাশিং
পিএইচপি 5.5 পাসওয়ার্ড হ্যাশিং ফাংশনগুলি প্রবর্তন করেছে যা আপনি উপরের পদ্ধতিটি হ্যাশিং সহজ করার জন্য ব্যবহার করতে পারেন:
$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 13]);
এবং যাচাই করা হচ্ছে:
if (password_verify($given_password, $db_hash)) {
// password valid
}
আরও দেখুন: password_hash()
,password_verify()