PHP Strings & Patterns
PHP String Manipulation পর্ব-২: PHP Cryptography
PHP String Manipulation দ্বিতীয় পর্বে আপনাকে স্বাগতম। এই পর্বে আমরা String এর cryptography, Encryption, Decryption,Encoding, Decoding এবং Hashing কি এবং কিভাবে কাজ করে তার বিস্তারিত জানব। চলুন শুরু করা যাক :
Cryptography, Encryption, Decryption সম্পূর্ণ আলাদা word হলেও Encryption এবং Decryption শব্দ দুটি Cryptography এর ই অংশ। তো চলুন তাহলে প্রথমে জেনে নেয়া যাক Cryptography কি?
Cryptography কি? এটা কীভাবে কাজ করে?
মূলতঃ কম্পিউটার বিজ্ঞানে এমনকি কম্পিউটার আবিষ্কারের পূর্বেও তথ্য গোপন বা লুকানোর পদ্ধতি কে বলা হয় cryptography. ব্যাপারটা বুঝানোর জন্য আপনাদেরকে একটা সত্যিকারের গল্প বলি, আমি যখন HSC তে পড়ি তখন আমি আমার X কে এই তিনটা শব্দ SMS করি:
J Mpwf Zpv
SMS এর পরের গল্পটি একটু পরে আপনি নিজেই বুঝতে পারবেন। তার আগে SMS টি কি সেটা বুঝে নেয়া যাক। এখানে আমি প্রতি লেটারের জন্য পরের লেটার টি নিয়েছি । বলা যায় প্রতি লেটারের সাথে এক যোগ করেছি । এখন এটা থেকে আসল টেক্সট পেতে হলে আপনাকে প্রতি লেটারের জন্য আগের লেটার নিতে হবে। তখন আসল লেখা টি হবে ঠিক নিচের মতো :p
I Love You
কতই মজার তাইনা!!
এখন আসি আসল ব্যাখ্যায়। এই যে চালাকিটা করলাম এই নিয়মটিই হল Cryptography. আর অই যে SMS টিকে উল্টাপাল্টা করে “J Mpwf Zpv” এইটা করলাম, এটাকে বলে এনক্রিপ্টেড(Encrypted বা Encryption) ম্যাসেজ। আর যে চালাকি কৌশল অবলম্বন করে অর্থাৎ, প্রতিটা অক্ষরের পরের অক্ষরটা বসিয়ে একটা উল্টাপাল্টা ম্যাসেজ বানাইছি। বলা যায় প্রতি লেটারের সাথে এক যোগ করেছি । তাহলে মুল জিনিস্টা হল ১। একে বলে কি “KEY” ভ্যালু। এখন আমি যখন আমার X কে বলে দিলাম আমার ম্যাসেজের কি (KEY) ভ্যালুটা হল ১ তখন সে ঠিক একইভাবে আবার ১ ঘর করে এগিয়ে এসে আসল ম্যাসেজটি উদ্ধার করল। যখন সে আসল ম্যাসেজটি উদ্ধার করল তখন সেই ম্যাসেজটিকে বলে ডিক্রিপ্টেড(Decrypted বা Decryption) ম্যাসেজ। ক্রিপ্টোগ্রাফির ভাষায় এই পদ্ধতিকে বলে চেজার সাইফার ( Caesar Cipher) এলগরিদম। এটা খুবই প্রাথমিক লেভেলের একটি এলগরিদম।। এর থেকে আরো অনেক জটিল ও মজার এলগরিদম আছে।।
Cipher: যে algorithm ব্যাবহার করে তথ্য বা ডাটা লুকান হয় বা লুকায়িত ডাটা কে পুনরদ্ধার করা হইয় তাকে cipher বলে ।
PHP তে কিভাবে যেকোনো Text কে Encryption এবং Decryption করবেন?
PHP তে যেকোনো Text কে Encryption এবং Decryption করার জন্য আপনি php_openssl extension টি ব্যবহার করতে পারেন। এর জন্য আপনাকে প্রথমে php.ini ফাইল এ php_openssl.dll (উইন্ডোজ হলে) এবং php_openssl.so (লিনাক্স হলে ) enable করে দিতে হবে। অর্থাৎ সামনের সেমিকোলন টি রিমুভ করতে হবে। নিচের ছবিতে লক্ষ্য করুন :
এবার চলুন Openssl ব্যবহার করে একটা Plain Text কে encryption এবং Decryption করা যাক।
<?php //$key should have been previously generated in a cryptographically safe way, like openssl_random_pseudo_bytes $plaintext = "message to be encrypted"; $cipher = "aes-128-gcm"; if (in_array($cipher, openssl_get_cipher_methods())) { $ivlen = openssl_cipher_iv_length($cipher); $iv = openssl_random_pseudo_bytes($ivlen); $key="w3programmers"; $ciphertext = openssl_encrypt($plaintext, $cipher, $key, $options=0, $iv, $tag); //store $cipher, $iv, and $tag for decryption later $original_plaintext = openssl_decrypt($ciphertext, $cipher, $key, $options=0, $iv, $tag); echo "<b>Cipher Text:</b> ",$ciphertext,"<br>"; echo "<b>Original Text:</b> ",$original_plaintext."\n"; } ?>
Output
ব্যাখ্যা:এইবার ব্যাখ্যায় যাওয়া যাক, এখানে লাইন নম্বর ৩ এ আমরা যেই Plain Text কে Encrypt করব, সেটি $plaintext নামক variable এ রেখেছি, ৪ নম্বর লাইনে যেই algorithm ব্যবহার করে আমরা Encryption করব সেটিকে $cipher variable এ রাখি , এখানে আমরা aes-128-gcm algorithm কে রেখেছি। ৫ নম্বর লাইনে আমরা aes-128-gcm algorithm টি openssl cipher method লিস্ট এ আছে কিনা প্রথমে তা চেক করি। ৭ নম্বর লাইনে আমরা আমাদের chiper Method এর vector length বের করি। ৮ নম্বর লাইনে Initial Vector lengh থেকে initial vector বা iv বের করি। ৯ নম্বর লাইনে আমরা আমাদের key কে set করি। আর এতো সব করি মূলতঃ আমাদের ১০ এবং ১২ নম্বর লাইনে আমাদের encryption এবং Decryption Method দুটির জন্য।
Encoding এবং Decoding কি ? এটি কিভাবে কাজ করে?
একটা ডাটাকে ভিন্ন একটা ডাটা ফরম্যাটে পরিবর্তন করাকে বলা হয় Encoding. আরেকটু ভালো ভাবে বুঝে নেয়া যাক , এই যে আপনি বাংলা বর্ণে এই লেখাটি পড়ছেন, এই লেখাটি কম্পিউটার এভাবে তার মেমোরীতে রাখেনি। কম্পিউটার তার মেমোরীতে এটাকে বাইনারী ফরম্যাটে স্টোর করে রেখেছে। কিন্তু আমরা যখন আমাদের ব্রাউজারে বা এপে এই ডাটা দেখছি তখন কিন্তু আমরা বাইনারী সংখ্যার পরিবর্তে বাংলা বর্ণে দেখছি, যে কারণে আমরা সেটা পড়তে পারছি। এই যে একটা ডাটাকে ভিন্ন একটা ডাটা ফরম্যাটে পরিবর্তন করা যাতে করে অন্য কোনো সিস্টেম সেটাকে সহজে ব্যবহার করতে পারে সেটাকেই বলা হয় Encoding.
কোনো একটা ডাটাকে যে পদ্ধতিতে Encoding করে পরিবর্তন করা হলো, সেই একই পদ্ধতিতেই তাকে আবার আগের ফরম্যাটে নেওয়াকে বলা হয় Decoding.
Encoding এবং Decoding এর মেথডগুলো সব জায়গায় একই এবং সেটা সবার জন্য উন্মুক্ত। যে কেউ চাইলেই এই মেথড ব্যবহার করতে পারে এবং সেটাই আসলে মূল লক্ষ্য।
PHP তে কিভাবে যেকোনো Text কে encode এবং decode করবেন?
PHP তে base64_encode() function দিয়ে যেকোনো Text কে encode এবং সেই encoded string কে base64_decode() function দিয়ে খুব সহজে decode করতে পারবেন। নিচের উদাহরণে দেখুন।
<?php $str = 'This is an encoded string'; echo base64_encode($str); ?> <?php $str = 'VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw=='; echo base64_decode($str); ?>
Output
VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw==
This is an encoded string
PHP তে কিভাবে একটা image কে base_64 এ encode এবং decode করবেন ?
PHP তে একটা image কে base_64 এ encode এবং decode করার জন্য নিচের code টি লক্ষ্য করুন:
<?php $img_file = 'rose.jpg'; // Read image path, convert to base64 encoding $imgData = base64_encode(file_get_contents($img_file)); // Format the image SRC: data:{mime};base64,{data}; $src = 'data: '.mime_content_type($img_file).';base64,'.$imgData; // Echo out a sample image echo '<img src="'.$src.'">';
convert_uuencode এবং convert_uudecode function দিয়ে Text Encode এবং Decode
<?php $some_string = "I love PHP!"; $encoded= convert_uuencode($some_string); $decoded=convert_uudecode("+22!L;W9E(%!(4\"$`"); echo $encoded,"<br>"; echo $decoded; ?>
Output
+22!L;W9E(%!(4"$` I love PHP!
Hasing কি ? এটি কিভাবে কাজ করে?
যখন কোনো ডাটাকে এনক্রিপ্ট করা যায় কিন্তু সেটাকে আবার ডিক্রিপ্ট করে মূল ডাটাকে বের করা যায় না, তখন এটাকে বলা হয় হ্যাশিং (Hashing)। এটাকে আবার one way encryption ও বলে। হ্যাশিংয়ের মাধ্যমে গবেষণার গুরুত্বপূর্ণ তথ্য,পাসওয়ার্ড,ক্রেডিট কার্ড নম্বর,সংবেদনশীল তথ্য ইত্যাদি এনক্রিপ্ট করা হয় যাতে কেউ তা সহজে বের করতে না পারে। তবে হ্যাকাররা সাধারণত ব্রুট ফোর্স অ্যাটাক করে হ্যাশ ক্র্যাক করার চেষ্টা করে।অর্থাৎ সম্ভাব্য ডাটাসমূহকে বিভিন্ন বিন্যাসে সাজিয়ে হ্যাশিং করে যদি মূল ডাটার হ্যাশের সাথে মিলে যায় তাহলে হ্যাশটি ক্র্যাক করা যায়। তাই কোনো হ্যাশিংই ১০০% নিরাপদ সে কথা বলা যায়না, আর তাইতো কিছুদিন পর পর নিত্য নতুন Hashing function এবং পদ্দ্বতি বের হয়। PHP তে md5(), sha1(), crypt() এবং pasword_hash() এই চারটি Hashing ফাঙ্কশন উল্লেখযোগ্য ।
md5() এবং sha1() function
PHP তে md5() এবং sha1() এই দুটি function একই রকম হ্যাশিং করে, এদের মধ্যে মূল পার্থক্য হচ্ছে md5 এর এনক্রিপ্টেড আউটপুট এর মোট character সংখ্যা ৩২ টি থাকে , অন্য দিকে sha1() ফাঙ্কশনের এনক্রিপ্টেড আউটপুট এর মোট character সংখ্যা ৪০ টি থাকে। নিচের উদাহরণে দেখুন :
<?php echo sha1("123456"); echo "\n <br>"; echo md5("123456"); ?>
Output
7c4a8d09ca3762af61e59520943dc26494f8941b e10adc3949ba59abbe56e057f20f883e
crypt() Function
PHP তে হ্যাশিং এর জন্য crypt() function এর মূল সুবিধা হচ্ছে এখানে আপনি অতিরিক্ত salt ব্যবহার করতে পারবেন। আর এতে সুবিধা হচ্ছে এটি md5() function এবং sha1() ফাঙ্কশনের তুলনায় অধিক নিরাপদ। নিচের উদাহরণে দেখুন :
<?php $hashed_password = crypt('mypassword','12'); //echo "Encrypted Value: $hashed_password \n"; if (hash_equals($hashed_password, crypt("mypassword", '12'))) { echo "Password verified!"; } ?>
Output
Password verified!
এখন যদি আপনি password ঠিক রাখলেন কিন্তু salt পরিবর্তন করে দেন , তাহলে আগের মতো password verify করবেনা।
<?php $hashed_password = crypt('mypassword','12'); //echo "Encrypted Value: $hashed_password \n"; if (hash_equals($hashed_password, crypt("mypassword", '13'))) { echo "Password verified!"; } else{ echo "Your Passowrd Not Valid"; } ?>
Output
Your Passowrd Not Valid
এছাড়াও আপনি বিভিন্ন hash type ব্যবহার করে অনেক complex password তৈরী করতে পারেন। নিচের উদাহরণে দেখুন :
<?php /* These salts are examples only, and should not be used verbatim in your code. You should generate a distinct, correctly-formatted salt for each password. */ if (CRYPT_STD_DES == 1) { echo 'Standard DES: ' . crypt('rasmuslerdorf', 'rl') . "\n"; } if (CRYPT_EXT_DES == 1) { echo 'Extended DES: ' . crypt('rasmuslerdorf', '_J9..rasm') . "\n"; } if (CRYPT_MD5 == 1) { echo 'MD5: ' . crypt('rasmuslerdorf', '$1$rasmusle$') . "\n"; } if (CRYPT_BLOWFISH == 1) { echo 'Blowfish: ' . crypt('rasmuslerdorf', '$2a$07$usesomesillystringforsalt$') . "\n"; } if (CRYPT_SHA256 == 1) { echo 'SHA-256: ' . crypt('rasmuslerdorf', '$5$rounds=5000$usesomesillystringforsalt$') . "\n"; } if (CRYPT_SHA512 == 1) { echo 'SHA-512: ' . crypt('rasmuslerdorf', '$6$rounds=5000$usesomesillystringforsalt$') . "\n"; } ?>
Output
Standard DES: rl.3StKT.4T8M Extended DES: _J9..rasmBYk8r9AiWNc MD5: $1$rasmusle$rISCgZzpwk3UhDidwXvin0 Blowfish: $2a$07$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi SHA-256: $5$rounds=5000$usesomesillystri$KqJWpanXZHKq2BOB43TSaYhEWsQ1Lr5QNyPCDH/Tp.6 SHA-512: $6$rounds=5000$usesomesillystri$D4IrlXatmP7rx3P3InaxBeoomnAihCKRVQP22JZ6EY47Wc6BkroIuUUBOov1i.S5KPgErtP/EN5mcO.ChWQW21
Password Hashing API
পাসওয়ার্ড তৈরী এবং ভেরিফাই এর জন্য PHP এর সবচেয়ে যুগান্তকারী API হচ্ছে Password Hashing API. যা PHP 5.5 থেকে চালু হয়। এটি PHP এর এই যাবৎ কালের যতগুলো পাসওয়ার্ড ফাঙ্কশন যেমন md5, sha1 এবং crypt ফাঙ্কশনের তুলনায় অনেক বেশি নিরাপদ এবং ব্যবহারের দিক দিয়ে অনেক বেশি সহজ। নতুন Password Hasing API তে চারটি সহজ ফাংশন রয়েছে :
- password_hash() – পাসওয়ার্ডকে হ্যাশ করার জন্য ব্যবহৃত হয়।
- password_verify() – পাসওয়ার্ডকে তার হ্যাশ এর বিপরীতে ভেরিফাই এর জন্য ব্যবহৃত হয়।
- password_needs_rehash() – একটি হ্যাশ পাসওয়ার্ডকে নতুন করে রিহ্যাশ করার জন্য ব্যবহৃত হয়।
- password_get_info() – একটি পাসওয়ার্ড কে হ্যাশিং করার সময় কি এলগোরিদম এবং অপশনস ব্যবহার হয়েছে , তা জানার জন্য ব্যবহৃত হয়।
password_hash()
password_hash() দিয়ে আপনি খুব সহজে যেকোনো password কে হ্যাশ করতে পারেন। আবার আপনি চাইলে পাসওয়ার্ড হ্যাশিং এর সময় নির্দিষ্ট এলগোরিদম এবং আরো অনেক ধরণের options ব্যবহার করে আপনার পাসওয়ার্ডকে অনেক বেশি নিরাপদ করতে পারেন। চলুন নিচে syntax দেখা যাক :
string password_hash ( string $password , int $algo [, array $options ] )
বর্তমানে password_hash() function নিচের তিনটি এলগোরিদম কে সাপোর্ট করে :
- PASSWORD_DEFAULT
- PASSWORD_BCRYPT
- PASSWORD_ARGON2I
এবার চলুন একটা উদাহরণ দেখা যাক :
<?php /** * We just want to hash our password using the current DEFAULT algorithm. * This is presently BCRYPT, and will produce a 60 character result. * * Beware that DEFAULT may change over time, so you would want to prepare * By allowing your storage to expand past 60 characters (255 would be good) */ echo password_hash("rasmuslerdorf", PASSWORD_DEFAULT); ?>
Possible Output
$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a
Manually Cost Setting এর মাধ্যমে Password Hashing
<?php /** * In this case, we want to increase the default cost for BCRYPT to 12. * Note that we also switched to BCRYPT, which will always be 60 characters. */ $options = [ 'cost' => 12, ]; echo password_hash("rasmuslerdorf", PASSWORD_BCRYPT, $options); ?>
Possible Output
$2y$12$QjSH496pcT5CEbzjD/vtVeH03tfHKFy36d4J0Ltp3lRtee9HDxY3K
Manually Salt Setting এর মাধ্যমে Password Hashing
<?php /** * Note that the salt here is randomly generated. * Never use a static salt or one that is not randomly generated. * * For the VAST majority of use-cases, let password_hash generate the salt randomly for you */ $options = [ 'cost' => 11, 'salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM), ]; echo password_hash("rasmuslerdorf", PASSWORD_BCRYPT, $options); ?>
Possible Output
$2y$11$q5MkhSBtlsJcNEVsYh64a.aCluzHnGog7TQAKVmQwO9C8xb.t89F.
Argon2 এর মাধ্যমে Password Hashing
<?php echo 'Argon2 hash: ' . password_hash('rasmuslerdorf', PASSWORD_ARGON2I); ?>
Possible Output
Argon2 hash: $argon2i$v=19$m=1024,t=2,p=2$YzJBSzV4TUhkMzc3d3laeg$zqU/1IN0/AogfP4cmSJI1vc8lpXRW9/S0sYY2i2jHT0
password_verify()
password_verify() ফাঙ্কশন দিয়ে যেকোনো পাসওয়ার্ডকে তার হ্যাশ এর বিপরীতে ভেরিফাই করতে পারেন। নিচের উদাহরণ দেখুন :
<?php // See the password_hash() example to see where this came from. $hash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq'; if (password_verify('rasmuslerdorf', $hash)) { echo 'Password is valid!'; } else { echo 'Invalid password.'; } ?>
Output
Password is valid!