এই পর্বে যা শিখবেন
- Block আর stream cipher-এর পার্থক্য, DES কেন অবসরে গেল, আর AES-এর একটি round-এ কী ঘটে
- ECB, CBC, CTR আর GCM কীভাবে কাজ করে, আর কোনটি কখন বিপজ্জনক
- IV আর nonce-এর পার্থক্য, আর nonce reuse কেন সর্বনাশ ডাকে
- Encryption একা কেন অখণ্ডতা দেয় না, আর AEAD কীভাবে সেই ফাঁক বন্ধ করে
- Random nonce-এর birthday সীমা হিসাব করা, nonce reuse ধরা, আর ঘটলে সাড়া দেওয়া
১ · এক চাবির তালা — symmetric encryption কী দেয়, কী দেয় না
বাড়ির দরজার তালা ভাবুন। যে চাবিতে তালা লাগান, সেই চাবিতেই খোলেন। পরিবারের প্রত্যেকের কাছে একটি করে কপি থাকে। Symmetric encryption-এর ধারণা ঠিক এটুকুই: পাঠানোর দিক আর পাওয়ার দিক একই গোপন চাবি জানে। Plaintext (মূল লেখা) আর চাবি মিলে তৈরি হয় ciphertext (তালাবন্ধ লেখা), আর একই চাবি দিয়ে ciphertext থেকে মূল লেখা ফেরে।
পর্ব ০৭-এ (Cryptography-র ভিত্তি) গোপনীয়তা, অখণ্ডতা আর পরিচয়ের পার্থক্য দেখা হয়েছে, আর Kerckhoffs-এর নীতি মনে করিয়ে দিয়েছে যে গোপন থাকবে শুধু চাবি। পর্ব ০২-এর (CIA triad) ভাষায় encryption মূলত confidentiality রক্ষা করে। Integrity বা availability রক্ষা করে না, যদি না আপনি আলাদা ব্যবস্থা নেন। এই একটি বাক্য মনে রাখলে এই পর্বের অর্ধেক ভুল এড়ানো যায়।
Symmetric cipher সাধারণত public key পদ্ধতির চেয়ে অনেক দ্রুত, তাই বড় ফাইল, disk, ডেটাবেস আর network ট্রাফিক এভাবেই এনক্রিপ্ট হয়। এর বড় দুর্বলতা হলো দুই পক্ষের কাছে চাবি পৌঁছানো। সেই সমস্যার সমাধান দেখবেন পর্ব ১০-এ (Public key cryptography).
Block cipher আর stream cipher
Block cipher
Block cipher একবারে নির্দিষ্ট আকারের টুকরো নেয়। চাবি ঠিক থাকলে প্রতিটি ইনপুট block একটি নির্দিষ্ট আউটপুট block-এ যায়, আর উল্টোটাও করা যায়। ডাকঘরের একই মাপের খামে চিঠি ভাগ করে পাঠানোর মতো।
AES: ১২৮ bit blockStream cipher
Stream cipher চাবি থেকে এলোমেলো দেখতে একটি লম্বা বাইটের সারি বানায়। এর নাম keystream. তারপর প্রতিটি বাইটের সাথে XOR করে। XOR-এর গুণ হলো (P ⊕ K) ⊕ K = P.
সীমারেখা বাস্তবে ঝাপসা। পরে দেখবেন CTR mode একটি block cipher-কে stream cipher বানিয়ে ফেলে। তাই “block না stream” যতটা নকশার প্রশ্ন, “কোন mode আর কোন nonce নিয়ম” ততটাই নিরাপত্তার প্রশ্ন।
এই পর্বের সব কোড খেলনা, চলে নিজের পাতায় ছোট in-memory ডেটার ওপর। উদ্দেশ্য ভুল চেনা আর ঠেকানো। অন্যের system-এর encryption পরীক্ষা করতে লিখিত অনুমতি লাগে; অনুমতি ছাড়া ঢোকা অপরাধ। সীমারেখা জানতে পর্ব ০৬ (আইন আর নৈতিকতা) দেখুন।
২ · DES থেকে AES — কেন পুরোনো cipher অবসরে গেল
১৯৭৭ সালে যুক্তরাষ্ট্রের National Bureau of Standards (আজকের NIST) IBM-এর একটি নকশা থেকে DES প্রকাশ করে: ৬৪ bit block, ৫৬ bit চাবি। দুই দশক ধরে ব্যাংক আর সরকার এটি ব্যবহার করেছে। ১৯৯৮ সালে EFF-এর বিশেষ যন্ত্র Deep Crack একটি DES চাবি প্রায় ৫৬ ঘণ্টায় বের করে দেখায়। মাঝপথের সমাধান ছিল Triple DES, কিন্তু সেটি ধীর, আর block তখনো ৬৪ bit. NIST ২০০৫ সালে DES-এর মান তুলে নেয়, আর SP 800-131A Rev. 2 অনুযায়ী ২০২৩ সালের পর Triple DES দিয়ে নতুন encryption অনুমোদিত নয়।
DES-এর সমস্যা দুটি, আর দুটিই সংখ্যার। প্রথমত, ২৫৬ ≈ ৭.২ × ১০১৬টি চাবি একসময় অসম্ভব মনে হলেও যন্ত্র সস্তা হতেই নাগালে চলে আসে। তাই একে বলা হয় brute force-এর সীমা। দ্বিতীয়ত, ৬৪ bit block ছোট। প্রায় ২৩২টি block, অর্থাৎ 32 GiB ডেটা এক চাবিতে গেলে দুটি ciphertext block মিলে যাওয়ার সম্ভাবনা গুরুতর হয়ে ওঠে। ২০১৬ সালের Sweet32 গবেষণা দেখায় লম্বা সংযোগে এই সীমা বাস্তব ঝুঁকি।
১৯৯৭ সালে NIST একটি প্রকাশ্য প্রতিযোগিতা শুরু করে। নকশা, আক্রমণের চেষ্টা, সবই ছিল খোলা। ২০০০ সালে বেলজিয়ামের Joan Daemen আর Vincent Rijmen-এর Rijndael নির্বাচিত হয়, আর ২০০১ সালে সেটি AES নামে FIPS 197 হিসেবে প্রকাশিত হয়। এটি open design নীতির সবচেয়ে ভালো উদাহরণগুলোর একটি।
| রূপ | চাবি | Block | Round |
|---|---|---|---|
| AES-128 | ১২৮ bit | ১২৮ bit | ১০ |
| AES-192 | ১৯২ bit | ১২৮ bit | ১২ |
| AES-256 | ২৫৬ bit | ১২৮ bit | ১৪ |
খেয়াল করুন, চাবি বড় হলেও block একই থাকে। Round মানে একই ধরনের কাজের একটি পালা। ১৯৪৯ সালে Claude Shannon দুটি গুণ চেয়েছিলেন: confusion (চাবি আর আউটপুটের সম্পর্ক জটিল করা) আর diffusion (একটি বাইটের প্রভাব সব দিকে ছড়ানো)। AES-এর চারটি কাজ এই দুটিই করে। রান্নার মতো ভাবুন: মসলা বদলানো, হাঁড়ির উপাদান সরানো, নেড়ে মেশানো, আর গোপন উপাদান যোগ করা, এভাবে বারবার।
নিচের stepper-এ FIPS 197-এর Appendix B-র আসল মান দেখুন। AES ১৬টি বাইটকে ৪ × ৪ ছকে সাজায়, যার নাম state. বাইটগুলো কলাম ধরে বসে।
- SubBytesবাইট বদল
- ShiftRowsসারি সরানো
- MixColumnsকলাম মেশানো
- AddRoundKeyচাবি মেশানো
input key 32 88 31 e0 2b 28 ab 09 43 5a 31 37 7e ae f7 cf f6 30 98 07 15 d2 15 4f a8 8d a2 34 16 a6 88 3c
19 a0 9a e9
3d f4 c6 f8
e3 e2 8d 48
be 2b 2a 08
d4 e0 b8 1e
27 bf b4 41
11 98 5d 52
ae f1 e5 30
d4 e0 b8 1e সারি ০: নড়েনি bf b4 41 27 সারি ১: ১ ঘর বাঁয়ে 5d 52 11 98 সারি ২: ২ ঘর 30 ae f1 e5 সারি ৩: ৩ ঘর
04 e0 48 28 66 cb f8 06 81 19 d3 26 e5 9a 7a 4c
a4 68 6b 02 9c 9f 5b 6a 7f 35 ea 50 f2 2b 43 49
- শুরু। ১৬ বাইট ইনপুট আর ১৬ বাইট চাবি। চাবি থেকে key schedule নামের নিয়মে আরও ১০টি round key তৈরি হয়। কলাম ধরে পড়লে ইনপুট শুরু হয়
32 43 f6 a8দিয়ে। - প্রথম AddRoundKey. প্রথম round-এর আগেই ইনপুট আর চাবি XOR হয়। যেমন
32 ⊕ 2b = 19. চাবি না জানলে এখান থেকেই পরের কোনো ধাপের ইনপুট জানা যায় না। - SubBytes. প্রতিটি বাইট একটি নির্দিষ্ট টেবিল (S-box) দেখে বদলায়:
19হয়d4. এটি confusion আনে, কারণ এই টেবিল সরল রৈখিক হিসাবের বাইরে। - ShiftRows. সারিগুলো বাঁয়ে ঘোরে: সারি ১ এক ঘর, সারি ২ দুই ঘর, সারি ৩ তিন ঘর। এক কলামের বাইট এবার ছড়িয়ে যায় চারটি কলামে।
- MixColumns. প্রতিটি কলামের চারটি বাইট গাণিতিকভাবে মিশে নতুন চারটি বাইট হয়। প্রথম কলাম
d4 bf 5d 30হলো04 66 81 e5. এখন একটি ইনপুট বাইট বদলালে পুরো কলাম বদলায়। - AddRoundKey. Round key XOR হয়ে round 1 শেষ, প্রথম কলাম এখন
a4 9c 7f f2. AES-128 এমন মোট ১০ round চালায়, শেষ round-এ MixColumns থাকে না। দুই round-এর পরেই প্রতিটি আউটপুট বাইট প্রতিটি ইনপুট বাইটের ওপর নির্ভর করে।
মানগুলো আমরা নিজের scratch script-এ হিসাব করে Appendix B-র সাথে মিলিয়েছি। AES-এর চার কাজ আপনাকে হাতে করতে হবে না, আর কখনো নিজে লিখবেনও না। জানা দরকার একটি কারণে: AES একটি মাত্র ১৬ বাইটের block নিয়ে কাজ করে। ১৬ বাইটের বেশি ডেটা হলে কী করবেন, প্রায় সব ভুল সেখানেই শুরু হয়।
৩ · Mode — একটি block থেকে পুরো বার্তা
Mode of operation হলো সেই নিয়ম, যা বলে দেয় block cipher দিয়ে লম্বা বার্তা কীভাবে এনক্রিপ্ট হবে। NIST SP 800-38A (২০০১) ECB, CBC, CFB, OFB আর CTR বর্ণনা করে, আর SP 800-38D (২০০৭) GCM. নিচের ছবিতে তিনটি mode-এর গঠন দেখুন।
ECB, CBC আর CTR-এর গঠন
How ECB, CBC and CTR chain two blocks
ECB — কোড-বইয়ের ফাঁদ
ECB-তে প্রতিটি block আলাদাভাবে এনক্রিপ্ট হয়। ধরুন একটি পুরোনো কোড-বইয়ে “টাকা” লিখলেই সবসময় “আম” লেখা হয়। কেউ অর্থ না জানলেও দেখবে কোন শব্দ কতবার ফিরে আসছে। ECB ঠিক তাই করে: একই plaintext block মানেই একই ciphertext block. চাবি ভাঙেনি, তবু নকশা ফাঁস হয়ে গেছে।
CBC — আগের ciphertext-এর সাথে শিকল
CBC-তে প্রতিটি plaintext block আগের ciphertext block-এর সাথে XOR হয়ে তবেই AES-এ যায়। প্রথম block-এর আগে কিছু নেই, তাই লাগে IV (initialization vector). CBC-র IV গোপন নয়, ciphertext-এর সাথেই যায়, কিন্তু হতে হবে আগে থেকে অনুমান করা যায় না এমন। অনুমানযোগ্য IV থেকেই TLS 1.0-র CBC-তে ২০১১ সালে BEAST সমস্যা দেখা দেয়। CBC-তে বার্তাকে block-এর মাপে পূরণ করতে padding লাগে, আর সেখান থেকে আরেক ধরনের ফাঁদ আসে (অংশ ৫)।
CTR — block cipher থেকে stream
CTR-এ AES দিয়ে plaintext এনক্রিপ্ট করাই হয় না। এনক্রিপ্ট হয় nonce‖0, nonce‖1, nonce‖2 এমন একটি গণনা, আর তার ফল হয় keystream. সেই keystream plaintext-এর সাথে XOR হয়। সুবিধা অনেক: padding লাগে না, block-গুলো সমান্তরালে চলে, যেকোনো জায়গা থেকে পড়া যায়। মূল্য একটি কঠিন শর্ত: একই চাবিতে একই (nonce, counter) জোড়া কখনো ফিরতে পারবে না।
এবার হাতে হিসাব করা যায় এমন একটি খেলনা cipher দিয়ে তিনটি mode পাশাপাশি দেখুন। দুটি plaintext block ইচ্ছা করেই একই রাখা হয়েছে।
E(x) = ((x XOR 2b) * 5 + 7) mod 256 P1 = 41, P2 = 41 (hex), IV = 3c CTR: nonce = a, counter = 0, 1
| ECB C1, C2 | |
| CBC C1, C2 | |
| CTR keystream | |
| CTR C1, C2 |
- প্রস্তুতি। খেলনা চাবি
2b, আরEএকটি সাধারণ সূত্র। আসল cipher এত সরল নয়; এখানে শুধু হাতে মেলানোর সুবিধার জন্য এটি নেওয়া হয়েছে। - ECB.
41 ⊕ 2b = 6a(দশমিকে 106),106 × 5 + 7 = 537, আর537 mod 256 = 25 = 19(hex). দুটি block-এই একই হিসাব, তাই C1 = C2 =19. পর্যবেক্ষক জেনে গেল P1 = P2. - CBC, প্রথম block.
41 ⊕ 3c = 7d. তারপরE(7d) = b5. IV কাজটি করল প্রথম block-কে অনন্য বানিয়ে। - CBC, দ্বিতীয় block. এবার IV-এর জায়গায় C1:
41 ⊕ b5 = f4, আরE(f4) = 62. plaintext একই হলেও ciphertext আলাদা। খুলতে গেলে প্রাপক উল্টো পথে চলেন। - CTR keystream. nonce
aআর counter মিলেa0,a1.E(a0) = be,E(a1) = b9. plaintext এখনো কাজে লাগেনি। - CTR ciphertext.
41 ⊕ be = ff,41 ⊕ b9 = f8. খোলার জন্য প্রাপক একই keystream বানিয়ে আবার XOR করেন; তাই CTR-এ AES-এর উল্টো দিক লাগে না। - তুলনা। ECB-তে দুটি মান এক, CBC আর CTR-এ আলাদা। কিন্তু এই পার্থক্য টিকে থাকে শুধু IV আর nonce ঠিক থাকলে। আরেকটি বার্তায় একই nonce
aব্যবহার করলে keystream আবারbe, b9হবে। পরের অংশের বিষয় এটাই।
এবার একটি ছোট ছবিতে পার্থক্যটি চোখে দেখুন। প্রতিটি pixel একটি ৮-bit block, চিহ্নগুলো ciphertext বাইটের প্রতিনিধি।
// Toy 8-bit block cipher: real নয়, শুধু ধারণার জন্য. Real: AES-GCM.
function mulberry32(a) {
return () => { a = a + 0x6D2B79F5 | 0; let t = Math.imul(a ^ a >>> 15, 1 | a);
t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t; return ((t ^ t >>> 14) >>> 0) / 4294967296; };
}
const rnd = mulberry32(2026); // the "key" picks one shuffle of 0..255
const E = [...Array(256).keys()];
for (let i = 255; i > 0; i--) {
const j = Math.floor(rnd() * (i + 1)); [E[i], E[j]] = [E[j], E[i]];
}
const SYM = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const sym = b => SYM[b % 64];
const img = ["..........", "...####...", "..#....#..", "..#....#..", "...####...", ".........."];
const NONCE = 0x20;
let ctr = 0;
const ecbSeen = new Set(), ctrSeen = new Set();
console.log("plain ECB CTR");
for (const row of img) {
let e = "", c = "";
for (const ch of row) {
const p = ch.charCodeAt(0);
const eb = E[p], cb = p ^ E[(NONCE + ctr++) & 255];
ecbSeen.add(eb); ctrSeen.add(cb);
e += sym(eb); c += sym(cb);
}
console.log(row + " " + e + " " + c);
}
console.log("distinct bytes: ECB =", ecbSeen.size, ", CTR =", ctrSeen.size);..#....#.. yykyyyykyy fUidTjcmBJ
distinct bytes: ECB = 2 , CTR = 57
দুটি pixel রঙ, তাই ECB-তে ciphertext-ও মাত্র ২ রকম (y আর k). ছবির আকৃতি হুবহু রয়ে গেছে। CTR-এ প্রতিটি অবস্থানে আলাদা keystream, তাই ৬০টি pixel-এ ৫৭ রকম বাইট, আকৃতি নেই। AES-এ block ১৬ বাইট, কিন্তু ফাঁসের নিয়ম একই: দুটি ১৬ বাইটের block মিললে ciphertext-ও মেলে। Block-এর আকার ৮ bit রাখা হয়েছে শুধু ছবিটি ছোট রাখার জন্য; এই খেলনা real নয়, শুধু ধারণার জন্য।
৪ · IV, nonce আর পুনর্ব্যবহারের সর্বনাশ
Nonce মানে “number used once”, একবারই ব্যবহৃত সংখ্যা। অফিসের রেজিস্টার খাতার ক্রমিক নম্বরের মতো: গোপন নয়, কিন্তু একই নম্বর দুবার বসলে খাতার হিসাব ভেঙে পড়ে। IV-ও একই পরিবারের, তবে শব্দ দুটির দাবি আলাদা।
| CBC-র IV | CTR ও GCM-এর nonce | |
|---|---|---|
| গোপন? | না | না |
| মূল শর্ত | অনুমান করা যাবে না | একই চাবিতে কখনো ফিরবে না |
| Counter চলবে? | না, CBC-তে অনুমানযোগ্য IV বিপজ্জনক | হ্যাঁ, অনন্য থাকলেই হলো |
| পুনর্ব্যবহারে | একই শুরুর বার্তা চেনা যায় | Keystream ফিরে আসে: গোপনীয়তা ভাঙে, GCM-এ জালিয়াতিও সম্ভব |
শব্দের ব্যবহার সব জায়গায় সমান নয়। NIST GCM-এর nonce-কেও “IV” বলে, আর অনেক library-র parameter-এর নাম iv. তাই নাম নয়, mode-এর শর্ত দেখে বিচার করুন।
কেন এত বিপদ — ছোট উদাহরণে
আগের stepper-এর keystream ছিল be. ধরুন ভুল করে একই চাবি আর একই nonce দিয়ে দুটি আলাদা বার্তার প্রথম বাইট এনক্রিপ্ট হলো: P = 41 আর Q = 4d. তাহলে C1 = 41 ⊕ be = ff, আর C2 = 4d ⊕ be = f3. পথের একজন পর্যবেক্ষক শুধু দুটি ciphertext দেখেন। তিনি XOR করলে পান ff ⊕ f3 = 0c, যা হুবহু 41 ⊕ 4d = 0c. চাবি কিছুই জানতে হলো না:
Keystream কেটে গেল। Plaintext-এর গঠন যেহেতু এলোমেলো নয়, দুই plaintext-এর XOR থেকে অনেক তথ্য বের হতে পারে, আর একটি বার্তা জানা থাকলে অন্যটি সরাসরি মিলে যায়। এটি one-time pad-এর একই পাতা দুবার ব্যবহারের ভুল। নিচের খেলনা কোডে ভুলটি দেখুন, সাথে দেখুন রক্ষক কীভাবে log থেকে এটি ধরতে পারেন।
// Toy stream cipher: real নয়, শুধু ধারণার জন্য. A warning about misuse.
function stream(key, nonce, n) {
let a = (key ^ Math.imul(nonce, 0x9E3779B1)) | 0;
const out = [];
for (let i = 0; i < n; i++) {
a = a + 0x6D2B79F5 | 0; let t = Math.imul(a ^ a >>> 15, 1 | a);
t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t; out.push((t ^ t >>> 14) & 255);
}
return out;
}
const bytes = s => [...s].map(c => c.charCodeAt(0));
const hex = a => a.map(b => b.toString(16).padStart(2, "0")).join("");
const xor = (a, b) => a.map((x, i) => x ^ b[i]);
const KEY = 0x2b7e1516;
const p1 = bytes("PAY 500 TK RINA"), p2 = bytes("MEET 9 PM GATE3");
const c1 = xor(p1, stream(KEY, 7, 15));
const c2 = xor(p2, stream(KEY, 7, 15)); // MISUSE: nonce 7 again
const c3 = xor(p2, stream(KEY, 8, 15)); // correct: fresh nonce
const leak = xor(c1, c2), goal = xor(p1, p2);
console.log("c1 xor c2 :", hex(leak));
console.log("p1 xor p2 :", hex(goal));
console.log("same nonce leaks p1^p2:", hex(leak) === hex(goal));
console.log("fresh nonce leaks p1^p2:", hex(xor(c1, c3)) === hex(goal));
// Defender: spot a repeated (key, nonce) pair in an in-memory log.
const log = [["k1", 7], ["k1", 8], ["k1", 7], ["k2", 7]];
const seen = new Set();
for (const [k, n] of log) {
const id = k + ":" + n;
console.log(id, seen.has(id) ? "REUSE: stop and rotate key" : "ok");
seen.add(id);
}c1 xor c2 : 1d041c7415091070196b67131d0b72
p1 xor p2 : 1d041c7415091070196b67131d0b72
same nonce leaks p1^p2: true
fresh nonce leaks p1^p2: false
k1:7 REUSE: stop and rotate key
প্রথম দুটি লাইন হুবহু এক: চাবি ব্যবহার না করেই দুই plaintext-এর XOR বেরিয়ে এসেছে। নতুন nonce দিলে মেলে না (false). শেষ অংশটি রক্ষকের: k1:7 দ্বিতীয়বার এলেই ধরা পড়ে, অথচ k2:7 ঠিক আছে, কারণ নিয়মটি (চাবি, nonce) জোড়ার ওপর। Nonce একই হলেও চাবি আলাদা হলে সমস্যা নেই। বাস্তব system-এ এমন গণনা আপনার নিজের log-এ চালান।
৫ · Encryption একা অখণ্ডতা দেয় না — AEAD কেন
অনেকে ভাবেন, “এনক্রিপ্ট করা আছে, কেউ বদলাতে পারবে না।” এটি সবচেয়ে ব্যয়বহুল ভুল ধারণাগুলোর একটি। তালাবন্ধ বাক্স কেউ খুলতে না পারলেও বাক্সের গায়ে আঘাত করতে পারে, আর ভেতরের জিনিসের জায়গা বদলে যেতে পারে। CTR আর stream cipher-এ ciphertext-এর একটি bit উল্টালে plaintext-এর ঠিক সেই bit উল্টে যায়। এই গুণের নাম malleability. প্রাপক কিছুই টের পান না, কারণ decrypt সবসময় “কিছু একটা” ফেরত দেয়।
নিচের খেলনা কোডে ciphertext সরাসরি বদলানো হয়েছে, চাবি ছাড়াই। দেখুন authentication tag না থাকলে কী হয়, আর থাকলে কী হয়। এখানে keystream খেলনা, কিন্তু HMAC আর constant-time তুলনা Python-এর আসল library.
# Toy keystream with a real HMAC tag: real নয়, শুধু ধারণার জন্য
import hashlib, hmac
ENC_KEY = b"example-enc-key" # fake demo keys, two separate keys
MAC_KEY = b"example-mac-key"
NONCE = b"n-0001"
def keystream(n):
out, ctr = b"", 0
while len(out) < n:
out += hashlib.sha256(ENC_KEY + NONCE + bytes([ctr])).digest()
ctr += 1
return out[:n]
def xor(a, b):
return bytes(x ^ y for x, y in zip(a, b))
def seal(msg): # encrypt first, then MAC the ciphertext
ct = xor(msg, keystream(len(msg)))
return ct, hmac.new(MAC_KEY, NONCE + ct, hashlib.sha256).digest()
def open_box(ct, tag): # check the tag BEFORE decrypting
want = hmac.new(MAC_KEY, NONCE + ct, hashlib.sha256).digest()
if not hmac.compare_digest(want, tag):
return None
return xor(ct, keystream(len(ct)))
ct, tag = seal(b"PAY 500 TK")
bad = bytearray(ct)
bad[4] ^= ord("5") ^ ord("9") # changed in transit, no key used
bad = bytes(bad)
print("no check :", xor(bad, keystream(len(bad))))
print("with check:", open_box(bad, tag))
print("untouched :", open_box(ct, tag))no check : b'PAY 900 TK'
with check: None
untouched : b'PAY 500 TK'
পথে একটি বাইটের কয়েকটি bit বদলাতেই, tag না দেখলে “500” হয়ে গেল “900”, কোনো চাবি ছাড়াই। Tag দেখলে ফল None: বার্তা প্রত্যাখ্যাত, আর decrypt-ই হয়নি। অক্ষত বার্তা ঠিকই খোলে। লক্ষ্য করুন তিনটি নিয়ম: encrypt আর MAC-এর চাবি আলাদা, nonce-ও MAC-এ আছে, আর তুলনা hmac.compare_digest দিয়ে, যাতে সময়ের পার্থক্য থেকে তথ্য না যায়। Hash আর HMAC-এর ভেতরের কাজ পর্ব ০৯-এ (Hash আর MAC) দেখবেন।
তিন ক্রম, একটি নিরাপদ অভ্যাস
Encryption আর MAC একসাথে দেওয়ার তিনটি পুরোনো পথ আছে। পোস্ট অফিসের খামে সিলমোহরের কথা ভাবুন: সিল কি চিঠির গায়ে, না বন্ধ খামের ওপর?
| ক্রম | কীভাবে | ফল |
|---|---|---|
| Encrypt-then-MAC | আগে encrypt, পরে ciphertext-এর ওপর MAC. উদাহরণ: IPsec ESP | নিরাপদ পছন্দ। জাল বার্তা decrypt-এর আগেই বাদ। |
| MAC-then-encrypt | আগে plaintext-এর MAC, পরে দুটোই encrypt. উদাহরণ: পুরোনো TLS | Decrypt করে তবেই যাচাই। ভুল আচরণ থেকে তথ্য ফাঁসের ইতিহাস আছে। |
| Encrypt-and-MAC | দুটো আলাদাভাবে plaintext থেকে। উদাহরণ: SSH-এর মূল নকশা | MAC plaintext সম্পর্কে তথ্য দিতে পারে, তাই সাধারণ অর্থে নিরাপদ বলা যায় না। |
২০০০ সালে Bellare আর Namprempre এই ক্রমগুলোর নিরাপত্তা তাত্ত্বিকভাবে তুলনা করেন। তবু বাস্তবে নিজে জোড়া দেওয়া ঝুঁকিপূর্ণ: আলাদা চাবি লাগে, nonce-কেও MAC-এ রাখতে হয়, তুলনা constant-time হতে হয়। CBC-তে যাচাই ছাড়া padding ত্রুটি দেখালে padding oracle নামের সমস্যা দেখা দেয়: ত্রুটির বার্তা নিজেই গোপন তথ্যের ইঙ্গিত দেয়। Vaudenay ২০০২ সালে এটি বর্ণনা করেন, আর পরে TLS-এর CBC-তে নানা রূপে ফিরে আসে। তাই সমাধান এলো একসাথে বাঁধা এক প্যাকেজে।
AEAD — এক কাজে গোপনীয়তা আর অখণ্ডতা
AEAD (Authenticated Encryption with Associated Data) একটিমাত্র interface: ইনপুট চাবি, nonce, plaintext আর associated data. আউটপুট ciphertext আর tag. RFC 5116 (২০০৮) এই interface-কে মান হিসেবে বর্ণনা করে।
Associated data (AD) হলো যে অংশ এনক্রিপ্ট হবে না, কিন্তু বদলানোও যাবে না। মোবাইল ব্যাংকিংয়ের লেনদেনের কথা ভাবুন: লেনদেনের নোট গোপন, কিন্তু রাউটিংয়ের জন্য লেনদেন নম্বর খোলা থাকতে হয়। সেই নম্বর কেউ বদলালে যেন ধরা পড়ে। Packet header, ডেটাবেসের row id, চাবির version, সবই ভালো AD.
AEAD বার্তা — কোনটি গোপন, কোনটি শুধু সুরক্ষিত
What an AEAD message hides and what it only protects
৬ · AES-GCM আর ChaCha20-Poly1305
AES-GCM হলো CTR mode-এর encryption আর GHASH নামের একটি দ্রুত গাণিতিক হিসাব। সাধারণ রূপে nonce ৯৬ bit, tag ১২৮ bit. চাবি থেকে একটি গোপন মান H তৈরি হয় (H = E(K, 0)). GHASH সেই H দিয়ে AD আর ciphertext থেকে একটি মান বানায়, আর শেষে nonce-নির্ভর একটি গোপন মুখোশ XOR হয়ে tag হয়।
নিচের মানগুলো আমরা নিজের scratch folder-এ Node.js-এর crypto দিয়ে আসল AES-128-GCM চালিয়ে পেয়েছি। চাবিটি শুধু দেখানোর জন্য, কোথাও ব্যবহারের নয়।
- ইনপুটkey, nonce, AD, P
- EncryptCTR
- TagGHASH
- Openআগে যাচাই
key 000102030405060708090a0b0c0d0e0f nonce a0a1a2a3a4a5a6a7a8a9aaab AD order=1042 P PAY 500 TK
P 5041592035303020544b
KS aa8638bb7e89330a8a78
C fac7619b4bb9032ade33
GHASH(H, AD, C) ⊕ E(K, nonce-block)
T = d3e38fe517eb11e6
401244abd98d4fdf
nonce a0a1a2a3a4a5a6a7a8a9aaab
AD order=1042
C fac7619b4bb9032ade33
T d3e38fe517eb11e6
401244abd98d4fdf
tag recomputed == T
OK: PAY 500 TK
C fac7619b43b9032ade33 FAIL: Unsupported state or unable to authenticate data plaintext দেওয়া হয়নি
AD order=1043 FAIL: Unsupported state or unable to authenticate data nonce-এর শেষ bit বদলালেও FAIL
- ইনপুট। প্রেরক ও প্রাপক দুজনেই চাবি জানেন। Nonce এই চাবিতে আগে ব্যবহৃত নয়। AD
order=1042খোলা থাকবে, plaintext ১০ বাইট। - Encrypt. AES CTR mode-এ keystream বানায়, আর plaintext-এর সাথে XOR হয়ে ciphertext হয়। Ciphertext-ও ১০ বাইট, GCM-এ padding লাগে না।
- Tag. GHASH AD আর ciphertext, দুটোকেই হিসাবে নেয়, তাদের দৈর্ঘ্যও। এরপর nonce-নির্ভর মুখোশ XOR হয়ে ১৬ বাইটের tag হয়।
- পাঠানো। Nonce, AD, ciphertext আর tag পথে যায়। এর কোনোটিই গোপন চাবি নয়। পর্যবেক্ষক AD পড়তে পারেন, plaintext পারেন না।
- Open, সব ঠিক। প্রাপক একই হিসাবে tag বানিয়ে পাওয়া tag-এর সাথে constant-time তুলনা করেন। মিলেছে, তাই plaintext
PAY 500 TKফেরত এলো। - Ciphertext-এ এক bit বদল। পঞ্চম বাইট
4bথেকে43হলো। হিসাব করা tag আর মেলে না। Library ত্রুটি দেয়, plaintext দেয় না। অংশ ৫-এর “PAY 900 TK” এখানে অসম্ভব। - AD-তে বদল। Ciphertext অক্ষত, শুধু
order=1043. তবু FAIL, আর nonce বদলালেও FAIL. তাই tag যাচাই করে: এই চাবি, এই nonce, এই AD আর এই ciphertext একসাথে অক্ষত। একটি ciphertext অন্য order-এ জুড়ে দেওয়া যায় না।
Tag মেলার আগে plaintext ব্যবহার করবেন না। Streaming API-তে অনেক library বাইট আগে দিয়ে দেয়, tag শেষে যাচাই করে। ফলে যাচাইয়ের আগেই লগ, ডেটাবেস বা JSON parser-এ ঢুকে পড়তে পারে। Tag ব্যর্থ হলে পুরো ডেটা ফেলে দিন, ঘটনাটি log করুন, আর বাইরে সাধারণ একটি ত্রুটি দেখান।
ChaCha20-Poly1305
RFC 8439 (২০১৮) এই AEAD-কে বর্ণনা করে। ChaCha20 হলো Daniel J. Bernstein-এর stream cipher, যা শুধু যোগ, ঘোরানো আর XOR দিয়ে চলে; Poly1305 tag বানায়। চাবি ২৫৬ bit, nonce ৯৬ bit, tag ১২৮ bit. এখানেও একই চাবিতে nonce ফেরানো যাবে না। পার্থক্য আসে হার্ডওয়্যারে।
| বিষয় | AES-GCM | ChaCha20-Poly1305 |
|---|---|---|
| যেখানে ভালো | AES নির্দেশ থাকা CPU-তে খুব দ্রুত | AES নির্দেশ নেই এমন ছোট ফোন, IoT যন্ত্রে দ্রুত |
| Software-এ নিরাপদ বাস্তবায়ন | Table-ভিত্তিক AES-এ timing ঝুঁকি থাকতে পারে | constant-time লেখা তুলনামূলক সহজ |
| এক বার্তার সীমা | প্রায় 64 GiB | প্রায় 256 GiB |
| মান ও নিয়ম | NIST SP 800-38D অনুমোদিত, FIPS পরিবেশে সাধারণ পছন্দ | IETF RFC 8439; FIPS-এর শর্ত থাকলে আগে নিয়ম মিলিয়ে নিন |
| TLS 1.3 (প্রথম RFC 8446, এখন RFC 9846) | AES-128-GCM আবশ্যক | বাস্তবায়নের পরামর্শ (SHOULD) |
সিদ্ধান্তের নিয়মটি সহজ। সার্ভার আর আধুনিক ল্যাপটপে AES-GCM সাধারণত ভালো। AES নির্দেশ নেই এমন যন্ত্রে, বা যেখানে software-এ constant-time চাই, ChaCha20-Poly1305 ভালো। দুটোই নিরাপদ পছন্দ, দুটোরই nonce শর্ত একই।
৭ · Nonce বানানোর নীতি — birthday সীমা আর রক্ষকের পরিকল্পনা
Nonce বানানোর দুই পথ: ক্রমিক counter, অথবা CSPRNG থেকে random সংখ্যা। Random সহজ, state রাখতে হয় না। কিন্তু random হলেই পুনরাবৃত্তি অসম্ভব নয়। প্রশ্ন হলো কতগুলো বার্তার পরে ঝুঁকি মানা যায় না।
Birthday হিসাব
একটি ক্লাসে মাত্র ২৩ জন থাকলেই দুজনের জন্মদিন মিলে যাওয়ার সম্ভাবনা ৫০%-এর বেশি। কারণ আমরা নির্দিষ্ট একজনের সাথে মিল খুঁজছি না, যেকোনো জোড়ার মিল খুঁজছি, আর জোড়ার সংখ্যা দ্রুত বাড়ে। একে বলে birthday bound. nটি বার্তা হলে জোড়া n(n−1)/2টি, আর b-bit nonce-এ প্রতিটি জোড়া মেলার সম্ভাবনা 2^−b. তাই ছোট p-র জন্য:
পুরো হিসাব, b = 96: n = 232 হলে p ≈ 264 ÷ 297 = 2−33 ≈ ১.১৬ × ১০−১০. প্রায় ৮৬০ কোটিতে একবার। NIST SP 800-38D-এর শর্ত হলো এক চাবিতে random IV-র সংঘর্ষের সম্ভাবনা ২−৩২-এর নিচে থাকবে, আর তাই সেখানে সীমা ২৩২ বার encryption. সেকেন্ডে ১ লাখ বার্তায় এই সীমা আসে প্রায় ১২ ঘণ্টায়। সংখ্যাটি বড় শোনালেও ব্যস্ত সার্ভিসে সহজেই পৌঁছায়।
// Birthday-bound calculator for random nonces (pure arithmetic).
const pAny = (n, bits) => -Math.expm1(-n * (n - 1) / 2 / 2 ** bits);
console.log("messages p, 96-bit random nonce");
for (const e of [20, 28, 32, 36, 40, 44, 48]) {
console.log(("2^" + e).padEnd(10), pAny(2 ** e, 96).toExponential(2));
}
const half = Math.sqrt(2 * Math.LN2 * 2 ** 96);
console.log("50% near n =", half.toExponential(2));
console.log("n for p = 2^-32: 2^" + Math.log2(Math.sqrt(2 * 2 ** -32 * 2 ** 96)).toFixed(1));
console.log("1e9 messages: p =", pAny(1e9, 96).toExponential(2));
console.log("64-bit nonce, 2^32 messages: p =", pAny(2 ** 32, 64).toFixed(3));
console.log("192-bit nonce, 2^64 messages: p =", (2 ** 128 / 2 ** 193).toExponential(2));
for (const r of [1e3, 1e5, 1e6]) {
const hours = 2 ** 32 / r / 3600;
console.log(r.toExponential(0) + " msg/s reaches 2^32 in", hours.toFixed(1), "hours");
}2^32 1.16e-10
2^44 1.95e-3
2^48 3.93e-1
50% near n = 3.31e+14
n for p = 2^-32: 2^32.5
64-bit nonce, 2^32 messages: p = 0.393
192-bit nonce, 2^64 messages: p = 2.71e-20
1e+5 msg/s reaches 2^32 in 11.9 hours
২৩২-এ ঝুঁকি খুব ছোট, ২৪৮-এ প্রায় ৩৯%, আর প্রায় ৩.৩১ × ১০১৪ বার্তায় ৫০%. p = ২−৩২ আসে n ≈ ২৩২.৫-এ, তাই NIST-এর ২৩২ সীমা শর্তের ভেতরেই থাকে। Nonce যদি ৬৪ bit হতো, একই ২৩২ বার্তায় ঝুঁকি ৩৯%. এই সংখ্যাটি Böck ও সহকর্মীদের ২০১৬ সালের TLS গবেষণার হিসাবের সাথে মেলে। আর ১৯২ bit nonce-এ ২৬৪ বার্তাতেও ঝুঁকি ২.৭১ × ১০−২০, এজন্যই XChaCha20 random nonce-এর জন্য জনপ্রিয়। একই হিসাবে দেখুন, nonce-এর এক bit কমলে ঝুঁকি দ্বিগুণ হয়।
কোন পথ কখন
| কৌশল | কখন ভালো | ঝুঁকি |
|---|---|---|
| Counter | এক প্রেরক, স্থির state. TLS-এর record নম্বর এভাবে চলে | Restart, VM snapshot বা একই চাবি দুই instance-এ থাকলে reset হতে পারে |
| ৯৬-bit random | কম বার্তা, অনেক instance | ২৩২ সীমা; অনেক গবেষক আরও সাবধানতা চান |
| XChaCha20-Poly1305 | Random nonce চাই, বার্তা অনেক | ১৯২ bit nonce; libsodium-এ আছে, তবে IETF মান নয় |
| AES-GCM-SIV (RFC 8452) | Nonce ভুলের ক্ষতি কমাতে হবে | একই nonce-এ শুধু একই বার্তা চেনা যায়; এটি ছাড়পত্র নয়, nonce এখনো অনন্য রাখা ভালো |
| Message-ভিত্তিক নতুন চাবি | চাবি প্রায়ই ঘোরানো যায় | Key derivation সঠিকভাবে করতে হয় |
এবার পরিস্থিতিটি রক্ষকের চোখে দেখুন। কাল্পনিক invoice-api সার্ভিস GCM-এ counter nonce ব্যবহার করে। Log-এর মান fake, চাবি log-এ নেই, শুধু key_id আর nonce.
10:00:01 key=k7 nonce=...0041 rec=A 10:00:02 key=k7 nonce=...0042 rec=B 10:00:03 key=k7 nonce=...0043 rec=C
10:05:00 VM restored from snapshot
snapshot-এ counter ছিল ...0041 এর আগে
10:05:03 key=k7 nonce=...0041 rec=D 10:05:04 key=k7 nonce=...0042 rec=E decrypt আগের মতোই সফল
group by (key_id, nonce)
alert if count > 1
ALERT k7 ...0041 count=2 (A, D)
ALERT k7 ...0042 count=2 (B, E)
confidentiality: A+D, B+E at risk
integrity: treat ALL k7 data as
forgeable (GCM)
severity: high
k7: encrypt = OFF, decrypt only k8: new key, new nonce space re-encrypt stored k7 records destroy k7 after migration
reserve counter blocks in durable store or: per-boot key from KMS keep alert: (key_id, nonce) count > 1 add alert: key_id encrypt count limit
- স্বাভাবিক দিন। Counter বাড়ছে, প্রতিটি (key, nonce) জোড়া অনন্য। নকশা কাগজে ঠিক আছে।
- নিরীহ ঘটনা। Maintenance-এ VM একটি পুরোনো snapshot থেকে ফিরল। Counter মেমরিতে ছিল, তাই সেটিও পুরোনো মানে ফিরে গেল।
- নীরব ব্যর্থতা। নতুন record D আর E একই nonce পেল। কোনো exception নেই, decrypt-ও সফল। এটাই nonce reuse-এর সবচেয়ে বিপজ্জনক দিক: কিছুই ভাঙা দেখায় না।
- Detection. Nonce গোপন নয়, তাই log করা নিরাপদ। সহজ নিয়ম দুটি জোড়া ধরল। চাবি নিজে কখনো log করবেন না। Detection-এর সীমা হলো এটি ঘটনার পরে জানায়, আর log সম্পূর্ণ হলে তবেই ধরে।
- Triage. A-D আর B-E জোড়ার গোপনীয়তা ঝুঁকিতে। GCM-এ পুনর্ব্যবহার থেকে ভেতরের মান H ফাঁস হতে পারে, তাই সতর্ক সিদ্ধান্ত হলো k7-এর পুরো অখণ্ডতার ভরসা তুলে নেওয়া, শুধু দুই জোড়ার নয়।
- Containment. k7-এ নতুন encryption বন্ধ, নতুন চাবি k8 চালু। সংরক্ষিত ডেটা নতুন চাবিতে আবার এনক্রিপ্ট হলো, তারপর k7 ধ্বংস। Tag আগে যাচাই করে তবেই নতুন চাবিতে নিন।
- Recovery আর শিক্ষা। Counter durable store-এ block ধরে আগেভাগে সংরক্ষণ, অথবা প্রতি boot-এ নতুন চাবি। আগের alert থাকল, যোগ হলো চাবি-প্রতি encryption গণনার সীমা। বড় ঘটনা হলে পর্ব ৬১-এর (Incident response) ধাপ মেনে ব্যবস্থা নিন, আর ডেটা নিয়ন্ত্রিত হলে আইনি দায়িত্ব মিলিয়ে দেখুন।
৮ · বাস্তব সিদ্ধান্ত — চাবির আকার, মান আর library
চাবির আকার কত
NIST SP 800-57 Part 1 Rev. 5 (২০২০) AES-128-কে ১২৮ bit নিরাপত্তা শক্তির হিসেবে ধরে, আর সেই শক্তি ২০৩১ সালের পরেও গ্রহণযোগ্য বলে তালিকাভুক্ত। NIST-এর post-quantum প্রশ্নোত্তরে বলা হয়েছে, Grover-এর algorithm AES-এ সামান্যই সুবিধা দেবে বলে মনে হয়, আর ১২৮, ১৯২, ২৫৬ তিন আকারই ব্যবহার করা চলে। তবে কিছু নিয়ন্ত্রিত পরিবেশ AES-256 চায়, যেমন যুক্তরাষ্ট্রের CNSA 2.0. তাই পরামর্শটি শর্তসাপেক্ষ:
- সাধারণ কাজে: AES-128-GCM বা AES-256-GCM, দুটোই শক্ত। দীর্ঘমেয়াদি ডেটা বা নিয়মের শর্ত থাকলে AES-256 বেছে নেওয়া যুক্তিসঙ্গত।
- Tag: ১২৮ bit রাখুন। ছোট tag-এ জালিয়াতি সহজ হয়; NIST ২০২৪ সালে জানিয়েছে, GCM-এর সংশোধনে ৯৬ bit-এর চেয়ে ছোট tag বাদ যাবে।
- চাবি: CSPRNG থেকে, password থেকে সরাসরি নয়। Password থেকে চাবি বানাতে আলাদা ধীর পদ্ধতি লাগে (পর্ব ১৩, Password নিরাপদে রাখা)।
- এক চাবির আয়ু: গণনা রাখুন, সীমার আগে ঘোরান (key rotation). Cloud-এ চাবি সামলানো দেখুন Secrets আর KMS পর্বে।
মানের অবস্থা বদলাতে পারে। ২০২৬ সালের অক্টোবরে NIST-এর পাতায় আমরা যা দেখেছি: SP 800-131A Rev. 3 এখনো খসড়া (২০২৪), আর তাতে confidentiality-র জন্য ECB অবসরে পাঠানোর প্রস্তাব আছে। SP 800-38D Rev. 1-ও (GCM) খসড়ার আগের ধাপে। চূড়ান্ত নিয়মের জন্য কাজের সময় csrc.nist.gov দেখুন, এখানকার সারাংশে ভরসা করবেন না।
নিজে লিখবেন না — library বাছাই
AES-এর সূত্র ঠিকঠাক লিখলেও বাস্তবায়ন নিরাপদ নাও হতে পারে। সময়ের পার্থক্য, cache-এর আচরণ, ত্রুটির বার্তা, সবই তথ্য ফাঁস করতে পারে। তাই নিয়ম: নিজের cipher, নিজের mode, নিজের AES, কোনোটিই উৎপাদনে নয়। বাছাইয়ে দেখুন:
উদাহরণ হিসেবে libsodium, Tink, Python-এর cryptography, ভাষার নিজস্ব standard library বা OS-এর crypto API আছে; কোনোটিই একমাত্র উত্তর নয়। নিচে Python cryptography-র AEAD ব্যবহারের ধরন দেখুন। এটি উদাহরণ, পাতায় চলে না, কারণ runner-এ ওই package নেই।
# উদাহরণ: AEAD API-র ধরন (নিজের প্রকল্পে, cryptography package লাগবে)
import os
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.exceptions import InvalidTag
key = AESGCM.generate_key(bit_length=256) # real system: load from a KMS
aead = AESGCM(key)
nonce = os.urandom(12) # never repeat under this key
ad = b"table=orders;row=1042;key=v3"
ct = aead.encrypt(nonce, b"example-message", ad) # ct ends with the 16-byte tag
try:
pt = aead.decrypt(nonce, ct, ad) # returns only if the tag matches
except InvalidTag:
pt = None # reject, log, show a generic erroropenssl enc নিয়ে সাবধান। এই command AEAD mode সমর্থন করে না। আমাদের স্থানীয় OpenSSL 3.5.5-এ -aes-256-gcm দিলে enc: AEAD ciphers not supported আসে। অন্য mode-এ এটি tag ছাড়াই ফাইল বানায়, তাই অখণ্ডতা থাকে না। ফাইল এনক্রিপ্ট করতে ভালোভাবে যাচাই করা, AEAD-ভিত্তিক টুল বা library ব্যবহার করুন।
আরও গভীরে: GCM-এ nonce reuse-এর জালিয়াতি ঝুঁকি Antoine Joux ২০০৬ সালে NIST-কে পাঠানো মন্তব্যে তুলে ধরেন; দুই tag মিলিয়ে H সম্পর্কে একটি সমীকরণ দাঁড়ায়। ব্লকের দিকের সীমাও আছে: RFC 8446 §5.5 অনুযায়ী TLS 1.3-এ AES-GCM-এর এক সংযোগে প্রায় ২২৪.৫টি পূর্ণ record-এর পর চাবি আপডেট করতে হয়, যা nonce নয়, ১২৮ bit block-এর birthday নিরাপত্তা-সীমা থেকে আসে। AES-GCM-SIV-এর মতো nonce-misuse resistant নকশা tag থেকেই nonce-সদৃশ মান বের করে, তাই ক্ষতি কমে, শূন্য হয় না।
পরীক্ষা ও ইন্টারভিউতে: এ ধরনের প্রশ্ন আসতে পারে।
১. ECB কেন অনিরাপদ? — একই plaintext block একই ciphertext block দেয়, তাই নকশা ফাঁস হয়।
২. CTR-এ nonce ফিরলে কী হয়? — Keystream ফেরে, আর C1 ⊕ C2 = P1 ⊕ P2.
৩. AEAD-এর AD কী? — যে ডেটা এনক্রিপ্ট হয় না, কিন্তু tag দিয়ে সুরক্ষিত।
৪. Encrypt-then-MAC কেন ভালো? — Decrypt-এর আগেই জাল বার্তা বাদ যায়।
৫. ৯৬ bit random nonce-এর NIST সীমা কত? — এক চাবিতে ২৩২ বার encryption.
৯ · AI-এর যুগে — সুন্দর কোড, ভুল crypto
AI encryption কোড দ্রুত লিখে দেয়, আর সেটি চলেও। সমস্যা হলো ভুল crypto-ও চলে: decrypt সফল, test সবুজ, অথচ নিরাপত্তা নেই। তাই এখানে “চলছে” কোনো প্রমাণ নয়।
| AI-এর সাধারণ ভুল | কেন বিপদ | যাচাই |
|---|---|---|
ECB বা ডিফল্ট mode-এর কোড; Java-তে শুধু "AES" লিখলে অনেক provider ECB ধরে | নকশা ফাঁস | Mode স্পষ্ট লেখা আছে কি না দেখুন |
| স্থির IV বা nonce, যেমন সব শূন্য | প্রতি বার্তায় reuse | দুবার encrypt করে দেখুন ciphertext আলাদা কি না |
সাধারণ random, যেমন Math.random() | অনুমানযোগ্য | CSPRNG ব্যবহার হচ্ছে কি না দেখুন |
| Password সরাসরি চাবি, চাবি কোডে লেখা | চাবি দুর্বল বা ফাঁস | KMS বা সঠিক KDF, repository-তে secret scan |
| Tag ত্রুটি ধরে উপেক্ষা, “error ঠিক করতে” যাচাই বাদ | AEAD-এর অর্থই শেষ | এক bit বদলে test লিখুন, ব্যর্থ হতে হবে |
| বানানো standard বা CVE নম্বর, পুরোনো পরামর্শ | ভুল ভরসা | NIST, RFC বা CVE ডেটাবেসে মূল উৎস দেখুন |
কোড লেখানোর চেয়ে পর্যালোচনা করানো ভালো কাজ দেয়। AI-কে নিচের মতো নির্দিষ্ট প্রশ্ন করুন, আর আসল চাবি কখনো দেবেন না।
AI-এর crypto কোড যাচাইয়ের চেকলিস্ট
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন, তারপর “→ উত্তর” চাপুন।
প্র ০১DES-এর ৫৬ bit চাবি কি ইচ্ছা করে ছোট রাখা হয়েছিল? এত বছর টিকে থেকেও কেন অবসরে গেল?
DES এসেছিল IBM-এর Lucifer নকশা থেকে, আর মান করার সময় যুক্তরাষ্ট্রের NSA পরামর্শ দিয়েছিল। ১৯৭৭ সালে Whitfield Diffie আর Martin Hellman প্রকাশ্যে সমালোচনা করেন: ৫৬ bit চাবি ছোট, আর যথেষ্ট টাকা থাকলে একটি বিশেষ যন্ত্র সব চাবি পরীক্ষা করতে পারবে। চাবি ছোট রাখা কতটা ইচ্ছাকৃত ছিল, তা নিয়ে আজও আলোচনা আছে; নিশ্চিত করে বলা কঠিন।
মজার দিকটি অন্যখানে। ১৯৯০-এর আশেপাশে Eli Biham আর Adi Shamir প্রকাশ্যে differential cryptanalysis দেখান, আর পরে জানা যায় DES-এর S-box এই ধরনের আক্রমণের বিরুদ্ধে শক্ত করেই বানানো হয়েছিল। IBM-এর Don Coppersmith ১৯৯৪ সালে লিখেছেন, দলটি এই কৌশল আগে থেকেই জানত। অর্থাৎ একই নকশায় গোপন শক্তি আর ছোট চাবি, দুটোই ছিল।
DES গণিতে ভেঙে পড়েনি, সময়ে হেরেছে। ১৯৯৮ সালে EFF আড়াই লাখ ডলারের কম খরচে Deep Crack বানিয়ে প্রায় ৫৬ ঘণ্টায় চাবি বের করে দেখায়। ১৯৯৯ সালে distributed.net-এর সাথে মিলে সময় নামে প্রায় ২২ ঘণ্টায়। Triple DES সাময়িক ভরসা দেয়, কিন্তু meet-in-the-middle কৌশলের কারণে তিন চাবিতেও কার্যকর শক্তি প্রায় ১১২ bit, আর ৬৪ bit block-এর সীমা থেকেই যায়। ২০১৬ সালে Sweet32 সেই সীমা বাস্তবে দেখায়।
রক্ষকের জন্য শিক্ষা হলো, কাগজে শক্ত cipher-ও সময়ের সাথে পুরোনো হয়। Legacy যন্ত্র, ব্যাংকের পুরোনো টার্মিনাল আর পুরোনো protocol-এ এমন cipher বহু বছর টিকে থাকে। তাই inventory রাখা, দুর্বল cipher বন্ধ করার পরিকল্পনা, আর algorithm বদলানোর সক্ষমতা শুরু থেকেই দরকার।
মূল উপলব্ধি: নিরাপত্তার সংখ্যা স্থির নয়। আজকের যথেষ্ট কাল অপর্যাপ্ত হতে পারে, তাই বদলানোর পথ আগে থেকেই নকশায় রাখুন।
প্র ০২গণিত ঠিক থাকলেও nonce reuse কেন বারবার ফিরে আসে? ইতিহাস থেকে কী শেখা যায়?
গল্পটি প্রায় ৮০ বছরের। দ্বিতীয় বিশ্বযুদ্ধের সময় সোভিয়েত ইউনিয়ন one-time pad ব্যবহার করত, যা ঠিকভাবে ব্যবহার করলে তাত্ত্বিকভাবে ভাঙা যায় না। কিন্তু যুদ্ধের চাপে কিছু pad-এর পাতা দুবার ছাপা হয়। যুক্তরাষ্ট্রের VENONA প্রকল্প ১৯৪৩ সাল থেকে সেই পুনরাবৃত্তি কাজে লাগিয়ে কিছু বার্তা পড়ে, যা ১৯৯৫ সালে প্রকাশ করা হয়। গণিত ভাঙেনি, উৎপাদনের চাপে নিয়ম ভেঙেছিল।
২০০১ সালে Borisov, Goldberg আর Wagner দেখান Wi-Fi-এর WEP-এ একই ভুল। WEP-এর IV মাত্র ২৪ bit, অর্থাৎ প্রায় ১.৬৮ কোটি মান। Birthday হিসাবে random IV-তে প্রায় ৪,৮০০ packet-এই পুনরাবৃত্তির সম্ভাবনা ৫০%. ব্যস্ত network-এ তা কয়েক মিনিটের ব্যাপার, আর IV নিজে packet-এ খোলাই থাকে।
২০১৬ সালে Böck ও সহকর্মীরা internet-এ খুঁজে ১৮৪টি HTTPS সার্ভার পান, যারা AES-GCM-এর nonce ফিরিয়ে আনছিল, আর random nonce ব্যবহারকারী আরও অনেক সার্ভার। ২০১৭ সালে Mathy Vanhoef আর Frank Piessens-এর KRACK গবেষণা দেখায়, WPA2 নিজে শক্ত হলেও handshake-এর একটি অবস্থায় চাবি আবার বসানো হলে nonce counter শূন্যে ফিরে যেতে পারে। সমাধান এসেছিল software patch হিসেবে, অর্থাৎ state সামলানোয়।
লক্ষ্য করুন প্রতিটি ঘটনার মিল। Nonce একটি “state”, আর state ভাঙে restart, snapshot, retransmission, একাধিক instance আর চাপের সময়। Unit test-এ এটি ধরা পড়ে না, কারণ decrypt সফল হয়। রক্ষক তাই তিনটি কাজ করেন: nonce-এর দায়িত্ব library-কে দেন, (key, nonce) পর্যবেক্ষণ করেন, আর misuse-resistant নকশা বিবেচনা করেন।
মূল উপলব্ধি: Cryptography-তে বড় ব্যর্থতা প্রায়ই algorithm-এর নয়, state আর পরিচালনার। যে শর্ত ভাঙলে কিছুই চোখে পড়ে না, তার জন্য আলাদা নজরদারি দরকার।
প্র ০৩CBC আর HMAC তো দুটোই ভালো। তাহলে TLS 1.3 কেন সেগুলোর জোড়া বাদ দিয়ে শুধু AEAD রাখল?
দুটি শক্ত অংশ জোড়া দিলেই পুরো ব্যবস্থা শক্ত হয় না। পুরোনো TLS-এ ক্রম ছিল MAC-then-encrypt: আগে plaintext-এর MAC, তারপর padding, তারপর CBC encryption. প্রাপককে আগে decrypt করতে হয়, padding দেখতে হয়, তারপর MAC যাচাই। অর্থাৎ যাচাইয়ের আগেই গোপন ডেটা নিয়ে কাজ শুরু।
২০০১ সালে Hugo Krawczyk এই ক্রমের ঝুঁকি তাত্ত্বিকভাবে দেখান, আর ২০০২ সালে Serge Vaudenay বর্ণনা করেন padding-এর ঠিক-ভুল জানা গেলেই plaintext ধীরে ধীরে ফাঁস হতে পারে। প্রতিক্রিয়া হিসেবে ত্রুটির বার্তা এক করা হলো। কিন্তু সময়ের পার্থক্য রয়ে গেল। ২০১৩ সালের Lucky Thirteen গবেষণা MAC হিসাবের অতি ক্ষুদ্র সময়-পার্থক্য থেকেই তথ্য বের করার পথ দেখায়। ২০১৪ সালে POODLE দেখায় SSL 3.0-র CBC padding একই পরিবারের সমস্যা বহন করে।
প্রতিটি patch-এর পর বাস্তবায়ন আরও জটিল হলো, আর জটিল কোডে আবার নতুন ফাঁক এলো। RFC 7366 (২০১৪) TLS-এ encrypt-then-MAC-এর একটি extension আনে, কিন্তু ততদিনে বড় সমাধান ছিল AEAD: একটি interface, দুটি কাজ, ভুল ক্রমের সুযোগ নেই। TLS 1.3 (২০১৮) তাই শুধু AEAD cipher suite রাখে। বিকল্প কমানোই সেখানে নিরাপত্তা বাড়ায়।
একই শিক্ষা TLS-এর বাইরেও খাটে, আর সেখানেও মূল কারণ একটাই: যাচাইয়ের আগে ডেটা নিয়ে কাজ করা। ২০১৮ সালের EFAIL গবেষণা দেখায়, পুরোনো OpenPGP আর S/MIME ব্যবস্থায় যাচাইহীন ciphertext-এর malleability থেকে কিছু email client-এ plaintext ফাঁস হতে পারত। AEAD-এর শর্তটি সরল: tag না মিললে কিছুই নয়।
মূল উপলব্ধি: ভালো নকশা শুধু শক্ত অংশ বেছে নেয় না, ভুলভাবে জোড়া দেওয়ার সুযোগও কমায়। ব্যবহারকারীর হাতে কম সিদ্ধান্ত মানে কম ভুল।
প্র ০৪AES-এর মতো শক্ত মান থাকতে ChaCha20 কেন জনপ্রিয় হলো? গতি ছাড়া আর কী কারণ আছে?
AES-এর গণিত নিয়ে বড় কোনো ব্যবহারিক সমস্যা জানা নেই। সমস্যা ছিল বাস্তবায়নে। Software-এ দ্রুত AES সাধারণত বড় lookup table ব্যবহার করে, আর কোন table ঘর পড়া হচ্ছে তা গোপন বাইটের ওপর নির্ভর করে। ২০০৫ সালে Daniel J. Bernstein আর আলাদাভাবে Osvik, Shamir ও Tromer দেখান, cache-এর সময়-পার্থক্য থেকে চাবির তথ্য ফাঁস হতে পারে। অর্থাৎ algorithm শক্ত, কিন্তু CPU-র আচরণ দিয়ে তথ্য বেরিয়ে যায়।
সমাধান এলো হার্ডওয়্যারে। প্রায় ২০১০ সাল থেকে সাধারণ Intel প্রসেসরে AES-NI নির্দেশ আসে, যা table ছাড়াই AES করে, আর AMD ও ARM-ও একই পথে যায়। এতে AES দ্রুত হলো, timing ঝুঁকিও কমল। কিন্তু সেই সময়ের অনেক সস্তা ফোন আর ছোট যন্ত্রে এই নির্দেশ ছিল না। সেখানে constant-time AES ধীর, আর দ্রুত AES ঝুঁকিপূর্ণ।
ChaCha20 এই ফাঁক পূরণ করে। এর কাজ শুধু যোগ, ঘোরানো আর XOR, যা সাধারণ CPU-তে দ্রুত এবং গোপন মানের ওপর নির্ভর করা table নেই। তাই বিশেষ নির্দেশ ছাড়াই দ্রুত, আর constant-time লেখাও সহজ। Mobile browser আর TLS-এ এর ব্যবহার বাড়ে, পরে RFC 7539 আর RFC 8439 আসে। WireGuard তো cipher বাছাইয়ের সুযোগই রাখেনি: নকশায় ChaCha20-Poly1305 স্থির, যাতে দর-কষাকষির ভুলের জায়গা না থাকে। দুর্বলতা পেলে পুরো protocol-এর version বদলাতে হবে, এটি তার মূল্য।
আরেকটি যুক্তি হলো বৈচিত্র্য। একটি cipher-এ কখনো বড় সমস্যা পাওয়া গেলে আরেকটি প্রস্তুত থাকা ভালো। তাই TLS 1.3 দুটিই রাখে। আবার FIPS পরিবেশে AES-ই সাধারণ পথ, তাই ক্ষেত্রভেদে সিদ্ধান্ত বদলায়।
মূল উপলব্ধি: Cipher বেছে নেওয়া শুধু গণিতের প্রশ্ন নয়; হার্ডওয়্যার, বাস্তবায়নের ঝুঁকি, আর নিয়মের শর্ত মিলিয়ে সিদ্ধান্ত।
প্র ০৫AES-256 কি AES-128-এর চেয়ে সবসময় ভালো? Quantum computer এলে AES-128-এর কী হবে?
প্রথমে brute force-এর হিসাব। ২১২৮ ≈ ৩.৪ × ১০৩৮. ধরুন সেকেন্ডে ১০২১টি চাবি পরীক্ষা করা যায়, যা একটি অতি উদার ধরে নেওয়া সংখ্যা। তবু লাগবে প্রায় ১০১০ বছর। তাই AES-128-কে brute force দিয়ে ভাঙা আজ বাস্তব দুশ্চিন্তা নয়। সবচেয়ে ভালো জানা গাণিতিক আক্রমণগুলোও পূর্ণ AES-কে brute force-এর চেয়ে সামান্যই ভালো করে, আর ব্যবহারিক নয়।
AES-256 বেশি নিরাপত্তা-সীমা দেয়, তবে সবকিছুতে নিখুঁত নয়। এর round ১৪টি, তাই কিছুটা ধীর, যদিও আধুনিক হার্ডওয়্যারে পার্থক্য সাধারণত ছোট। ২০০৯ সালে গবেষকেরা AES-256-এর key schedule-এ related-key দুর্বলতা দেখান: নির্দিষ্টভাবে সম্পর্কিত চাবি থাকলেই সেটি প্রাসঙ্গিক, আর সঠিকভাবে বানানো এলোমেলো চাবিতে সাধারণত এই পরিস্থিতি আসে না। শিক্ষাটি হলো “বড় সংখ্যা” আর “সব দিকে শক্ত” এক কথা নয়।
Quantum-এর ক্ষেত্রে পার্থক্য স্পষ্ট করা দরকার। Shor-এর algorithm RSA আর elliptic curve-এর জন্য বড় হুমকি। AES-এর জন্য প্রাসঙ্গিক Grover-এর algorithm, যা তাত্ত্বিকভাবে অনুসন্ধানকে বর্গমূলে নামায়: ২১২৮ থেকে প্রায় ২৬৪ ধাপ। তাই অনেক জায়গায় “চাবি দ্বিগুণ করুন” পরামর্শ দেখা যায়। কিন্তু Grover-কে সমান্তরালে ভাগ করা খুব কঠিন, আর সার্কিটের খরচ বিপুল। তাই NIST-এর post-quantum প্রশ্নোত্তর বলে AES-128 বহু দশক নিরাপদ থাকতে পারে, আর তিন আকারই ব্যবহারযোগ্য। অন্যদিকে যুক্তরাষ্ট্রের CNSA 2.0 নিরাপত্তা-সিস্টেমের জন্য AES-256 চায়। দুটি অবস্থানই ঝুঁকি-সহনশীলতার পার্থক্য, পরস্পরের ভুল নয়।
রক্ষকের বাস্তব সিদ্ধান্ত: নিয়মের শর্ত বা দীর্ঘমেয়াদি গোপনীয়তা থাকলে AES-256, নইলে দুটোই ঠিক। আর মনে রাখুন, বাস্তব ক্ষতি আসে চাবি চুরি, ভুল nonce আর দুর্বল password থেকে, ১২৮ বনাম ২৫৬ থেকে নয়।
মূল উপলব্ধি: চাবির আকার সবচেয়ে সহজ সিদ্ধান্ত, তাই লোকে সেখানেই সময় দেয়। ঝুঁকি বেশি থাকে চাবি সামলানো আর ব্যবহারের নিয়মে।
অনুশীলন
হিসাব, ফল অনুমান আর নকশা পর্যালোচনা। উত্তর দেখার আগে নিজে চেষ্টা করুন।
-
হিসাব: একটি সার্ভিস ৯৬-bit random nonce দিয়ে এক চাবিতে সেকেন্ডে ১ লাখ বার্তা এনক্রিপ্ট করে। (ক) কত ঘণ্টায় ২৩২ বার্তা হবে? (খ) ঠিক ২৩২-এ পুনরাবৃত্তির সম্ভাবনা প্রায় কত? (গ) ১০০ কোটি বার্তায় কত?
(ক) 232 = 4,294,967,296. ÷ 100,000 = 42,950 সেকেন্ড ≈ ১১.৯ ঘণ্টা. তাই এই সার্ভিসে প্রতিদিন একাধিকবার চাবি ঘোরাতে হবে, অথবা counter nonce বা ১৯২ bit nonce নিতে হবে।
(খ) p ≈ n² ÷ 297 = 264 ÷ 297 = 2−33 ≈ ১.১৬ × ১০−১০.
(গ) n = 109 হলে p ≈ 1018 ÷ 297 ≈ ৬.৩ × ১০−১২, অর্থাৎ প্রায় ১৬ হাজার কোটিতে একবার।
-
ফল অনুমান: খেলনা cipher
E(x) = ((x XOR 2b) * 5 + 7) mod 256. CBC mode, IV =10, P1 = P2 =41(সব hex). C1 আর C2 কত আসবে? আগে হিসাব করুন।প্রথম block:
41 ⊕ 10 = 51;51 ⊕ 2b = 7a= 122; 122 × 5 + 7 = 617; 617 mod 256 = 105 =69.দ্বিতীয় block:
41 ⊕ 69 = 28;28 ⊕ 2b = 03; 3 × 5 + 7 = 22 =16.IV বদলাতেই ফল পুরো বদলে গেছে: আগে
b5, 62, এখন69, 16. Plaintext একই থাকলেও পর্যবেক্ষক বুঝতে পারেন না, যদি IV নতুন ও অনুমান-অযোগ্য হয়। -
নকশা পর্যালোচনা: একটি কাল্পনিক অনলাইন বাজার এই নকশা দিয়েছে: গ্রাহকের ঠিকানা AES-CBC-তে এনক্রিপ্ট, IV সব row-এ একই, চাবি config ফাইলে, কোনো MAC নেই। ত্রুটিগুলো বলুন আর সংশোধন প্রস্তাব করুন।
- স্থির IV: একই শুরুর ঠিকানা একই ciphertext দেবে, ফলে একই এলাকার গ্রাহক চেনা যাবে।
- MAC নেই: DB-তে কেউ ciphertext বদলালে বা অন্য row-এ সরালে ধরা পড়বে না।
- Config-এ চাবি: ফাইল ফাঁস মানেই সব ফাঁস, ঘোরানোও কঠিন।
সংশোধন: AES-256-GCM বা ChaCha20-Poly1305; প্রতি record-এ নতুন nonce; AD-তে table, row id আর key version; চাবি KMS-এ, envelope encryption; নিয়মিত key rotation; encryption গণনার নজরদারি; ঠিকানা আদৌ দরকার কি না সেই data minimization প্রশ্নও।
-
AD বাছাই: ডেটাবেসের
users.national_idকলামে AEAD ব্যবহার করবেন। Ciphertext যেন অন্য ব্যবহারকারীর row-এ কপি করে কাজে লাগানো না যায়, সেজন্য AD-তে কী রাখবেন? প্রতিটির কারণ বলুন। Log-এ কী রাখবেন না?AD:
table + column + user_id + key_version.user_idciphertext-কে এই row-এ বাঁধে, তাই কপি করলে tag মিলবে না।tableআরcolumnঅন্য কলামে সরানো ঠেকায়।key_versionচাবি ঘোরানোর সময় সঠিক চাবি বেছে নিতে সাহায্য করে।খেয়াল করুন, AD নিজে ডেটার সাথে সংরক্ষণ করতে হয় না, যদি row থেকেই আবার বানানো যায়। Log-এ plaintext, চাবি বা পুরো পরিচয় নম্বর রাখবেন না;
key_id, ফলাফল (tag ok বা fail) আর সময় যথেষ্ট।
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমAEAD দিয়ে একটি বার্তা পাঠানো আর গ্রহণের ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- এই চাবিতে আগে ব্যবহৃত নয় এমন nonce বাছাই
- Plaintext এনক্রিপ্ট করে ciphertext তৈরি
- AD আর ciphertext-এর ওপর tag তৈরি
- Nonce, AD, ciphertext আর tag পাঠানো
- প্রাপকের দিকে tag আবার হিসাব করে তুলনা
- মিললে তবেই plaintext ব্যবহার
একটি ছবি AES-ECB-তে এনক্রিপ্ট করলে ছবির আকৃতি কেন বোঝা যায়?
- ECB চাবির একটি অংশ ciphertext-এ লিখে দেয়
- একই plaintext block একই ciphertext block দেয়
- ১২৮ bit চাবি ছবির জন্য ছোট
- ECB ডেটা compress করে
AES-256 সম্পর্কে কোন বক্তব্যটি সঠিক?
- Block ২৫৬ bit, round ১০টি
- Block ১২৮ bit, round ১০টি
- Block ১২৮ bit, round ১৪টি
- Block ২৫৬ bit, round ১৪টি
AES-CTR-এ একই চাবি আর একই nonce দিয়ে P1 আর P2 এনক্রিপ্ট হলো, ফল C1 আর C2. পর্যবেক্ষক C1 ⊕ C2 করলে কী পান?
- P1 ⊕ P2
- AES চাবি
- সম্পূর্ণ এলোমেলো বাইট, কিছুই শেখা যায় না
- Keystream
AES-GCM-এ প্রাপকের হিসাব করা tag আর পাওয়া tag মিলল না। সঠিক আচরণ কোনটি?
- Plaintext ফেরত দিয়ে একটি warning দেখানো
- যে অংশ পড়া যায় সেটুকু ব্যবহার করা
- কারণসহ বিস্তারিত ত্রুটি পাঠিয়ে অন্য nonce-এ decrypt চেষ্টা
- ডেটা প্রত্যাখ্যান করে ঘটনাটি log করা, plaintext না দেওয়া
AEAD-এ associated data (AD) বলতে কী বোঝায়?
- দ্বিতীয় একটি গোপন চাবি
- যে ডেটা খোলা থাকে কিন্তু বদলালে ধরা পড়ে
- ciphertext-এর সাথে এনক্রিপ্ট করা বাড়তি ডেটা
- Block পূরণের padding
৯৬-bit random nonce দিয়ে এক চাবিতে 232টি বার্তা এনক্রিপ্ট হলে অন্তত একটি পুনরাবৃত্তির সম্ভাবনা প্রায় কত?
- প্রায় ৫০%
- 2−96
- 2−33
- একদম শূন্য
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন, অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- Encryption গোপন রাখে, অখণ্ডতা আপনাআপনি দেয় না।
- AES-এর block ১২৮ bit; চাবি ১২৮, ১৯২ বা ২৫৬ bit, round ১০, ১২ বা ১৪.
- ECB নয়। CBC-র IV অনুমান-অযোগ্য, CTR ও GCM-এর nonce অনন্য।
- Nonce reuse নীরব: C1 ⊕ C2 = P1 ⊕ P2, আর GCM-এ জালিয়াতির ঝুঁকি; ধরতে (key, nonce) নজরে রাখুন।
- AEAD আর যাচাই করা library ডিফল্ট; random ৯৬-bit nonce-এ এক চাবিতে সীমা ২৩২.
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ০৯ · Hash আর MAC — SHA-2, HMAC আর অখণ্ডতা যাচাইপরবর্তী পর্বTag-এর পেছনের hash আর MAC ভেতর থেকে।
- সাইবার নিরাপত্তা · কোর্স হোম৮০টি পর্বপুরো কোর্সের রোডম্যাপ।
- Cryptography-র ভিত্তি (কম্পিউটার নেটওয়ার্ক)পাশের ট্র্যাকNetwork-এর চোখে symmetric, public key, hash আর signature.
- TLS আর HTTPSগভীরে যানAEAD আসলে network-এ কীভাবে চলে।
- Secrets আর KMSবাস্তবেচাবি রাখা, ঘোরানো আর envelope encryption.
- Undefined behavior আর secure codingপাশের ট্র্যাককেন নিচের স্তরের কোডে ছোট ভুল নিরাপত্তা ভাঙে।