এই পর্বে যা শিখবেন
- Confidentiality, integrity, authentication আর non-repudiation — কোনটির জন্য কোন cryptographic হাতিয়ার
- AES কীভাবে block ধরে কাজ করে, ECB-র “পেঙ্গুইন সমস্যা”, CBC, CTR আর AEAD — আর nonce reuse কেন সর্বনাশ
- Hash-এর তিন নিরাপত্তা-গুণ, avalanche, birthday bound-এর হিসাব, HMAC আর password রাখার সঠিক উপায়
- Diffie–Hellman আর RSA ছোট সংখ্যায় হাতে-কলমে — key তৈরি, encrypt, sign, verify — আর বাস্তবে কেন padding ও বড় key লাগে
- Hybrid encryption, forward secrecy, ভালো randomness, post-quantum cryptography আর AI-এর crypto-পরামর্শ যাচাইয়ের উপায়
১ · Cryptography কী চায় — চার লক্ষ্য আর তাদের হাতিয়ার
ধরুন রাজশাহী থেকে আপনি ঢাকার এক বন্ধুকে কুরিয়ারে একটি চিঠি পাঠাচ্ছেন। পথে চিঠিটি অনেক হাত ঘোরে — কাউন্টারের কর্মী, ট্রাকের চালক, বাছাই-কেন্দ্র। ইন্টারনেটে আপনার প্রতিটি packet-এর অবস্থাও ঠিক তাই: বাসার Wi-Fi router, ISP-র যন্ত্র, IXP, সমুদ্রের নিচের তার, অন্য দেশের router — যে কেউ চাইলে পড়তে, বদলাতে বা জাল চিঠি ঢোকাতে পারে। পর্ব ৪৬-এ (নেটওয়ার্ক নিরাপত্তার ভিত্তি) দেখেছেন হুমকিগুলো কী কী। এই পর্বে দেখব সেই হুমকির বিরুদ্ধে গণিতের হাতিয়ার — cryptography.
প্রথমে চারটি আলাদা প্রশ্ন আলাদা করে চেনা দরকার, কারণ প্রতিটির হাতিয়ার আলাদা:
| লক্ষ্য | প্রশ্নটি | মূল হাতিয়ার | কুরিয়ারের উপমা |
|---|---|---|---|
| Confidentiality (গোপনীয়তা) | অন্য কেউ পড়তে পারবে? | Encryption: AES, ChaCha20 | তালা দেওয়া বাক্স |
| Integrity (অখণ্ডতা) | পথে কেউ বদলেছে? | Hash (জানা আসল ছাপের সাথে মেলানো), MAC, AEAD | সিল-গালা করা খাম |
| Authentication (পরিচয়) | সত্যিই কি সে-ই পাঠিয়েছে? | MAC (ভাগ করা চাবি), digital signature, certificate | পরিচিত হাতের লেখা |
| Non-repudiation (অস্বীকার ঠেকানো) | পরে কি প্রেরক “আমি পাঠাইনি” বলতে পারবে? | শুধু digital signature | সাক্ষীর সামনে দেওয়া সই |
পর্ব ০৯-এ (Error detection) দেখেছেন, CRC আর checksum দুর্ঘটনাজনিত ভুল ধরে, কিন্তু ইচ্ছাকৃত বদল ঠেকায় না — আক্রমণকারী ডেটা বদলে নতুন CRC বসিয়ে দিতে পারে, কারণ CRC হিসাব করতে কোনো গোপন কিছু লাগে না। Cryptography-র সাথে এখানেই পার্থক্য: এর নিরাপত্তা দাঁড়িয়ে থাকে একটি গোপন চাবির ওপর, বা এমন গাণিতিক সমস্যার ওপর যা সমাধান করতে মহাবিশ্বের বয়সের চেয়ে বেশি সময় লাগে।
১৮৮৩ সালে ডাচ ভাষাবিদ ও ক্রিপ্টোগ্রাফার Auguste Kerckhoffs লিখেছিলেন: একটি ব্যবস্থা নিরাপদ হতে হবে এমনকি যদি চাবি ছাড়া তার সবকিছু শত্রু জেনে যায়। একে বলে Kerckhoffs-এর নীতি. তাই AES, SHA-256, RSA — সবকিছুর নকশা প্রকাশ্য, হাজারো গবেষক বছরের পর বছর ভাঙার চেষ্টা করেছেন। গোপন শুধু চাবি। “আমাদের নিজস্ব গোপন algorithm” মানে নিরাপত্তা নয় — মানে কেউ এখনো যাচাই করেনি।
প্রায় দুই হাজার বছর আগে Julius Caesar বর্ণমালার প্রতিটি অক্ষর তিন ঘর সরিয়ে লিখতেন বলে বর্ণনা আছে (A → D) — মাত্র ২৫টি সম্ভাব্য চাবি, হাতে গুনেই ভাঙা যায়। সাধারণ substitution cipher-এ (প্রতিটি অক্ষরের বদলে আরেকটি অক্ষর) চাবি অনেক, কিন্তু নবম শতকে আরব পণ্ডিত al-Kindi দেখান অক্ষরের ব্যবহার-হার গুনেই (frequency analysis) তা ভাঙা যায়। দ্বিতীয় বিশ্বযুদ্ধে জার্মানির Enigma যন্ত্র প্রতিটি অক্ষরের পরে নিজের চাকা ঘুরিয়ে substitution বদলাত; পোল্যান্ডের গণিতবিদেরা (Marian Rejewski প্রমুখ) ১৯৩০-এর দশকে প্রথম সাফল্য পান, পরে ব্রিটেনের Bletchley Park-এ Alan Turing-সহ অনেকে যন্ত্র বানিয়ে নিয়মিত বার্তা পড়েন — ইতিহাসবিদদের অনেকে মনে করেন এতে যুদ্ধ সংক্ষিপ্ত হয়েছিল। শিক্ষাটি আজও খাটে: যন্ত্র যত জটিলই হোক, ব্যবহারের ভুল (একই শুরুর সেটিং, অনুমানযোগ্য বার্তা) নিরাপত্তা ভাঙে।
২ · One-time pad আর brute force — নিখুঁত গোপনীয়তার দাম
একটি cipher-এর তিনটি অংশ: plaintext (মূল লেখা), চাবি, আর ciphertext (তালাবন্ধ লেখা)। সবচেয়ে সরল আর সবচেয়ে শক্তিশালী cipher-টি দাঁড়িয়ে আছে XOR-এর ওপর — যে কাজটি পর্ব ০৯-এ CRC-তে দেখেছেন। XOR-এর জাদু: (P ⊕ K) ⊕ K = P. একই চাবি দুবার XOR করলে আগের জিনিস ফেরত আসে।
One-time pad-এ চাবি হয় বার্তার সমান লম্বা, সম্পূর্ণ এলোমেলো, আর মাত্র একবার ব্যবহৃত। ১৯৪৯ সালে Claude Shannon প্রমাণ করেন এটি নিখুঁতভাবে গোপন (perfect secrecy): ciphertext C দেখে প্রতিটি সম্ভাব্য plaintext সমান সম্ভাব্য থাকে, কারণ যেকোনো P'-এর জন্য একটি চাবি K' = C ⊕ P' আছে যা ঠিক ওই ciphertext দেয়। অসীম কম্পিউটার শক্তি দিয়েও কিছু শেখা যায় না।
তাহলে সবাই এটি ব্যবহার করে না কেন? তিনটি কারণে। (১) চাবি বার্তার সমান লম্বা — ১ GB ভিডিও পাঠাতে আগে থেকে ১ GB গোপন চাবি নিরাপদে পৌঁছাতে হবে; যদি সেটা নিরাপদে পৌঁছানোই যায়, ভিডিওটাই সেভাবে পাঠানো যেত। (২) চাবি একবারের বেশি ব্যবহার করলেই সব ভেঙে পড়ে (অংশ ৩-এ হাতে-কলমে দেখবেন)। (৩) এটি শুধু গোপনীয়তা দেয়, অখণ্ডতা নয় — ciphertext-এর একটি bit উল্টালে plaintext-এর ঠিক সেই bit উল্টে যায়, আর প্রাপক টেরও পান না।
আধুনিক পথ: ছোট চাবি, “গণনাগতভাবে” নিরাপদ
আধুনিক cipher ছোট চাবি (১২৮ বা ২৫৬ bit) থেকে কাজ চালায়। নিরাপত্তার দাবি তখন: “চাবি না জেনে ভাঙার সবচেয়ে ভালো জানা পথ হলো সব চাবি একে একে চেষ্টা করা” — brute force. তাহলে প্রশ্ন দাঁড়ায়, সব চাবি চেষ্টা করতে কত সময়? একটি উদার হিসাব করি — আক্রমণকারীর পক্ষে সবকিছু বাড়িয়ে ধরে:
| চাবির দৈর্ঘ্য | মোট চাবি | ১০০ কোটি যন্ত্র × সেকেন্ডে ১০১২ চেষ্টা = ১০২১/সেকেন্ড |
|---|---|---|
| ৫৬ bit (পুরোনো DES) | 256 ≈ 7.2 × 1016 | এক সেকেন্ডের হাজার ভাগের এক ভাগেরও কম; একটিমাত্র যন্ত্রে প্রায় ২০ ঘণ্টা |
| ৮০ bit | 280 ≈ 1.2 × 1024 | প্রায় ২০ মিনিট |
| ১২৮ bit (AES-128) | 2128 ≈ 3.4 × 1038 | 3.4 × 1017 সেকেন্ড ≈ ১০৮০ কোটি বছর |
| ২৫৬ bit (AES-256) | 2256 ≈ 1.2 × 1077 | প্রায় ৩.৭ × ১০৪৮ বছর — তুলনাই অর্থহীন |
হিসাবটা নিজে মিলিয়ে দেখুন: 3.4 × 1038 ÷ 1021 = 3.4 × 1017 সেকেন্ড; এক বছরে প্রায় 3.16 × 107 সেকেন্ড, তাই ≈ 1.08 × 1010 বছর — মহাবিশ্বের বয়সের (প্রায় ১৩৮০ কোটি বছর) কাছাকাছি। গড়ে অর্ধেক চাবি চেষ্টা করলেই পাওয়া যায়, তবু সেটা ৫০০ কোটি বছরের বেশি। আর এখানে আমরা ধরে নিয়েছি পৃথিবীর প্রায় প্রতিটি মানুষের হাতে একটি করে অতি-দ্রুত যন্ত্র! প্রতি ১ bit বাড়ালে কাজ দ্বিগুণ হয় — এটাই exponential বৃদ্ধির শক্তি। ১৯৯৮ সালে EFF-এর বানানো একটি বিশেষ যন্ত্র (“Deep Crack”) ৫৬-bit DES-এর একটি চাবি প্রায় ৫৬ ঘণ্টায় বের করে দেখিয়েছিল যে DES-এর দিন শেষ।
তাই আধুনিক cipher ভাঙার খবর প্রায় কখনো “brute force” নয়। বাস্তবের ভাঙন আসে অন্য পথে: ভুল mode, nonce-এর পুনর্ব্যবহার, দুর্বল random সংখ্যা, চুরি হওয়া চাবি, বা সময়ের পার্থক্য মেপে চাবি আন্দাজ করা (timing attack). এই পর্বের বাকি অংশ মূলত এই ফাঁদগুলো চেনার গল্প।
৩ · Symmetric encryption — AES, mode আর nonce-এর নিয়ম
Symmetric encryption-এ তালা দেওয়া আর খোলার চাবি একই — বাসার দরজার চাবির মতো, যার কাছে কপি আছে সে-ই খুলতে পারে। এটি অত্যন্ত দ্রুত: আধুনিক CPU-তে AES-এর জন্য বিশেষ নির্দেশ (যেমন Intel/AMD-র AES-NI, ARM-এর crypto extension) থাকায় এক core সেকেন্ডে কয়েক GB এনক্রিপ্ট করতে পারে। তাই আপনার ভিডিও, ফাইল, ওয়েবপেজ — সব বড় ডেটা symmetric cipher দিয়েই চলে।
Block cipher আর AES
Block cipher একটি নির্দিষ্ট আকারের টুকরো (block) নিয়ে কাজ করে: চাবি ঠিক থাকলে প্রতিটি সম্ভাব্য ইনপুট block-কে একটি আলাদা আউটপুট block-এ নেয়, আর চাবি ছাড়া এই ম্যাপিং এলোমেলো দেখায়। AES (Advanced Encryption Standard) এর রাজা: block ১২৮ bit (১৬ বাইট), চাবি ১২৮, ১৯২ বা ২৫৬ bit, আর চাবির দৈর্ঘ্য অনুযায়ী ১০, ১২ বা ১৪ round. প্রতিটি round-এ চারটি কাজ: SubBytes (প্রতিটি বাইট একটি টেবিল দিয়ে বদলানো — অ-রৈখিকতা আনে), ShiftRows আর MixColumns (বাইটগুলো ছড়িয়ে-মিশিয়ে দেওয়া, যাতে একটি বাইটের প্রভাব পুরো block-এ যায়), আর AddRoundKey (round-এর চাবি XOR). শেষ round-এ MixColumns বাদ থাকে। ১৯৯৭–২০০০ সালের প্রকাশ্য প্রতিযোগিতায় বেলজিয়ামের Joan Daemen আর Vincent Rijmen-এর Rijndael জেতে, আর ২০০১ সালে NIST তা FIPS 197 হিসেবে প্রকাশ করে।
Mode — block cipher দিয়ে লম্বা বার্তা
AES একবারে মাত্র ১৬ বাইট নেয়। ১ MB ফাইল এনক্রিপ্ট করতে block-গুলো কীভাবে জোড়া হবে, সেই নিয়মকে বলে mode of operation. এখানেই বেশিরভাগ ভুল হয়:
ECB — কখনো নয়
ECB: প্রতিটি block আলাদাভাবে এনক্রিপ্ট। একই plaintext block সবসময় একই ciphertext block দেয়, তাই নকশা ফাঁস হয়। বিখ্যাত উদাহরণ: Linux-এর পেঙ্গুইন ছবি ECB-তে এনক্রিপ্ট করলেও পেঙ্গুইনের অবয়ব স্পষ্ট দেখা যায়।
“ECB penguin”CBC — পুরোনো, সাবধানে
CBC: প্রতিটি plaintext block আগের ciphertext block-এর সাথে XOR করে তারপর এনক্রিপ্ট; প্রথমটির জন্য একটি এলোমেলো, অনুমান-অযোগ্য IV. নিজে অখণ্ডতা দেয় না; padding-এর ত্রুটি-বার্তা থেকে plaintext ফাঁসের আক্রমণ (padding oracle) বাস্তবে বহুবার ঘটেছে।
TLS 1.3-এ বাদCTR — block থেকে stream
CTR: AES দিয়ে nonce‖0, nonce‖1, nonce‖2… এনক্রিপ্ট করে একটি keystream বানানো, তারপর plaintext ⊕ keystream. সমান্তরালে চলে, padding লাগে না; কিন্তু nonce-এর পুনর্ব্যবহার মারাত্মক।
AEAD — আজকের ডিফল্ট
AEAD একসাথে গোপনীয়তা আর অখণ্ডতা দেয়: AES-GCM (CTR + একটি গাণিতিক tag) আর ChaCha20-Poly1305 (AES-হার্ডওয়্যারহীন ফোনে দ্রুত)। Tag না মিললে ডিক্রিপ্ট-ই প্রত্যাখ্যাত।
TLS 1.3, QUIC, WireGuard“AEAD”-এর “AD” মানে associated data — যে অংশ এনক্রিপ্ট হয় না কিন্তু বদলানো যাবে না, যেমন packet-এর header. পর্ব ৩৩-এ (QUIC) দেখেছেন, QUIC-এর header খোলা থাকলেও AEAD tag-এ বাঁধা — পথের কোনো যন্ত্র header বদলালে প্রাপক packet ফেলে দেয়। AES-GCM-এ সাধারণত nonce ৯৬ bit আর tag ১২৮ bit.
Stream cipher আর nonce reuse — দুটি ciphertext XOR করলে কী হয়
CTR mode, ChaCha20 বা যেকোনো stream cipher আসলে একটি “নকল one-time pad”: চাবি আর nonce থেকে লম্বা keystream বানিয়ে plaintext-এর সাথে XOR. এখন যদি একই চাবি আর একই nonce দুটি বার্তায় ব্যবহার হয়, keystream-ও একই — আর তখন:
চাবি পুরো উধাও! আক্রমণকারী দুই plaintext-এর XOR পেয়ে গেল, আর একটি বার্তা আন্দাজ করতে পারলে (যেমন HTTP request-এর শুরু প্রায় সবসময় GET /) অন্যটি সরাসরি বেরিয়ে আসে। AES-GCM-এ nonce reuse আরও খারাপ: tag-এর গোপন অংশ বের করে জাল বার্তা বানানোও সম্ভব হয়। তাই নিয়ম: একই চাবিতে nonce কখনো দ্বিতীয়বার নয় — nonce এলোমেলো হতে পারে, বা একটি counter, কিন্তু অবশ্যই অনন্য। নিচের simulator-এ একটি খেলনা block cipher দিয়ে দুটি জিনিস দেখুন: ECB-তে ছবির নকশা ফাঁস হওয়া, আর একই nonce-এ দুটি বার্তার পরিণতি।
// Toy 32-bit block cipher (4-round Feistel) — শেখার জন্য, বাস্তবে ব্যবহার নিষেধ. Real: AES-GCM / ChaCha20-Poly1305.
const KEY = [0x3a7c, 0x91e5, 0x5d02, 0xc4b8];
function E(x) { // encrypt one 4-byte block (as a 32-bit number)
let L = x >>> 16, R = x & 0xffff;
for (const k of KEY) [L, R] = [R, L ^ (((R * 0x9e37 + k) ^ (R >>> 5)) & 0xffff)];
return ((L << 16) | R) >>> 0;
}
const toNum = (s) => [...s].reduce((a, c) => a * 256 + c.charCodeAt(0), 0);
const show = (c) => String.fromCharCode(65 + (c % 26)).repeat(4); // one letter per cipher block
const img = ["########################", "########################",
"........########........", "........########........", "........########........"];
console.log(`${"plaintext".padEnd(24)} ${"ECB: same in -> same out".padEnd(24)} CTR: every block new`);
let ctr = 0;
for (const row of img) {
const blocks = row.match(/.{4}/g);
const ecb = blocks.map(b => show(E(toNum(b)))).join("");
const ctrRow = blocks.map(b => show((toNum(b) ^ E(0x1000 + ctr++)) >>> 0)).join("");
console.log(`${row} ${ecb} ${ctrRow}`);
}
// Stream/CTR nonce reuse: same key + same nonce => same keystream for two messages.
const keystream = (len, nonce) => { const ks = [];
for (let i = 0; ks.length < len; i++) { const w = E(nonce * 256 + i); ks.push(w >>> 24, (w >>> 16) & 255, (w >>> 8) & 255, w & 255); }
return ks.slice(0, len); };
const xor = (a, b) => a.map((x, i) => x ^ b[i]), bytes = (s) => [...s].map(c => c.charCodeAt(0));
const P1 = bytes("TRANSFER 500 TK TO RAHIM"), P2 = bytes("MEET AT GATE 3 AT 9 PM!!");
const ks = keystream(P1.length, 7), C1 = xor(P1, ks), C2 = xor(P2, ks); // nonce 7 used TWICE
console.log("\nC1 xor C2 == P1 xor P2 ?", xor(C1, C2).every((v, i) => v === xor(P1, P2)[i]));
console.log("attacker knows P1, recovers P2:", String.fromCharCode(...xor(xor(C1, C2), P1)));আউটপুট:
plaintext ECB: same in -> same out CTR: every block new
######################## IIIIIIIIIIIIIIIIIIIIIIII LLLLKKKKUUUUQQQQRRRRMMMM
######################## IIIIIIIIIIIIIIIIIIIIIIII SSSSNNNNMMMMCCCCJJJJGGGG
........########........ TTTTTTTTIIIIIIIITTTTTTTT KKKKSSSSZZZZKKKKUUUUXXXX
........########........ TTTTTTTTIIIIIIIITTTTTTTT CCCCCCCCVVVVHHHHVVVVAAAA
........########........ TTTTTTTTIIIIIIIITTTTTTTT FFFFWWWWLLLLNNNNGGGGVVVV
C1 xor C2 == P1 xor P2 ? true
attacker knows P1, recovers P2: MEET AT GATE 3 AT 9 PM!!
বাঁ দিকে একটি “ছবি” — # দিয়ে আঁকা একটি বড় T. ECB কলামে প্রতিটি ৪-অক্ষরের block-এর ciphertext একটি অক্ষর দিয়ে দেখানো হয়েছে: সব #### block হয়েছে IIII, সব .... block হয়েছে TTTT — চাবি না জেনেও T আকৃতিটি স্পষ্ট পড়া যায়। এটাই ECB-র পেঙ্গুইন সমস্যা। CTR কলামে প্রতিটি block-এর counter আলাদা, তাই একই #### প্রতিবার আলাদা অক্ষর হয়েছে — নকশা গায়েব। শেষ দুই লাইনে nonce ৭ দুবার ব্যবহার করা হয়েছে: C1 xor C2 == P1 xor P2 ? true, আর প্রথম বার্তাটি (TRANSFER 500 TK TO RAHIM) জানা থাকায় আক্রমণকারী চাবি ছাড়াই দ্বিতীয়টি পড়ে ফেলল: MEET AT GATE 3 AT 9 PM!!. খেলনা cipher-টি ৪-round-এর একটি ছোট Feistel — শুধু ধারণা দেখানোর জন্য; বাস্তবে AES-GCM বা ChaCha20-Poly1305 ব্যবহার করুন।
২০১০ সালের দিকে Sony PlayStation 3-এর firmware সই করার সময় প্রতিবার একই “এলোমেলো” সংখ্যা ব্যবহার হতো বলে প্রকাশ্য গবেষণায় জানা যায় — সেই ভুল থেকে গোপন চাবিটিই হিসাব করে ফেলা যায়। ক্ষেত্র আলাদা (signature), কিন্তু শিক্ষা একই: “একবার ব্যবহারের” সংখ্যা দ্বিতীয়বার ব্যবহার করলে গণিত আপনার বিরুদ্ধে যায়।
৪ · Hash function — ডেটার আঙুলের ছাপ
জাতীয় পরিচয়পত্রে আপনার আঙুলের ছাপ থাকে। ছাপ দেখে আপনার চেহারা বানানো যায় না, কিন্তু দুজন মানুষের হুবহু এক ছাপ পাওয়া প্রায় অসম্ভব। একটি cryptographic hash ফাংশন ডেটার জন্য ঠিক এই কাজ করে: যেকোনো আকারের ইনপুট থেকে নির্দিষ্ট আকারের আউটপুট (SHA-256-এ ২৫৬ bit = ৬৪টি hex অক্ষর)। কোনো চাবি নেই — যে কেউ হিসাব করতে পারে। নিরাপত্তা আসে তিনটি গুণ থেকে:
- Preimage resistance (এক-মুখী): শুধু hash
hদেখে এমন কোনোxবের করা কার্যত অসম্ভব যাতেH(x) = h. ২৫৬-bit hash-এ সাধারণ চেষ্টায় প্রায় 2256 কাজ। - Second-preimage resistance: একটি নির্দিষ্ট
xদেওয়া থাকলে আরেকটিx' ≠ xখোঁজা যাতে hash একই — কার্যত অসম্ভব। এটাই ডাউনলোড করা ফাইল যাচাইয়ের ভিত্তি। - Collision resistance: যেকোনো দুটি আলাদা ইনপুট খোঁজা যাদের hash একই — এটাও কঠিন, তবে birthday paradox-এর কারণে মাত্র প্রায় 2n/2 কাজ লাগে।
আরেকটি প্রত্যাশিত বৈশিষ্ট্য avalanche effect: ইনপুটে একটিমাত্র bit বদলালে আউটপুটের প্রায় অর্ধেক bit উল্টে যায়, আর কোনগুলো উল্টাবে আগে থেকে বলা যায় না। ফলে “কাছাকাছি ইনপুট, কাছাকাছি hash” বলে কিছু নেই — hash দেখে ইনপুট সম্পর্কে আন্দাজ করার উপায় থাকে না।
Birthday bound — কেন n bit-এর hash-এ collision মাত্র 2n/2-এ
একটি ক্লাসে কতজন থাকলে দুজনের জন্মদিন একই হওয়ার সম্ভাবনা ৫০% ছাড়ায়? উত্তর মাত্র ২৩ — অনেকের কাছে অবাক করা। কারণ আমরা একজনের সাথে নয়, যেকোনো দুজনের মিল খুঁজছি, আর ২৩ জনে জোড়া হয় ২৩ × ২২ / ২ = ২৫৩টি।
সাধারণ হিসাব: hash-এর সম্ভাব্য মান N = 2nটি, আর আমরা k টি এলোমেলো ইনপুট hash করলাম। কোনো মিল না হওয়ার সম্ভাবনা
(এখানে ছোট x-এর জন্য 1 − x ≈ e−x আর 1 + 2 + … + (k−1) = k(k−1)/2 ব্যবহার করেছি)। এটি ½ হলে k² = 2N·ln 2, অর্থাৎ k ≈ 1.177 √N = 1.177 × 2n/2. প্রথম collision পর্যন্ত গড় চেষ্টা √(πN/2) ≈ 1.25 √N. জন্মদিনে N = 365: 1.177 × √365 ≈ ২২.৫ — সেই ২৩! ২৪-bit hash-এ √N = 212 = ৪০৯৬; SHA-256-এ 2128 — নিরাপদ। তাই hash-এর আকার নিরাপত্তার দ্বিগুণ রাখা হয়: ১২৮-bit নিরাপত্তার জন্য ২৫৬-bit hash.
নিচের কোডটি একটি ছোট, বিশুদ্ধ JavaScript-এ লেখা SHA-256 (FIPS 180-4 অনুযায়ী) — প্রথমে আনুষ্ঠানিক test vector দিয়ে নিজেকে যাচাই করে, তারপর avalanche মাপে, তারপর hash-কে ২৪ bit-এ ছেঁটে collision খোঁজে। (ব্রাউজারে আসল কাজে নিজে না লিখে crypto.subtle.digest("SHA-256", data) ব্যবহার করবেন; এখানে নিজে লেখা হয়েছে ভেতরটা দেখানোর জন্য।)
// Compact SHA-256 (FIPS 180-4) for ASCII text, then avalanche and birthday experiments.
const K = [], H0 = [], frac = (x) => ((x - Math.floor(x)) * 2 ** 32) >>> 0;
for (let n = 2, c = 0; c < 64; n++) if (![2, 3, 5, 7, 11, 13, 17, 19].some(d => d < n && n % d === 0)) {
if (c < 8) H0.push(frac(n ** 0.5)); K.push(frac(n ** (1 / 3))); c++; }
function sha256(str) {
const b = [...str].map(c => c.charCodeAt(0)), L = b.length * 8; b.push(0x80);
while (b.length % 64 !== 56) b.push(0);
for (let i = 7; i >= 0; i--) b.push(i > 3 ? 0 : (L >>> (i * 8)) & 255);
const H = H0.slice(), w = [], r = (x, n) => (x >>> n) | (x << (32 - n));
for (let o = 0; o < b.length; o += 64) {
for (let i = 0; i < 64; i++) w[i] = i < 16 ? (b[o+4*i] << 24 | b[o+4*i+1] << 16 | b[o+4*i+2] << 8 | b[o+4*i+3])
: (w[i-16] + (r(w[i-15], 7) ^ r(w[i-15], 18) ^ (w[i-15] >>> 3)) + w[i-7] + (r(w[i-2], 17) ^ r(w[i-2], 19) ^ (w[i-2] >>> 10))) | 0;
let [a, bb, c, d, e, f, g, h] = H;
for (let i = 0; i < 64; i++) {
const t1 = (h + (r(e, 6) ^ r(e, 11) ^ r(e, 25)) + ((e & f) ^ (~e & g)) + K[i] + w[i]) | 0;
const t2 = ((r(a, 2) ^ r(a, 13) ^ r(a, 22)) + ((a & bb) ^ (a & c) ^ (bb & c))) | 0;
[h, g, f, e, d, c, bb, a] = [g, f, e, (d + t1) | 0, c, bb, a, (t1 + t2) | 0];
}
[a, bb, c, d, e, f, g, h].forEach((v, i) => H[i] = (H[i] + v) | 0);
}
return H.map(x => (x >>> 0).toString(16).padStart(8, "0")).join("");
}
console.log(`sha256("abc") = ${sha256("abc")}`); // FIPS test vector ba7816bf...f20015ad
const m1 = "Pay 500 Tk to Rahim", m2 = "Pay 400 Tk to Rahim"; // '5'=0x35, '4'=0x34: ONE bit differs
const h1 = sha256(m1), h2 = sha256(m2);
const diff = [...Array(64).keys()].reduce((s, i) => s + [...(parseInt(h1[i], 16) ^ parseInt(h2[i], 16)).toString(2)].filter(x => x === "1").length, 0);
console.log(`${m1} -> ${h1.slice(0, 32)}...\n${m2} -> ${h2.slice(0, 32)}...\nbits changed: ${diff} of 256`);
// Birthday: keep only 24 bits (6 hex digits) of the hash; how many messages until two collide?
const found = [];
for (let trial = 0; trial < 10; trial++) {
const seen = new Map();
for (let i = 0; ; i++) { const t = sha256(`trial${trial}-msg${i}`).slice(0, 6);
if (seen.has(t)) { found.push(i + 1); break; } seen.set(t, i); }
}
console.log(`24-bit hash, messages until first collision: ${found.join(", ")}\navg = ${Math.round(found.reduce((s, x) => s + x) / found.length)}; 2^12 = 4096, sqrt(pi/2 * 2^24) ~ 5134`);আউটপুট:
sha256("abc") = ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
Pay 500 Tk to Rahim -> 717052a71bb45e8c557efc4a8d719ae7...
Pay 400 Tk to Rahim -> fbaf6da3cb038d26b701bf129f6b3bd8...
bits changed: 135 of 256
24-bit hash, messages until first collision: 1442, 2509, 4107, 3623, 5475, 4628, 6709, 5117, 3067, 3756
avg = 4043; 2^12 = 4096, sqrt(pi/2 * 2^24) ~ 5134
প্রথম লাইনটি NIST-এর প্রকাশিত test vector-এর সাথে হুবহু মেলে: "abc"-এর SHA-256 শুরু হয় ba7816bf দিয়ে, শেষ হয় f20015ad দিয়ে — নিজের বা AI-এর লেখা crypto কোড যাচাইয়ের এটাই প্রথম ধাপ (known-answer test). দ্বিতীয় অংশে '5' (0x35) আর '4' (0x34) — ইনপুটে মাত্র এক bit পার্থক্য — অথচ hash দুটির প্রথম ৩২ অক্ষরেও কোনো মিল চোখে পড়ে না; মোট 135 of 256 bit উল্টেছে, প্রত্যাশিত ১২৮-এর কাছাকাছি। তৃতীয় অংশে ২৪-bit-এ ছাঁটা hash-এ দশবারের পরীক্ষায় প্রথম collision এসেছে ১৪৪২ থেকে ৬৭০৯টি বার্তার মধ্যে, গড় 4043 — 224 ≈ ১ কোটি ৬৮ লাখ সম্ভাব্য মানের তুলনায় খুব কম, আর 212 = ৪০৯৬-এর ঘরেই। মাত্র ১০টি পরীক্ষার গড় তত্ত্বের ৫১৩৪ থেকে কিছুটা দূরে থাকতেই পারে; পরীক্ষা বাড়ালে কাছে আসে।
SHA-2, SHA-3 আর ভাঙা MD5, SHA-1
| Hash | আউটপুট | অবস্থা |
|---|---|---|
| MD5 (১৯৯১) | ১২৮ bit | ভাঙা: ২০০৪ সালে Wang Xiaoyun-এর দল collision দেখান; এখন সাধারণ ল্যাপটপে সেকেন্ডে collision. নিরাপত্তার কাজে নিষিদ্ধ। |
| SHA-1 (১৯৯৫) | ১৬০ bit | ভাঙা: ২০১৭ সালে Google আর CWI Amsterdam “SHAttered”-এ একই SHA-1-এর দুটি আলাদা PDF প্রকাশ করে; প্রকাশিত হিসাবে প্রায় 263 গণনা লেগেছিল — generic 280-এর চেয়ে অনেক কম। Certificate-এ বহু আগেই বাদ। |
| SHA-2 (SHA-256, SHA-384, SHA-512) | ২২৪–৫১২ bit | নিরাপদ, সর্বত্র ব্যবহৃত (TLS, Bitcoin, Git-এর নতুন ফরম্যাট, ফাইল যাচাই)। |
| SHA-3 (Keccak, FIPS 202, ২০১৫) | ২২৪–৫১২ bit | নিরাপদ; ভিন্ন নকশা (sponge), SHA-2 কোনোদিন দুর্বল হলে বিকল্প হিসেবে তৈরি। |
নিজের Linux বা macOS-এ (OpenSSL থাকলে) hash আর random বাইট দেখতে পারেন। নিচের উদাহরণটি OpenSSL 3.x চালানো একটি সাধারণ Linux যন্ত্রের — শেষ লাইনটি এলোমেলো, তাই আপনারটি আলাদা আসবে:
$ command -v openssl >/dev/null && openssl version || echo "openssl নেই"
OpenSSL 3.0.13 30 Jan 2024 (Library: OpenSSL 3.0.13 30 Jan 2024)
$ printf 'ABCL TECH' | openssl dgst -sha256
SHA2-256(stdin)= 3e8e9fd76e3152fbdc4a35b41b3b12595fe5d5e70eaa2f472bb7554f59d97a2d
$ echo 'ABCL TECH' | openssl dgst -sha256 # echo শেষে \n যোগ করে
SHA2-256(stdin)= 314378fee1bdc3d5889810f6b05135cb2e5978621ac3f87bce7eb0cc7074b3f3
$ openssl rand -hex 16 # CSPRNG থেকে ১২৮-bit চাবি
5f0c9e2a71d4b83e06a7c1f92d4e8b10খেয়াল করুন দ্বিতীয় আর তৃতীয় কমান্ড: echo লেখার শেষে একটি অদৃশ্য newline যোগ করে, আর সেই এক বাইটেই পুরো hash বদলে গেছে — avalanche-এর বাস্তব রূপ, আর “আমার hash মিলছে না কেন” প্রশ্নের সবচেয়ে সাধারণ উত্তর। পুরোনো OpenSSL (1.1.x) একই hash দেখায়, শুধু শুরুতে (stdin)= লেখে। Windows-এ PowerShell-এর Get-FileHash ফাইলের SHA-256 দেখায়।
৫ · MAC, HMAC আর password রাখার নিয়ম
Hash একা অখণ্ডতা দেয় না, যদি আক্রমণকারী বার্তা আর hash দুটোই বদলাতে পারে — CRC-র মতোই সমস্যা। দরকার এমন একটি ছাপ যা শুধু চাবিধারী বানাতে পারে: MAC (message authentication code). প্রেরক tag = MAC(K, বার্তা) পাঠান; প্রাপক একই চাবিতে আবার হিসাব করে মেলান। মিললে বোঝা যায় বার্তা অক্ষত, আর এসেছে চাবিধারী কারো কাছ থেকে। পর্ব ২৯-এর SYN cookie-তেও সার্ভার একটি গোপন চাবিসহ hash ব্যবহার করে, যাতে বাইরের কেউ বৈধ cookie বানাতে না পারে।
কেন SHA-256(key ‖ message) চলবে না
সহজ বুদ্ধি বলে চাবি আর বার্তা জুড়ে hash করলেই MAC হয়ে যায়। কিন্তু SHA-256 (আর MD5, SHA-1) Merkle–Damgård কাঠামোয় তৈরি: বার্তাকে ৬৪-বাইটের টুকরোয় ভাগ করে একটি অভ্যন্তরীণ অবস্থা ধাপে ধাপে বদলায়, আর শেষ অবস্থাটাই hash. ফলে H(key ‖ m) জানা থাকলে আক্রমণকারী সেখান থেকে hash চালিয়ে যেতে পারে — চাবি না জেনেই key ‖ m ‖ padding ‖ extra-এর বৈধ hash বানাতে পারে। একে বলে length extension attack; একসময় কিছু জনপ্রিয় ওয়েব API এমন ভুলে জাল অনুরোধ মেনে নিত বলে প্রকাশ্যে দেখানো হয়েছিল। SHA-3 আর BLAKE2-এর নকশায় এই দুর্বলতা নেই, কিন্তু প্রমিত সমাধান হলো HMAC (Bellare, Canetti, Krawczyk, ১৯৯৬; RFC 2104): চাবি দুবার, দুটি আলাদা ধ্রুবকের সাথে মিশিয়ে hash-এর ভেতরে hash.
| ইনপুট | |
| এই ধাপের ফল |
- ইনপুট। চাবি
"key"আর বার্তাThe quick brown fox…— HMAC-এর বহুল প্রচলিত উদাহরণ, যার উত্তর অনেক library-র পরীক্ষায় থাকে। চাবিটি দুই পক্ষই আগে থেকে জানেন। - চাবি block-এর মাপে। SHA-256 ৬৪ বাইটের block-এ কাজ করে। চাবি ছোট হলে শেষে শূন্য বসিয়ে ৬৪ বাইট করা হয়; ৬৪-এর বড় হলে আগে চাবিটিকেই hash করে নেওয়া হয়।
- ভেতরের চাবি। K′-এর প্রতিটি বাইটকে 0x36 দিয়ে XOR: 0x6b ⊕ 0x36 = 0x5d, 0x65 ⊕ 0x36 = 0x53, 0x79 ⊕ 0x36 = 0x4f, আর শূন্যগুলো হয়ে যায় 0x36.
- ভেতরের hash. (K′ ⊕ ipad)-এর পরে বার্তা জুড়ে SHA-256: ফল
7ad04e5a…562e3631. এটি একা প্রকাশ করলে length extension-এর ঝুঁকি থাকত — তাই আরেকটি ধাপ। - বাইরের চাবি। এবার K′-কে 0x5c দিয়ে XOR: 0x6b ⊕ 0x5c = 0x37, 0x65 ⊕ 0x5c = 0x39, 0x79 ⊕ 0x5c = 0x25. দুটি আলাদা ধ্রুবক দুটি “আলাদা” চাবির মতো কাজ করে।
- বাইরের hash = tag. (K′ ⊕ opad)-এর পরে ভেতরের ৩২-বাইটের hash জুড়ে আবার SHA-256:
f7bc83f4…2d1a3cd8. বাইরের hash-এর ইনপুটের শেষটা আক্রমণকারী নিয়ন্ত্রণ করতে পারে না, তাই length extension কাজে আসে না। - যাচাই। প্রাপক একই হিসাব করে tag মেলান। বার্তায় এক অক্ষর বদলালে (dog → cog) tag সম্পূর্ণ আলাদা। তুলনা করতে হবে constant-time ফাংশনে — সাধারণ
==প্রথম অমিল বাইটেই থেমে যায়, আর সেই সময়ের পার্থক্য মেপে বাইট-বাইট করে বৈধ tag আন্দাজ করা যায়।
Password কখনো সাধারণ hash-এ নয়
ওয়েবসাইট আপনার password নিজে রাখবে না, রাখবে তার একটি ছাপ; লগইনের সময় নতুন করে হিসাব করে মেলাবে। কিন্তু SHA-256(password) রাখা বিপজ্জনক, দুই কারণে:
- খুব দ্রুত: SHA-256 দ্রুত হওয়ার জন্যই বানানো। একটি আধুনিক GPU সেকেন্ডে শত শত কোটি SHA-256 হিসাব করতে পারে। ৮ অক্ষরের ছোট হাতের ইংরেজি password-এর সম্ভাব্য সংখ্যা 268 ≈ ২০,৮৮৩ কোটি; সেকেন্ডে ১,০০০ কোটি চেষ্টায় সব শেষ প্রায় ২১ সেকেন্ডে।
- একই password, একই hash: হাজার জনের password “123456” হলে সবার hash এক — আগে থেকে বানানো তালিকা (rainbow table) দিয়ে একবারে সবাই ধরা পড়েন।
সমাধান দুটি হাতিয়ারের জোড়া। প্রতিটি ব্যবহারকারীর জন্য আলাদা এলোমেলো salt (যেমন ১৬ বাইট), যা hash-এর পাশে খোলাই রাখা হয় — এতে একই password-এর hash-ও আলাদা হয় আর আগে বানানো তালিকা অকেজো হয়। আর ইচ্ছা করে ধীর, মেমরি-খেকো একটি password hashing ফাংশন: Argon2id (২০১৫ সালের Password Hashing Competition-জয়ী, RFC 9106), scrypt (২০০৯), bcrypt (১৯৯৯), বা মান্য নির্দেশিকা মেনে বড় iteration-এর PBKDF2. এগুলোকে key derivation function (KDF)-ও বলে। লগইনে ১০০ মিলিসেকেন্ড লাগলে ব্যবহারকারী টেরও পান না, কিন্তু আক্রমণকারীর প্রতিটি আন্দাজ লাখো গুণ দামি হয়ে যায়; আর Argon2 বা scrypt প্রতিটি চেষ্টায় অনেক মেমরি চায় বলে GPU-র হাজার core একসাথে কাজে লাগানো কঠিন। কখনো password এনক্রিপ্ট করে রাখবেন না (চাবি চুরি গেলে সব খোলা), আর কখনো plain SHA-256 বা MD5 নয়।
৬ · Public key আর Diffie–Hellman — খোলা রাস্তায় গোপন চাবি
Symmetric cipher-এর একটি বড় প্রশ্ন বাকি: চাবিটি দুই পক্ষের কাছে পৌঁছাবে কীভাবে? চট্টগ্রামের একজন গ্রাহক যখন প্রথমবার একটি ঢাকার ই-কমার্স সাইটে ঢোকেন, আগে থেকে কোনো গোপন চাবি ভাগ করা নেই। প্রতিটি সাইটের জন্য কুরিয়ারে চাবি পাঠানো অসম্ভব; n জন মানুষের প্রত্যেক জোড়ার জন্য আলাদা চাবি লাগলে মোট n(n−1)/2টি চাবি — ১০০ কোটি ব্যবহারকারীর জন্য প্রায় ৫ × ১০১৭টি। এটাই key distribution-এর সমস্যা।
১৯৭৬ সালে Whitfield Diffie আর Martin Hellman তাঁদের “New Directions in Cryptography” প্রবন্ধে দেখান, দুজন মানুষ সবার সামনে কথা বলেও একটি গোপন সংখ্যায় একমত হতে পারেন। ভিত্তি একটি এক-মুখী গণিত: modular exponentiation ga mod p হিসাব করা সহজ (square-and-multiply-এ প্রায় log₂a ধাপ), কিন্তু ফল দেখে a বের করা — discrete logarithm — বড় p-এর জন্য কার্যত অসম্ভব। (Modular arithmetic আর দ্রুত ঘাতের গণিত DSA কোর্সের Number theory — GCD, sieve আর modular arithmetic পর্বে বিস্তারিত আছে।)
রঙের উপমাটি জনপ্রিয়: দুজনে প্রকাশ্যে একটি সাধারণ রং (হলুদ) বাছলেন। প্রত্যেকে নিজের গোপন রং মিশিয়ে মিশ্রণটি খোলাখুলি বিনিময় করলেন। তারপর অন্যের মিশ্রণে নিজের গোপন রং আবার মেশালেন — দুজনের কাছেই একই চূড়ান্ত রং: হলুদ + দুই গোপন রং। মাঝের লোক দুটি মিশ্রণ দেখেছে, কিন্তু মিশ্রণ থেকে রং আলাদা করা প্রায় অসম্ভব। গণিতে “মেশানো” মানে ঘাত নেওয়া।
| সবাই দেখে (খোলা) | |
| Alice-এর কাছে | |
| Bob-এর কাছে | |
| Eve যা জানে |
- প্রকাশ্য মান। একটি মৌলিক সংখ্যা p = 23 আর একটি “generator” g = 5 সবাই জানে — এগুলো গোপন নয়, মানদণ্ডে লেখা থাকে। বাস্তবে p ২০৪৮ bit বা তার বড়, অথবা elliptic curve.
- Alice-এর গোপন সংখ্যা। Alice এলোমেলোভাবে a = 6 বাছলেন আর হিসাব করলেন A = 5⁶ mod 23. ধাপে: 5² = 25 ≡ 2, 5⁴ ≡ 2² = 4, 5⁶ = 5⁴ · 5² ≡ 4 · 2 = 8. সুতরাং A = 8.
- Bob-এর গোপন সংখ্যা। Bob বাছলেন b = 15: 5⁸ ≡ 16, তাই 5¹⁵ = 5⁸ · 5⁴ · 5² · 5 ≡ 16 · 4 · 2 · 5 = 640 ≡ 19 (কারণ 23 × 27 = 621, আর 640 − 621 = 19). B = 19.
- খোলা বিনিময়। A = 8 আর B = 19 খোলা চ্যানেলে পাঠানো হলো। Eve দুটোই দেখল। a আর b কখনো তারে যায়নি।
- Alice-এর হিসাব। s = Ba mod p = 19⁶ mod 23. 19² = 361 ≡ 16, 19⁴ ≡ 16² = 256 ≡ 3, তাই 19⁶ ≡ 3 · 16 = 48 ≡ 2.
- Bob-এর হিসাব। s = Ab mod p = 8¹⁵ mod 23 — তিনিও পেলেন 2. কারণ দুজনেই আসলে gab = 5⁹⁰ mod 23 হিসাব করেছেন, শুধু ক্রম আলাদা: (gb)a = (ga)b.
- Eve-এর সমস্যা। Eve-কে 5ˣ ≡ 8 (mod 23) থেকে x বের করতে হবে — discrete logarithm. p = 23-এ ২২টি সম্ভাবনা হাতেই চেষ্টা করা যায়; কিন্তু ২০৪৮-bit p-এর জন্য জানা সবচেয়ে ভালো algorithm-ও অসাধ্য সময় নেয়। এই চাবি (2) থেকে এবার AES-এর চাবি বানানো হয়।
MITM — কেন শুধু DH যথেষ্ট নয়
Eve শুধু শুনলে DH নিরাপদ। কিন্তু সক্রিয় আক্রমণকারী Mallory যদি মাঝখানে বসে Alice-এর A আটকে Bob-কে নিজের M পাঠান, আর Bob-এর B আটকে Alice-কে M পাঠান? তখন Alice-এর চাবি হয় Mallory-র সাথে, Bob-এর চাবিও Mallory-র সাথে — দুজনেই ভাবেন একে অপরের সাথে কথা বলছেন। এটাই man-in-the-middle. DH বলে “আমরা দুজন একই গোপন চাবি পেলাম”, কিন্তু বলে না “আমি কার সাথে চাবি পেলাম”। নিচের simulator-এ দুটোই দেখুন:
// Toy Diffie–Hellman (p = 23) — শেখার জন্য, বাস্তবে ব্যবহার নিষেধ (real p: 2048+ bits or X25519).
const modPow = (b, e, m) => { let r = 1; b %= m;
for (; e > 0; e >>= 1, b = b * b % m) if (e & 1) r = r * b % m; return r; };
const p = 23, g = 5;
const a = 6, b = 15; // secrets: never sent
const A = modPow(g, a, p), B = modPow(g, b, p); // public values: sent in the open
console.log(`public: p=${p}, g=${g}; Alice sends A=${A}, Bob sends B=${B}`);
console.log(`Alice: B^a mod p = ${modPow(B, a, p)} | Bob: A^b mod p = ${modPow(A, b, p)}`);
// Passive Eve sees p, g, A, B. With p=23 she can simply try every exponent:
const tries = [...Array(p - 1).keys()].filter(x => modPow(g, x, p) === A);
console.log(`Eve brute-forces g^x = A: x in [${tries}] -> key ${modPow(B, tries[0], p)} (why p must be huge)`);
// Active Mallory sits in the middle and swaps A and B with her own value M.
const m = 13, M = modPow(g, m, p);
const kAlice = modPow(M, a, p), kBob = modPow(M, b, p);
console.log(`\nMITM: Mallory sends M=${M} to both sides`);
console.log(`Alice thinks key with Bob = ${kAlice}; Mallory's copy = ${modPow(A, m, p)}`);
console.log(`Bob thinks key with Alice = ${kBob}; Mallory's copy = ${modPow(B, m, p)}`);
console.log(`Alice and Bob keys equal? ${kAlice === kBob} -> Mallory decrypts, reads, re-encrypts`);
// Defence = authentication: compare a fingerprint of the key over another channel
// (like a safety number), or have the server SIGN its value (TLS certificates, lesson 48).
console.log(`fingerprint check by phone: Alice ${kAlice} vs Bob ${kBob} -> ${kAlice === kBob ? "same" : "MISMATCH, abort"}`);আউটপুট:
public: p=23, g=5; Alice sends A=8, Bob sends B=19
Alice: B^a mod p = 2 | Bob: A^b mod p = 2
Eve brute-forces g^x = A: x in [6] -> key 2 (why p must be huge)
MITM: Mallory sends M=21 to both sides
Alice thinks key with Bob = 18; Mallory's copy = 18
Bob thinks key with Alice = 7; Mallory's copy = 7
Alice and Bob keys equal? false -> Mallory decrypts, reads, re-encrypts
fingerprint check by phone: Alice 18 vs Bob 7 -> MISMATCH, abort
প্রথম দুই লাইন stepper-এর সাথে মেলে: A = 8, B = 19, আর দুই পক্ষেই চাবি 2. তৃতীয় লাইন দেখায় কেন খেলনা p বিপজ্জনক — Eve মাত্র ২২টি ঘাত চেষ্টা করে x in [6] পেয়ে চাবি 2 বের করে ফেলল। MITM অংশে Mallory নিজের গোপন সংখ্যা 13 থেকে M = 5¹³ mod 23 = 21 দুই দিকে পাঠালেন। Alice-এর চাবি হলো 18, যার কপি Mallory-র কাছেও আছে; Bob-এর চাবি 7, তারও কপি Mallory-র কাছে। keys equal? false — কিন্তু Alice আর Bob তা জানেন না, যতক্ষণ না অন্য কোনো বিশ্বস্ত পথে (ফোনে, মুখোমুখি) চাবির একটি ছাপ মিলিয়ে দেখেন: 18 বনাম 7 → অমিল, সংযোগ বাতিল। Signal-এর “safety number” এই ধারণা; ওয়েবে এ কাজ করে সার্ভারের সই করা DH মান আর certificate — পর্ব ৪৮-এর (TLS আর HTTPS) বিষয়।
প্রতিটি সংযোগে নতুন, ক্ষণস্থায়ী (ephemeral) DH সংখ্যা বানিয়ে কাজ শেষে মুছে ফেললে, পরে সার্ভারের দীর্ঘমেয়াদি চাবি চুরি গেলেও আগের রেকর্ড করা আলাপ খোলা যায় না — একে বলে forward secrecy. দীর্ঘমেয়াদি চাবি শুধু সই করে (“এই DH মান আমার”), এনক্রিপ্ট করে না। পর্ব ১৪-এ (Wi-Fi) দেখেছেন WPA3-এর SAE-ও এই গুণ দেয়, আর TLS 1.3 certificate-ভিত্তিক পূর্ণ handshake-এ শুধু এমন ephemeral key exchange রেখেছে — পুরোনো static RSA key exchange বাদ।
৭ · RSA, elliptic curve আর digital signature
DH চাবিতে একমত করায়; কিন্তু “যে কেউ আমার জন্য তালা দিতে পারবে, খুলতে পারব শুধু আমি” — এমন তালা কি সম্ভব? ১৯৭৭ সালে MIT-র Ron Rivest, Adi Shamir আর Leonard Adleman দেখান সম্ভব: RSA. এটাই public key cryptography-র সবচেয়ে পরিচিত রূপ — প্রত্যেকের একজোড়া চাবি: সবার জন্য খোলা public key আর শুধু নিজের কাছে রাখা private key. ডাকঘরের চিঠির বাক্সের মতো — ফোকর দিয়ে যে কেউ চিঠি ফেলতে পারে, কিন্তু বাক্স খোলার চাবি শুধু পোস্টমাস্টারের কাছে।
RSA হাতে-কলমে (p = 61, q = 53)
- দুটি গোপন মৌলিক সংখ্যা: p = 61, q = 53. n = p·q = 3233 — এটি public.
- φ(n) = (p−1)(q−1) = 60 × 52 = 3120 — গোপন; p, q না জানলে বের করা কঠিন।
- e = 17 বাছাই, যাতে gcd(e, φ) = 1. (বাস্তবে প্রায় সবসময় e = 65537.)
- d = e−1 mod φ, extended Euclid দিয়ে: 3120 = 17·183 + 9; 17 = 9·1 + 8; 9 = 8·1 + 1. উল্টো দিকে: 1 = 9 − 8 = 9 − (17 − 9) = 2·9 − 17 = 2·(3120 − 183·17) − 17 = 2·3120 − 367·17. তাই d ≡ −367 ≡ 3120 − 367 = 2753. যাচাই: 17 × 2753 = 46801 = 15 × 3120 + 1 ✓.
- Public key = (n, e) = (3233, 17); private key = d = 2753. Encrypt: c = me mod n; decrypt: m = cd mod n. m = 65 হলে c = 6517 mod 3233 = 2790, আর 27902753 mod 3233 = 65 ফেরত আসে।
কেন কাজ করে? e·d = 1 + kφ(n). Euler-এর উপপাদ্য বলে gcd(m, n) = 1 হলে mφ(n) ≡ 1 (mod n). তাই cd = med = m · (mφ(n))k ≡ m · 1k = m (mod n). (gcd ≠ 1 হলেও Chinese remainder theorem দিয়ে ফলটি সত্য প্রমাণ করা যায়।) নিরাপত্তা দাঁড়িয়ে আছে factoring-এর কাঠিন্যে: n থেকে p আর q বের করতে পারলেই φ, তারপর d. 3233 হাতে ভাঙা যায়; ২০৪৮-bit (প্রায় ৬১৭ অঙ্কের) n ভাঙার কোনো জানা ব্যবহারিক উপায় নেই।
Digital signature — উল্টো দিকে চাবি
RSA-তে চাবি দুটির ভূমিকা উল্টে দিলে সই হয়: private key দিয়ে “এনক্রিপ্ট” করলে যে কেউ public key দিয়ে মিলিয়ে দেখতে পারেন, কিন্তু বানাতে পারেন শুধু private key-র মালিক। বাস্তবে পুরো বার্তা নয়, তার hash সই করা হয় (hash-then-sign) — বার্তা যত বড়ই হোক, সই ছোট থাকে। নিচের stepper-এ আরও ছোট সংখ্যায় পুরোটা হাতে মেলানো যায়:
| Key | |
| হিসাব | |
| ফল |
- দুটি মৌলিক। Rahim গোপনে p = 5, q = 11 বাছলেন; n = 55. (খেলনা — বাস্তবে প্রতিটি মৌলিক ১০২৪ bit বা তার বড়।)
- φ(n). φ = (5−1)(11−1) = 40 — ১ থেকে ৫৫-র মধ্যে ৫৫-র সাথে সহমৌলিক সংখ্যার সংখ্যা। p, q জানা থাকায় এটি সহজ; শুধু n জানলে নয়।
- e বাছাই। e = 3, কারণ gcd(3, 40) = 1 — নইলে উল্টো (d) থাকত না।
- d হিসাব। 3·d ≡ 1 (mod 40) → d = 27, কারণ 81 = 2 × 40 + 1. Public key (55, 3) সবাইকে দেওয়া হলো; d = 27 রইল শুধু Rahim-এর কাছে।
- সই। বার্তার (খেলনা) hash h = 9. সই s = hd mod n = 9²⁷ mod 55. Square-and-multiply: 9² = 81 ≡ 26, 26² = 676 ≡ 16, 16² = 256 ≡ 36, 36² = 1296 ≡ 31. 27 = 16 + 8 + 2 + 1, তাই 31 · 36 · 26 · 9: 31·36 = 1116 ≡ 16; 16·26 = 416 ≡ 31; 31·9 = 279 ≡ 4. সই s = 4.
- যাচাই। ব্যাংক public key দিয়ে se mod n = 4³ = 64 ≡ 9 হিসাব করল, আর নিজে বার্তার hash হিসাব করে পেল 9 — মিলেছে, সই বৈধ। ব্যাংকের d জানার দরকার পড়েনি।
- বদলানো বার্তা। পথে কেউ বার্তা বদলালে hash হলো 13. সই 4 থেকে আসে 9 — মেলে না, বাতিল। আক্রমণকারী 13-এর জন্য বৈধ সই বানাতে পারবে না, কারণ তার জন্য d লাগবে। Rahim পরে “আমি সই করিনি” বললেও টিকবে না — শুধু তাঁর কাছেই d ছিল (non-repudiation).
এবার BigInt দিয়ে পুরো RSA চালিয়ে দেখুন — key তৈরি (extended Euclid সহ), encrypt/decrypt আর sign/verify, যেখানে বদলানো বার্তা ধরা পড়ে:
// Toy RSA with BigInt — শেখার জন্য, বাস্তবে ব্যবহার নিষেধ (tiny primes, no padding).
const modPow = (b, e, m) => { let r = 1n; b %= m;
for (; e > 0n; e >>= 1n, b = b * b % m) if (e & 1n) r = r * b % m; return r; };
function egcd(a, b) { // returns [g, x, y] with a*x + b*y = g
if (b === 0n) return [a, 1n, 0n];
const [g, x, y] = egcd(b, a % b); return [g, y, x - (a / b) * y];
}
const p = 61n, q = 53n, n = p * q, phi = (p - 1n) * (q - 1n), e = 17n;
const [g, x] = egcd(e, phi), d = ((x % phi) + phi) % phi;
console.log(`n = ${n}, phi = ${phi}, e = ${e}, gcd(e,phi) = ${g}, d = ${d}`);
console.log(`check: e*d mod phi = ${e * d % phi}`);
const m = 65n, c = modPow(m, e, n); // encrypt with PUBLIC (e, n)
console.log(`encrypt m=${m}: c = ${m}^${e} mod ${n} = ${c}`);
console.log(`decrypt: c^d mod n = ${modPow(c, d, n)}`); // decrypt with PRIVATE d
// toy "hash" of a message into 0..n-1 (NOT a real hash; real RSA signs SHA-256 + PSS)
const h = (s) => [...s].reduce((a, ch) => (a * 31n + BigInt(ch.charCodeAt(0))) % n, 7n);
const msg = "Pay 500 Tk to Rahim", hm = h(msg);
const sig = modPow(hm, d, n); // sign with PRIVATE d
console.log(`\nmsg = "${msg}", h = ${hm}, signature s = h^d mod n = ${sig}`);
for (const recv of [msg, "Pay 900 Tk to Rahim"]) {
const back = modPow(sig, e, n), want = h(recv); // verify with PUBLIC e
console.log(`verify "${recv}": s^e mod n = ${back}, h(recv) = ${want} -> ${back === want ? "VALID" : "INVALID (tampered)"}`);
}আউটপুট:
n = 3233, phi = 3120, e = 17, gcd(e,phi) = 1, d = 2753
check: e*d mod phi = 1
encrypt m=65: c = 65^17 mod 3233 = 2790
decrypt: c^d mod n = 65
msg = "Pay 500 Tk to Rahim", h = 186, signature s = h^d mod n = 2711
verify "Pay 500 Tk to Rahim": s^e mod n = 186, h(recv) = 186 -> VALID
verify "Pay 900 Tk to Rahim": s^e mod n = 186, h(recv) = 37 -> INVALID (tampered)
উপরের হাতের হিসাবই মিলেছে: d = 2753, আর e*d mod phi = 1 যাচাই। 65 এনক্রিপ্ট হয়ে 2790, আর private key দিয়ে আবার 65. সই অংশে বার্তা Pay 500 Tk to Rahim-এর খেলনা hash 186, সই 2711. প্রাপক public key দিয়ে 271117 mod 3233 = 186 পেলেন; আসল বার্তায় মিলল (VALID), কিন্তু “500” বদলে “900” করা বার্তার hash 37 — মেলেনি (INVALID (tampered)). এখানে hash হিসেবে একটি খেলনা ফাংশন ব্যবহার করা হয়েছে, যার মান মাত্র ০–৩২৩২; বাস্তবে SHA-256 আর RSA-PSS.
“Textbook RSA” বাস্তবে ভাঙা। উপরের সরল রূপ deterministic (একই m সবসময় একই c — ছোট সম্ভাব্য বার্তা আন্দাজ করে মেলানো যায়), আর গুণফলের গঠন রক্ষা করে: দুটি সইয়ের গুণফল আরেকটি বার্তার বৈধ সই। তাই বাস্তবে এলোমেলো padding বাধ্যতামূলক: এনক্রিপশনে OAEP, সইয়ে PSS (PKCS #1 v2, RFC 8017). পুরোনো PKCS #1 v1.5 এনক্রিপশন-padding-এ ১৯৯৮ সালে Daniel Bleichenbacher ত্রুটি-বার্তা থেকে plaintext বের করার আক্রমণ দেখান, যার নানা রূপ পরের বহু বছর ধরে ফিরে এসেছে। চাবি অন্তত ২০৪৮ bit; দীর্ঘমেয়াদে ৩০৭২ bit.
Elliptic curve — ছোট চাবি, একই নিরাপত্তা
Elliptic curve cryptography (ECC)-তে সংখ্যার ঘাতের বদলে একটি বক্ররেখার বিন্দু বারবার “যোগ” করা হয়; বিন্দু P আর ফল kP দেখে k বের করার সমস্যাটি সাধারণ discrete log-এর চেয়েও কঠিন বলে জানা যায়। ফলে অনেক ছোট চাবিতে একই নিরাপত্তা। NIST-এর প্রচলিত তুলনায় (SP 800-57) মোটামুটি: ২৫৬-bit ECC ≈ ৩০৭২-bit RSA ≈ ১২৮-bit symmetric; ২২৪-bit ECC ≈ ২০৪৮-bit RSA ≈ ১১২-bit. এসব সমতা আনুমানিক, কারণ আক্রমণের সেরা algorithm-এর হিসাবের ওপর নির্ভর করে। আজকের জনপ্রিয় রূপ: X25519 (ECDH key exchange, RFC 7748 — আজ বহু TLS 1.3 সংযোগের প্রথম পছন্দ), Ed25519 (সই, RFC 8032 — SSH key-তে খুব প্রচলিত), আর ECDSA P-256 (certificate-এ বহুল ব্যবহৃত, কিন্তু প্রতিটি সইয়ে নতুন গোপন সংখ্যা লাগে — PS3-র ঘটনা মনে করুন)। X25519-এর public key মাত্র ৩২ বাইট, যেখানে ৩০৭২-bit RSA-র modulus ৩৮৪ বাইট — ফোনে আর handshake-এ এই পার্থক্য বড়।
| MAC (HMAC, GCM tag) | Digital signature (RSA-PSS, Ed25519) | |
|---|---|---|
| চাবি | একই গোপন চাবি দুই পক্ষের | সই private key-তে, যাচাই public key-তে |
| কে যাচাই করতে পারে | শুধু চাবিধারীরা | যে কেউ |
| Non-repudiation | না — প্রাপকও একই tag বানাতে পারেন | হ্যাঁ — শুধু private key-র মালিক বানাতে পারেন |
| গতি আর আকার | খুব দ্রুত, ১৬–৩২ বাইট | অনেক ধীর; Ed25519 সই ৬৪ বাইট, RSA-2048 সই ২৫৬ বাইট |
| নেটওয়ার্কে কোথায় | প্রতিটি TLS record, QUIC packet, IPsec packet | Certificate, TLS handshake, পর্ব ৩৯-এর DKIM, সফটওয়্যার আপডেট, DNSSEC |
পর্ব ৩৯-এ (ইমেইল) DKIM দেখেছেন: পাঠানো সার্ভার header আর body-র hash-এ সই করে, প্রাপক DNS থেকে public key এনে যাচাই করে — ঠিক এই hash-then-sign. আবার একটি সই শুধু বলে “এই private key-র মালিক সই করেছেন” — ওই public key সত্যিই bank.example-এর কি না, তা বলে না। সেই সংযোগ বানায় certificate আর বিশ্বাসের শিকল (PKI), যা পর্ব ৪৮-এর পুরো বিষয়।
৮ · সব জোড়া লাগানো — hybrid encryption, randomness, post-quantum আর সোনালি নিয়ম
Hybrid encryption — দুই জগতের সেরাটা
Public key ধীর (RSA বা ECDH-এর একটি কাজে symmetric-এর চেয়ে হাজার গুণ বা তার বেশি সময়), কিন্তু চাবি বিতরণের সমস্যা মেটায়; symmetric দ্রুত, কিন্তু আগে থেকে চাবি চায়। সমাধান — দুটো একসাথে, আর ঠিক এভাবেই HTTPS চলে:
একটি নিরাপদ সংযোগের ভেতরের কাঠামো
Public key for agreement and identity, symmetric AEAD for bulk data
- Ephemeral DH
X25519খোলা চ্যানেলে গোপন চাবি - সই যাচাই
Ed25519 / RSA-PSSসার্ভার সত্যিই সে-ই? - KDF
HKDF-SHA256ভাগ করা গোপন থেকে চাবি - AEAD
AES-GCMসব ডেটা দ্রুত
Randomness — সব চাবির উৎস
প্রতিটি চাবি, nonce, salt আর DH-এর গোপন সংখ্যা আসে random number থেকে। সাধারণ Math.random() বা C-র rand() খেলা আর simulation-এর জন্য — কয়েকটি আউটপুট দেখে পরেরগুলো আন্দাজ করা যায়। চাবির জন্য দরকার CSPRNG (cryptographically secure pseudo-random number generator), যা OS হার্ডওয়্যারের অনিশ্চয়তা (entropy) — interrupt-এর সময়, CPU-র হার্ডওয়্যার RNG — জড়ো করে বানায়। Linux-এ getrandom() system call (kernel 3.17 থেকে) বা /dev/urandom; Windows-এ BCryptGenRandom; ব্রাউজারে crypto.getRandomValues(); Python-এ secrets module.
এখানে ভুলের দাম ভয়াবহ। ২০০৮ সালের মে মাসে জানা যায় (CVE-2008-0166), Debian-এর OpenSSL প্যাকেজে ২০০৬ সালে একটি “পরিষ্কারের” পরিবর্তনে entropy জোগানোর লাইন বাদ পড়েছিল; ফলে random অবস্থা প্রায় শুধু process ID-র ওপর নির্ভর করত — প্রতিটি ধরন আর আকারের জন্য মাত্র কয়েক হাজার (৩২,৭৬৮-র মতো) সম্ভাব্য চাবি। প্রায় দুই বছর ধরে Debian আর Ubuntu-তে বানানো SSH ও TLS চাবি তালিকা ধরে ভাঙা যেত, আর সেগুলো খুঁজে বাতিল করতে হয়েছিল।
Post-quantum cryptography
১৯৯৪ সালে Peter Shor দেখান, যথেষ্ট বড় ও ত্রুটি-সংশোধিত quantum computer factoring আর discrete log দুটোই দ্রুত (polynomial সময়ে) করতে পারবে — অর্থাৎ RSA, DH, ECDH, ECDSA সবই ভাঙবে (Shor-এর algorithm). Symmetric cipher আর hash-এর ক্ষতি তুলনায় কম: Grover-এর algorithm (১৯৯৬) তাত্ত্বিকভাবে brute force-কে বর্গমূলে নামায়, তাই দীর্ঘমেয়াদে AES-256 পছন্দ করা হয়। এমন যন্ত্র কবে আসবে কেউ নিশ্চিত জানে না; কিন্তু “আজ রেকর্ড, পরে ডিক্রিপ্ট” (harvest now, decrypt later) ঝুঁকির কারণে দীর্ঘদিন গোপন রাখার তথ্যের জন্য এখনই প্রস্তুতি চলছে। ২০২৪ সালের আগস্টে NIST প্রথম post-quantum মানদণ্ড প্রকাশ করে: FIPS 203 — ML-KEM (Kyber থেকে, key exchange), FIPS 204 — ML-DSA (Dilithium থেকে, সই), আর FIPS 205 — SLH-DSA (hash-ভিত্তিক সই)। প্রধান ব্রাউজার আর বড় CDN-গুলো ২০২৪ সাল থেকে TLS-এ hybrid key exchange (X25519 আর ML-KEM-768 একসাথে, যাতে যেকোনো একটি টিকলেই নিরাপদ) চালু করতে শুরু করেছে বলে তাদের প্রকাশিত ঘোষণায় জানা যায় — কোন সংস্করণে কোনটি ডিফল্ট, তা দ্রুত বদলাচ্ছে। দাম আছে: ML-KEM-768-এর public key ১১৮৪ বাইট, ciphertext ১০৮৮ বাইট — X25519-এর ৩২ বাইটের তুলনায় অনেক বড়, তাই handshake-এর packet বড় হয়।
সোনালি নিয়ম
আরও গভীরে: টেবিল-ভিত্তিক সফটওয়্যার AES-এ মেমরি-cache-এর সময়ের পার্থক্য মেপে চাবি বের করার আক্রমণ ২০০৫ সালে Daniel J. Bernstein-সহ কয়েকজন গবেষক দেখান; তাই আধুনিক library হয় AES-NI-র মতো হার্ডওয়্যার নির্দেশ, নয়তো constant-time bitsliced কোড ব্যবহার করে, আর ChaCha20 নকশাতেই শুধু যোগ, rotate আর XOR দিয়ে তৈরি যাতে টেবিল না লাগে। TLS 1.3 DH-এর ফল থেকে সব চাবি বানায় HKDF (RFC 5869) দিয়ে — extract আর expand নামের দুই ধাপের একটি HMAC-ভিত্তিক KDF. Linux kernel-এর নিজস্ব crypto API আছে, যা IPsec, WireGuard, ডিস্ক এনক্রিপশন (dm-crypt) ব্যবহার করে, আর random-এর জন্য kernel ২০২২ সালের দিকে ভেতরের মিশ্রণে SHA-1-এর বদলে BLAKE2s-এ সরে গেছে।
পরীক্ষা ও ইন্টারভিউতে এই বিষয়ে প্রায়ই যা জিজ্ঞেস করা হয়:
- Symmetric আর asymmetric-এর পার্থক্য? — Symmetric-এ একই চাবি, দ্রুত (AES); asymmetric-এ public/private জোড়া, ধীর, চাবি বিতরণ আর সইয়ে (RSA, ECC); বাস্তবে দুটো মিলিয়ে hybrid.
- Hash, MAC আর digital signature-এর পার্থক্য? — Hash-এ চাবি নেই; MAC-এ ভাগ করা চাবি, তাই non-repudiation নেই; সই private key-তে, যে কেউ যাচাই করতে পারেন।
- RSA-তে p = 3, q = 11, e = 7 হলে d কত? — φ = 20, 7d ≡ 1 (mod 20) → d = 3.
- n-bit hash-এ collision খুঁজতে কত কাজ? — প্রায় 2n/2 (birthday bound); preimage-এ প্রায় 2n.
- Password কীভাবে রাখবেন? — প্রতি ব্যবহারকারী আলাদা salt আর Argon2id, bcrypt বা scrypt-এর মতো ধীর KDF; কখনো plain SHA-256, MD5 বা এনক্রিপশন নয়।
৯ · AI-এর যুগে cryptography — দেখতে ঠিক, আসলে ভাঙা
Crypto কোড বিপজ্জনকভাবে “চলে”: ভুল mode, স্থির IV বা দুর্বল random-এও ফাইল এনক্রিপ্ট হয়, ডিক্রিপ্টও হয়, test pass করে — শুধু নিরাপত্তা থাকে না। AI প্রায়ই পুরোনো টিউটোরিয়াল থেকে শেখা এমন কোড আত্মবিশ্বাসের সাথে দেয়। আর নেটওয়ার্কিংয়ের অন্য কাজের মতো এখানেও AI পুরোনো কমান্ড, এক vendor-এর নিয়মকে সার্বজনীন বলা, আর বানানো RFC নম্বর দেয়। চেনা ভুলগুলো:
| AI-এর ভুল | আসল কথা | কীভাবে যাচাই করবেন |
|---|---|---|
AES/ECB বা Java-র ডিফল্ট "AES" (যা অনেক provider-এ ECB), কোডে লেখা স্থির IV বা nonce | AEAD (GCM), প্রতিবার CSPRNG থেকে নতুন nonce | একই plaintext দুবার এনক্রিপ্ট করুন — ciphertext এক হলে ভুল |
| Password-এ MD5, SHA-1 বা salt ছাড়া SHA-256 | Argon2id, scrypt বা bcrypt, প্রতিজনে আলাদা salt | OWASP-এর password storage নির্দেশিকা মিলিয়ে দেখুন |
Token বা OTP-তে Math.random() বা rand() | crypto.getRandomValues, secrets, getrandom() | কোডে random-এর উৎস খুঁজুন |
| “Base64 করে এনক্রিপ্ট করলাম” | Base64 encoding, কোনো চাবি নেই — যে কেউ উল্টাতে পারে | অনলাইনে নয়, নিজের terminal-এ base64 -d দিয়ে দেখুন |
openssl enc -aes-256-cbc শুধু password দিয়ে | পুরোনো ডিফল্টে দুর্বল KDF আর কোনো integrity নেই; অন্তত -pbkdf2, ভালো হয় age বা libsodium-ভিত্তিক টুল | man openssl-enc আর OpenSSL-এর সতর্কবার্তা পড়ুন |
| RSA-1024, PKCS #1 v1.5 এনক্রিপশন, নিজে লেখা “textbook RSA” | ≥২০৪৮-bit, OAEP/PSS, বা X25519/Ed25519 | NIST SP 800-57, library-র ডকুমেন্টেশন |
MAC বা signature == দিয়ে তুলনা | Constant-time তুলনা | Library-র নিজস্ব verify ফাংশন ব্যবহার হচ্ছে কি না দেখুন |
| বানানো ফাংশনের নাম, parameter বা RFC নম্বর | যেমন HMAC = RFC 2104, ChaCha20-Poly1305 = RFC 8439, TLS 1.3 = RFC 8446 | rfc-editor.org আর library-র আসল API ডকুমেন্টেশন |
AI-কে crypto-র কাজে ডাকলে নিজের প্রেক্ষাপট দিন, আর তাকে library ব্যবহারে বাধ্য করুন:
AI-এর crypto কোড চালুর আগে — চেকলিস্ট
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন।
প্র ০১One-time pad গাণিতিকভাবে নিখুঁত — তবু ইতিহাসে এটি ভেঙেছে কীভাবে, আর আধুনিক cipher কেন “অনিখুঁত” পথ বেছে নিল?
Shannon-এর প্রমাণে শর্ত তিনটি: চাবি সত্যিকারের এলোমেলো, বার্তার সমান লম্বা, আর একবারই ব্যবহৃত। ইতিহাসের ভাঙনগুলো সবই এই শর্ত ভাঙার গল্প, গণিত ভাঙার নয়।
সবচেয়ে বিখ্যাত উদাহরণ যুক্তরাষ্ট্রের Venona প্রকল্প। দ্বিতীয় বিশ্বযুদ্ধের সময় সোভিয়েত ইউনিয়নের কূটনৈতিক ও গোয়েন্দা বার্তা one-time pad-এ এনক্রিপ্ট হতো। কিন্তু যুদ্ধকালীন চাপে pad ছাপানোর সময় কিছু পাতা একাধিক কপিতে তৈরি হয় বলে পরে জানা যায়। ফলে একই চাবির অংশ দুটি আলাদা বার্তায় ব্যবহৃত হয় — আর এই পর্বে দেখা C1 ⊕ C2 = P1 ⊕ P2 সূত্রটিই কাজে লাগে। মার্কিন বিশ্লেষকেরা বহু বছরের পরিশ্রমে হাজারো বার্তার অংশবিশেষ পড়তে পারেন, যা পারমাণবিক গুপ্তচরবৃত্তির মতো ঘটনা উন্মোচনে ভূমিকা রেখেছিল বলে প্রকাশিত নথিতে উল্লেখ আছে।
দ্বিতীয় সমস্যা বিতরণ। ঠান্ডা যুদ্ধের সময় মস্কো–ওয়াশিংটন “হটলাইন”-এ one-time pad ব্যবহারের কথা বলা হয় — কিন্তু সেখানে চাবি কূটনৈতিক ব্যাগে হাতে হাতে পৌঁছানো যেত, কারণ মাত্র দুটি পক্ষ। ইন্টারনেটে কোটি কোটি অচেনা পক্ষ, প্রতিটি সংযোগের জন্য আগে থেকে গিগাবাইট চাবি পৌঁছানো অসম্ভব।
তৃতীয়ত, OTP integrity দেয় না। একজন জানেন বার্তার একটি নির্দিষ্ট জায়গায় “500” লেখা আছে; ciphertext-এর সেই বাইটগুলোকে ('5' ⊕ '9') দিয়ে XOR করলেই plaintext-এ “900” হয়ে যায় — চাবি না জেনেই।
আধুনিক cipher তাই অন্য প্রতিশ্রুতি দেয়: “নিখুঁত” নয়, “গণনাগতভাবে নিরাপদ” — ১২৮ bit-এর ছোট চাবি থেকে লম্বা keystream, যা ভাঙতে মহাবিশ্বের বয়সের চেয়ে বেশি কাজ লাগে, আর সাথে AEAD tag দিয়ে বদল ধরা। ছোট চাবি বিতরণ করা যায় DH দিয়ে।
মূল উপলব্ধি: নিরাপত্তার প্রমাণ সবসময় শর্তসাপেক্ষ। বাস্তবের ব্যর্থতা প্রায় সবসময় শর্তের ফাঁকে — পুনর্ব্যবহার, বিতরণ, বা যে গুণ প্রমাণে ছিলই না (integrity). তাই “এটা প্রমাণিত নিরাপদ” শুনলে প্রথমে জিজ্ঞেস করুন: কোন শর্তে?
প্র ০২MD5 আর SHA-1 “ভাঙা” মানে কী — পুরো পৃথিবী রাতারাতি বদলায়নি কেন, আর এ থেকে crypto agility-র কী শিক্ষা?
Hash “ভাঙা” মানে সাধারণত collision resistance ভেঙেছে — কেউ এমন দুটি আলাদা ইনপুট বানাতে পারছেন যাদের hash এক। এর মানে এই নয় যে যেকোনো hash থেকে ইনপুট বের করা যায় (preimage). তবু ক্ষতি গুরুতর, কারণ সই আর certificate দাঁড়িয়ে থাকে hash-এর ওপর: একটি নিরীহ নথিতে সই নিয়ে একই hash-এর ক্ষতিকর নথিতে সেই সই বসানো যায়।
MD5-এর collision ২০০৪ সালে Wang Xiaoyun-এর দল প্রকাশ্যে দেখান। ২০০৮ সালে গবেষকেরা MD5 collision দিয়ে একটি জাল CA certificate বানিয়ে দেখান যে তত্ত্বটি বাস্তবে ব্যবহারযোগ্য। ২০১২ সালে Flame নামের গুপ্তচর-ম্যালওয়্যার MD5-এর একটি chosen-prefix collision ব্যবহার করে Microsoft-এর একটি পুরোনো certificate ব্যবস্থার নামে সই জাল করেছিল বলে বিশ্লেষণে পাওয়া যায় — দুর্বলতা জানার আট বছর পরেও MD5 একটি কোণায় টিকে ছিল।
SHA-1-এর তাত্ত্বিক দুর্বলতা ২০০৫ সাল থেকে জানা ছিল, ব্রাউজারগুলো ২০১৭ সালের দিকে SHA-1 certificate গ্রহণ বন্ধ করে, আর সেই বছরই Google ও CWI “SHAttered”-এ বাস্তব collision দেখায় — প্রকাশিত হিসাবে প্রায় ৬,৫০০ CPU-বছর আর ১১০ GPU-বছরের গণনা। পরে আরও সস্তা chosen-prefix আক্রমণও প্রকাশিত হয়। Git ঐতিহাসিকভাবে SHA-1 ব্যবহার করে; collision-ধরার বাড়তি যাচাই যোগ করা হয়েছে আর SHA-256-এ সরার কাজ চলছে, কিন্তু কোটি কোটি repository আর টুলকে সরানো ধীর প্রক্রিয়া।
রাতারাতি বদলায় না কারণ algorithm-এর নাম ছড়িয়ে আছে protocol-এর ফরম্যাটে, হার্ডওয়্যারে, পুরোনো যন্ত্রে, আর সবচেয়ে বেশি — মানুষের অভ্যাসে। যে protocol-এ algorithm বদলানোর ব্যবস্থা নকশাতেই থাকে (যেমন TLS-এর cipher suite আলোচনা), তা দ্রুত এগোতে পারে; যেখানে algorithm ফরম্যাটে স্থির, সেখানে বছরের পর বছর লাগে। একে বলে crypto agility — post-quantum রূপান্তরেও এই শিক্ষাই কাজে লাগছে।
মূল উপলব্ধি: Cryptography-তে আক্রমণ শুধু ভালো হয়, খারাপ হয় না। প্রথম তাত্ত্বিক দুর্বলতাকেই সরে যাওয়ার সংকেত ধরুন, আর নিজের নকশায় algorithm বদলানোর পথ খোলা রাখুন।
প্র ০৩Public key cryptography প্রকাশ্যে আবিষ্কারের আগেই কি গোপনে আবিষ্কৃত হয়েছিল? আর “crypto wars”-এর দুর্বল export cipher আজও কেন সমস্যা করেছিল?
১৯৯৭ সালে ব্রিটেনের গোয়েন্দা সংস্থা GCHQ প্রকাশ করে যে তাদের কর্মীরা অনেক আগেই একই ধারণায় পৌঁছেছিলেন: James Ellis ১৯৭০ সালের দিকে “non-secret encryption”-এর ধারণা দেন, Clifford Cocks ১৯৭৩ সালে RSA-র মতো একটি পদ্ধতি বের করেন, আর Malcolm Williamson পরে Diffie–Hellman-এর মতো key exchange. কিন্তু সব গোপন রাখা হয়েছিল। প্রকাশ্য জগতে Diffie–Hellman (১৯৭৬) আর RSA (১৯৭৭) স্বাধীনভাবে একই জায়গায় পৌঁছান, আর তাঁদের প্রকাশনাই ইন্টারনেট-বাণিজ্যের ভিত্তি গড়ে — গোপন আবিষ্কার সমাজকে কিছু দেয়নি, প্রকাশ্য আবিষ্কার দিয়েছে।
১৯৯০-এর দশকে যুক্তরাষ্ট্র শক্তিশালী cryptography-কে অস্ত্রের মতো রপ্তানি-নিয়ন্ত্রিত পণ্য গণ্য করত। ফলে প্রথম দিকের ব্রাউজারের আন্তর্জাতিক সংস্করণে “export-grade” cipher থাকত — ৪০-bit symmetric চাবি আর ৫১২-bit RSA বা DH. ৪০ bit মানে প্রায় ১.১ লাখ কোটি চাবি, যা তখনকার সাধারণ কম্পিউটারের নেটওয়ার্কেই দিনের মধ্যে ভাঙা যেত। Phil Zimmermann-এর PGP আর গবেষকদের আইনি লড়াইয়ের পর শতাব্দীর শেষে নিয়ম অনেক শিথিল হয়।
কিন্তু পুরোনো কোড রয়ে গিয়েছিল। ২০১৫ সালে FREAK আর Logjam আক্রমণ দেখায় যে অনেক সার্ভার তখনও export cipher সমর্থন করত, আর MITM আক্রমণকারী আলোচনার সময় ব্রাউজার আর সার্ভারকে সেই দুর্বল বিকল্পে নামিয়ে আনতে পারত (downgrade attack) — তারপর ৫১২-bit চাবি অল্প সময়ে ভাঙা যেত। Logjam-এর গবেষকেরা আরও দেখান, অনেক সার্ভার একই কয়েকটি DH prime ভাগ করে, তাই একটি prime-এর জন্য বড় প্রাক-গণনা অনেক সংযোগকে ঝুঁকিতে ফেলে।
এই অভিজ্ঞতাই TLS 1.3-এর নকশায় প্রতিফলিত: দুর্বল আর পুরোনো সব বিকল্প মুছে ফেলা, আর handshake-এর পুরো আলাপ সই ও MAC দিয়ে বাঁধা, যাতে downgrade ধরা পড়ে।
মূল উপলব্ধি: ইচ্ছা করে দুর্বল রাখা নিরাপত্তা শুধু “নির্দিষ্ট পক্ষের জন্য” দুর্বল থাকে না — দশক পরেও যে কেউ তার সুযোগ নেয়। আর যে বিকল্প protocol-এ থেকে যায়, আক্রমণকারী সেটিকেই বেছে নেওয়ানোর চেষ্টা করে।
প্র ০৪সবচেয়ে শক্ত algorithm-ও কেন খারাপ random সংখ্যায় ভেঙে পড়ে? বাস্তবের কয়েকটি ব্যর্থতা থেকে কী শিখবেন?
AES-256-এর নিরাপত্তা ধরে নেয় চাবিটি ২২৫৬টি সম্ভাবনার মধ্যে সমানভাবে এলোমেলো। চাবি যদি আসলে মাত্র ৩২,৭৬৮টি সম্ভাবনার একটি হয়, তাহলে চাবির দৈর্ঘ্য অর্থহীন — আক্রমণকারী শুধু ওই তালিকা চেষ্টা করবে। Algorithm-এর শক্তি আর চাবির অনিশ্চয়তা আলাদা জিনিস; দুর্বলতম অংশটিই নিরাপত্তা ঠিক করে।
Debian, ২০০৮: একটি memory-checking টুলের সতর্কবার্তা দূর করতে Debian-এর OpenSSL প্যাকেজ থেকে দুটি লাইন সরানো হয়েছিল, যার একটি আসলে entropy যোগ করত। প্রায় দুই বছর ধরে ওই সিস্টেমে বানানো SSH আর TLS চাবি এতই সীমিত ছিল যে গবেষকেরা সব সম্ভাব্য চাবির তালিকা বানিয়ে ফেলেন। সংশোধনের পর বিশ্বজুড়ে চাবি বদলাতে হয়েছিল।
ECDSA nonce: ECDSA প্রতিটি সইয়ে একটি গোপন এলোমেলো সংখ্যা চায়। একই সংখ্যা দুই সইয়ে এলে দুটি সমীকরণ থেকে private key সরাসরি হিসাব করা যায় — PS3-র ঘটনায় প্রতিবার একই সংখ্যা ছিল বলে প্রকাশ্য গবেষণায় দেখানো হয়, আর ২০১৩ সালে Android-এর একটি random-ত্রুটিতে কিছু Bitcoin wallet-এর অর্থ চুরি হয় বলে জানা যায়। এজন্যই Ed25519 আর RFC 6979-এর deterministic ECDSA সংখ্যাটি বার্তা ও private key থেকে hash দিয়ে বানায় — random-এর ওপর নির্ভরতাই সরিয়ে দেয়।
Dual_EC_DRBG: NIST-এর একটি random-generator মানদণ্ড নিয়ে ২০০৭ সালেই গবেষকেরা সতর্ক করেছিলেন যে এর ধ্রুবকগুলো একটি গোপন “পেছনের দরজা” লুকাতে পারে; ২০১৩ সালের প্রকাশিত নথির পর বিতর্ক জোরালো হয় আর NIST মানদণ্ডটি প্রত্যাহার করে। ব্যাখ্যাহীন ধ্রুবক নিয়ে সন্দেহ এখন crypto সমাজের স্বাভাবিক অভ্যাস।
আরেকটি নীরব ঝুঁকি: সদ্য চালু হওয়া embedded যন্ত্র বা VM, যার entropy জমার সময়ই হয়নি। ২০১২ সালের একটি বড় জরিপে ইন্টারনেটের বহু router আর যন্ত্রে একই বা গুণনীয়ক-ভাগ-করা RSA চাবি পাওয়া গিয়েছিল। এজন্য Linux-এর getrandom() ডিফল্টে entropy যথেষ্ট না হওয়া পর্যন্ত অপেক্ষা করে।
মূল উপলব্ধি: Random সংখ্যা একটি নিরাপত্তা-নির্ভরতা, সাধারণ সুবিধা নয়। OS-এর CSPRNG ছাড়া কিছু ব্যবহার করবেন না, আর যেখানে সম্ভব এমন নকশা বেছে নিন যা random-এর ভুল সহ্য করে।
প্র ০৫Quantum computer এখনো RSA ভাঙতে পারে না — তাহলে আজই post-quantum-এ সরার তাড়া কেন, আর রূপান্তরটি এত জটিল কেন?
Shor-এর algorithm-এর জন্য দরকার লক্ষ লক্ষ ভৌত qubit-এর একটি ত্রুটি-সংশোধিত quantum computer — আজকের পরীক্ষামূলক যন্ত্রগুলো তার অনেক দূরে, আর কবে পৌঁছাবে তা নিয়ে বিশেষজ্ঞদের অনুমান বহু বছরের পরিসরে ছড়ানো। তবু তাড়ার তিনটি কারণ আছে।
১. আজ রেকর্ড, পরে ডিক্রিপ্ট: কেউ আজ এনক্রিপ্ট করা ট্রাফিক জমিয়ে রাখলে ভবিষ্যতে quantum computer এলে ECDH দিয়ে বানানো চাবি বের করে পুরোনো আলাপ খুলতে পারবে। স্বাস্থ্য-তথ্য, সরকারি গোপন নথি, ব্যাংকের দীর্ঘমেয়াদি তথ্য — যা ১০–২০ বছর গোপন রাখতে হবে — সেগুলোর জন্য ঝুঁকি আজই। এজন্য key exchange আগে বদলাচ্ছে; সইয়ের ঝুঁকি মূলত ভবিষ্যতের জালিয়াতি, তাই সেখানে একটু সময় আছে।
২. রূপান্তরে দশক লাগে: SHA-1 থেকে সরতে লেগেছে প্রায় এক যুগ। Smart card, গাড়ির ECU, শিল্প-যন্ত্র, HSM — অনেক যন্ত্র ১৫–২০ বছর চলে, আর সেগুলোতে algorithm হার্ডওয়্যারে বাঁধা।
৩. নতুন algorithm-এর ওপর আস্থা সময় নেয়: NIST-এর প্রতিযোগিতায় শেষ ধাপের প্রার্থী SIKE ২০২২ সালে একটি সাধারণ ল্যাপটপেই ভেঙে ফেলা হয়েছিল। তাই এখনকার কৌশল hybrid: X25519 আর ML-KEM দুটো একসাথে, দুটির ফল মিলিয়ে চাবি — একটি ভাঙলেও অন্যটি রক্ষা করে।
জটিলতা কোথায়: আকার। ML-KEM-768-এর public key ১১৮৪ বাইট, ciphertext ১০৮৮ বাইট; ML-DSA-র সই কয়েক হাজার বাইট, যেখানে Ed25519-এর ৬৪ বাইট। TLS-এর ClientHello বড় হয়ে একাধিক packet-এ ভাঙতে পারে, আর কিছু পুরোনো middlebox বা firewall বড় ClientHello দেখে ভুল আচরণ করেছিল বলে ব্রাউজার-নির্মাতারা জানিয়েছেন। Certificate chain-এ PQ সই এলে handshake আরও ভারী হবে — এ নিয়ে গবেষণা চলছে।
মূল উপলব্ধি: নিরাপত্তার পরিকল্পনা আজকের আক্রমণকারীর জন্য নয়, তথ্যের পুরো জীবনকালের আক্রমণকারীর জন্য। আর বড় রূপান্তরের সবচেয়ে নিরাপদ পথ হলো পুরোনো আর নতুনকে একসাথে চালানো, যাতে কোনো একটির ব্যর্থতা সবকিছু না ভাঙে।
অনুশীলন
কাগজ-কলম নিন — modular হিসাব হাতে করলেই আসল বোঝা হয়।
-
হাতে RSA আর DH: (ক) p = 7, q = 11, e = 7 নিয়ে n, φ আর d বের করুন; তারপর m = 9 এনক্রিপ্ট করুন। (খ) Diffie–Hellman-এ p = 23, g = 5, Alice-এর a = 4, Bob-এর b = 3 হলে A, B আর ভাগ করা গোপন সংখ্যা কত?
(ক) n = 77, φ = 6 × 10 = 60. gcd(7, 60) = 1. 7d ≡ 1 (mod 60): 60 = 7·8 + 4, 7 = 4·1 + 3, 4 = 3·1 + 1 → 1 = 4 − 3 = 4 − (7 − 4) = 2·4 − 7 = 2·(60 − 8·7) − 7 = 2·60 − 17·7, তাই d ≡ −17 ≡ 43 (যাচাই: 7 × 43 = 301 = 5 × 60 + 1). Encrypt: 9² = 81 ≡ 4, 9⁴ ≡ 16, 9⁷ = 9⁴ · 9² · 9 ≡ 16 · 4 · 9 = 576 ≡ 576 − 539 = 37. Decrypt করলে 37⁴³ mod 77 = 9 ফেরত আসে।
(খ) A = 5⁴ mod 23 = 625 mod 23 = 4 (23 × 27 = 621); B = 5³ mod 23 = 125 mod 23 = 10. Alice: 10⁴ = 10000 mod 23 = 18; Bob: 4³ = 64 mod 23 = 18. দুজনেরই 18.
-
Birthday আর brute force-এর হিসাব: (ক) একটি সিস্টেম session ID হিসেবে hash-এর মাত্র প্রথম ৪০ bit রাখে। প্রায় কতগুলো ID তৈরির পর দুটি মিলে যাওয়ার সম্ভাবনা ৫০% হবে? (খ) ৬৪-bit চাবির একটি cipher-এ সেকেন্ডে 1012 চেষ্টা করা একটি যন্ত্র সব চাবি কত দিনে শেষ করবে?
(ক) k ≈ 1.177 × 240/2 = 1.177 × 220 = 1.177 × 1,048,576 ≈ ১২ লাখ ৩৫ হাজার. একটি জনপ্রিয় সেবায় এত session দিনেই তৈরি হতে পারে — তাই session ID বা token-এ অন্তত ১২৮ bit এলোমেলোতা রাখা হয়।
(খ) 264 ≈ 1.845 × 1019; ÷ 1012 = 1.845 × 107 সেকেন্ড; ÷ 86,400 ≈ ২১৩ দিন (গড়ে অর্ধেক, প্রায় ১০৭ দিন)। ১০০০টি যন্ত্রে মাত্র কয়েক ঘণ্টা — ৬৪ bit আর যথেষ্ট নয়।
-
আউটপুট অনুমান করুন — keystream reuse: দুটি ২-বাইটের বার্তা একই keystream
0F F0দিয়ে XOR করা হলো: P1 ="HI"(48 49), P2 ="OK"(4F 4B). C1, C2 আর C1 ⊕ C2 কত হবে? আক্রমণকারী শুধু C1, C2 আর P1 জানলে P2 কীভাবে পাবেন?C1 = 48⊕0F, 49⊕F0 =
47 B9; C2 = 4F⊕0F, 4B⊕F0 =40 BB. C1 ⊕ C2 = 47⊕40, B9⊕BB =07 02— আর P1 ⊕ P2 = 48⊕4F, 49⊕4B =07 02, হুবহু এক; keystream পুরো বাদ পড়ে গেছে। P2 = (C1 ⊕ C2) ⊕ P1 = 07⊕48, 02⊕49 =4F 4B="OK". -
কমান্ড ও কোড লিখুন: (ক) Linux-এ একটি ডাউনলোড করা ISO ফাইল নির্মাতার প্রকাশিত SHA-256-এর সাথে মেলানোর কমান্ড লিখুন। (খ) ব্রাউজারের JavaScript-এ একটি ১২৮-bit এলোমেলো token hex আকারে বানানোর এক লাইন লিখুন —
Math.random()কেন চলবে না, তাও বলুন।(ক)
sha256sum ubuntu.isoচালিয়ে আউটপুট প্রকাশিত মানের সাথে মেলান, অথবা প্রকাশিতSHA256SUMSফাইল থাকলেsha256sum -c SHA256SUMS --ignore-missing. macOS-এshasum -a 256 ubuntu.iso, Windows-এGet-FileHash ubuntu.iso. মনে রাখবেন, hash আর ফাইল একই সার্ভার থেকে এলে সার্ভার আক্রান্ত হলে দুটোই বদলানো যায় — তাই নির্মাতারাSHA256SUMS-এ GPG সইও দেন, যা যাচাই করা উচিত।(খ)
[...crypto.getRandomValues(new Uint8Array(16))].map(b => b.toString(16).padStart(2, "0")).join("").Math.random()CSPRNG নয় — ব্রাউজারগুলো সাধারণত দ্রুত কিন্তু অনুমানযোগ্য generator ব্যবহার করে, যার কয়েকটি আউটপুট থেকে ভেতরের অবস্থা বের করে পরের মানগুলো আন্দাজ করা প্রকাশ্য গবেষণায় দেখানো হয়েছে; তাছাড়া এর আউটপুটে ১২৮ bit এলোমেলোতাও থাকে না।
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমRSA key তৈরি আর ব্যবহারের ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- দুটি বড় গোপন মৌলিক সংখ্যা p আর q বাছাই
- n = p·q আর φ(n) = (p−1)(q−1) হিসাব
- gcd(e, φ) = 1 এমন public exponent e বাছাই (সাধারণত 65537)
- Extended Euclid দিয়ে d = e−1 mod φ বের করা
- (n, e) প্রকাশ, d গোপন রেখে বার্তার hash-এ সই
কোন হাতিয়ারটি non-repudiation দেয় — অর্থাৎ প্রেরক পরে বার্তা পাঠানোর কথা অস্বীকার করতে পারেন না?
- AES-GCM দিয়ে এনক্রিপশন
- HMAC-SHA256 tag
- SHA-256 hash
- Private key দিয়ে digital signature (যেমন Ed25519)
একটি ছবি AES-ECB mode-এ এনক্রিপ্ট করার পরেও ছবির আকৃতি বোঝা যায়। প্রধান কারণ কী?
- AES-এর চাবি খুব ছোট
- একই plaintext block সবসময় একই ciphertext block দেয়
- IV দুবার ব্যবহার হয়েছে
- ছবির header এনক্রিপ্ট হয়নি
একটি hash ফাংশনের আউটপুট ৬৪ bit. এলোমেলো বার্তা hash করতে থাকলে মোটামুটি কতগুলোর পর collision-এর সম্ভাবনা প্রায় ৫০% হবে?
- প্রায় 264
- প্রায় 263
- প্রায় 232
- প্রায় 216
একটি ওয়েবসাইট ব্যবহারকারীর password কীভাবে সংরক্ষণ করা উচিত?
- প্রতি ব্যবহারকারী আলাদা এলোমেলো salt আর Argon2id-এর মতো ধীর KDF
- Salt ছাড়া SHA-256
- AES-256 দিয়ে এনক্রিপ্ট করে
- Salt দিয়ে MD5
RSA-তে p = 5, q = 11 আর public exponent e = 3 হলে private exponent d কত?
- 13
- 27
- 37
- 18
প্রমাণীকরণ ছাড়া (কোনো সই বা certificate ছাড়া) ২০৪৮-bit Diffie–Hellman কোন আক্রমণের সামনে অসহায়?
- শুধু আড়ি পেতে A আর B থেকে চাবি হিসাব
- তৈরি হওয়া AES চাবির brute force
- সক্রিয় man-in-the-middle, যে দুই দিকে নিজের DH মান পাঠায়
- Hash collision আক্রমণ
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- লক্ষ্য অনুযায়ী হাতিয়ার: গোপনীয়তায় encryption, অখণ্ডতায় MAC বা AEAD, অস্বীকার ঠেকাতে digital signature; নকশা প্রকাশ্য, গোপন শুধু চাবি (Kerckhoffs).
- Symmetric: AES-GCM বা ChaCha20-Poly1305; ECB কখনো নয়; একই চাবিতে nonce দুবার দিলে C1 ⊕ C2 = P1 ⊕ P2.
- Hash: preimage 2n, collision 2n/2; MD5 আর SHA-1 ভাঙা; MAC-এ HMAC, password-এ salt আর Argon2id.
- Public key: DH খোলা চ্যানেলে চাবি দেয় কিন্তু পরিচয় নয় (MITM); RSA-র d = e−1 mod φ, বাস্তবে OAEP/PSS আর ≥২০৪৮ bit; ECC ছোট চাবিতে একই নিরাপত্তা।
- বাস্তবে: hybrid encryption, ephemeral DH-এ forward secrecy, CSPRNG, post-quantum hybrid — আর নিজে crypto না বানিয়ে যাচাই করা library ও যত্নশীল key management.
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ৪৮ · TLS আর HTTPS — handshake, certificate আর বিশ্বাসের শিকলপরবর্তী পর্বDH, সই আর AEAD একসাথে কাজে।
- পর্ব ৪৬ · নেটওয়ার্ক নিরাপত্তার ভিত্তি — CIA, হুমকি আর প্রতিরক্ষার স্তরআগের পর্বকোন হুমকির বিরুদ্ধে এই হাতিয়ারগুলো।
- পর্ব ৪৯ · Firewall আর VPN — nftables, IPsec আর WireGuardপ্রয়োগIPsec আর WireGuard-এ একই primitive.
- কম্পিউটার নেটওয়ার্ক · কোর্স হোম৬২টি পর্বপুরো কোর্সের রোডম্যাপ।
- DSA · Number theory — GCD, sieve আর modular arithmeticগণিতের ভিত্তিExtended Euclid, দ্রুত ঘাত আর modular inverse বিস্তারিত।
- Operating Systems · OS-এর নিরাপত্তাপাশের ট্র্যাকচাবি আর গোপন তথ্য OS কীভাবে রক্ষা করে।