সরাসরি পর্বে যান
পর্ব ৩০ · ৮৩-এর মধ্যে · মডিউল ৫

Finite field আর elliptic curve-এর পরিচয়

An Introduction to Finite Fields and Elliptic Curves — ℤp and GF(2⁸), the Chord-and-Tangent Group Law, Hasse's Bound, Double-and-Add, ECDLP and Toy ECDH

Taught in Bangla, this lesson introduces the mathematics behind modern cryptography with toy numbers. It proves Z_p is a field exactly when p is prime, multiplies bytes by hand in GF(2^8) with the AES modulus, derives the chord-and-tangent addition law with the point at infinity, lists every point of a small curve against the Hasse bound, and computes 13P by double-and-add. In-page Python checks GF(2^8) products, curve points, a toy ECDH and a toy ECDLP search.

এই পর্বে যা শিখবেন

  • Field-এর সংজ্ঞা, আর ℤp কেন field কিন্তু ℤ15 নয়, তার পূর্ণ প্রমাণ
  • GF(2⁸)-এ দুটি byte হাতে গুণ করা: polynomial গুণ, তারপর AES-এর modulus দিয়ে কমানো
  • Elliptic curve-এর যোগের নিয়ম (chord আর tangent), সূত্রের উৎপত্তি আর অসীমের বিন্দুর ভূমিকা
  • GF(p)-এর ওপর একটি ছোট curve-এর সব বিন্দু, Hasse-এর সীমা আর double-and-add দিয়ে 13P
  • ECDLP, খেলনা ECDH, কেন ECC-তে key ছোট, আর quantum যুগে কী বদলাচ্ছে

১ · বড় সংখ্যার বোঝা — বাজারঘরের নতুন প্রশ্ন

এই মডিউলে আমরা দেখেছি, সংখ্যাতত্ত্ব কীভাবে গোপনীয়তার কাজে লাগে। পর্ব ২৭ “Classical cipher — shift, affine আর frequency analysis”-এ পুরোনো cipher আর তাদের দুর্বলতা, পর্ব ২৮ “RSA-এর গণিত — key, encryption আর কেন কাজ করে”-এ factoring-এর কঠিনতার ওপর দাঁড়ানো RSA, আর পর্ব ২৯ “Discrete logarithm আর Diffie–Hellman key exchange”-এ mod p-তে ঘাতের উল্টো সমস্যা। তিনটির পেছনেই মডিউল ৪-এর যন্ত্রপাতি: modular inverse (পর্ব ২৩), Euler আর primitive root (পর্ব ২৪), আর factoring-এর কঠিনতা (পর্ব ২৫).

বাজারঘরের দুই কর্মী, রিনা (ঢাকা অফিস) আর সুমন (চট্টগ্রাম গুদাম), খোলা ইন্টারনেটে একটি গোপন key-তে একমত হতে চান। পর্ব ২৯-এর Diffie–Hellman এ কাজ করে, কিন্তু নিরাপদ থাকতে mod p-এর p-কে কয়েক হাজার bit লম্বা হতে হয়। মোবাইল ফোনে, ছোট সেন্সরে বা প্রতি সেকেন্ডে হাজার হাজার সংযোগ সামলানো সার্ভারে এই আকার একটি বোঝা। প্রশ্নটি তাই এমন: এমন কোনো “সংখ্যার জগৎ” কি আছে, যেখানে ঘাতের উল্টো সমস্যা আরও কঠিন, ফলে ছোট সংখ্যাতেই একই নিরাপত্তা মেলে?

উত্তর আসে দুটি ধারণা থেকে, যা এই পর্বের বিষয়। প্রথমটি finite field: সসীম একটি সেট, যেখানে সাধারণ সংখ্যার মতো যোগ, বিয়োগ, গুণ, ভাগ সব চলে। দ্বিতীয়টি elliptic curve: একটি finite field-এর ওপর আঁকা একটি বক্ররেখার বিন্দুগুলো, যাদের “যোগ” করা যায়। প্রথমটি দিয়ে আজকের প্রায় সব symmetric encryption-এর ভেতরের byte-হিসাব চলে (AES), আর দ্বিতীয়টি দিয়ে বেশিরভাগ HTTPS সংযোগের key exchange. এই পর্ব একটি পরিচয়; ring আর field-এর পূর্ণ বীজগণিত আসবে পর্ব ৭১ “Ring আর field — modular ring, polynomial আর GF(2ⁿ)”-এ, আর group-এর তত্ত্ব পর্ব ৭০ “Group — symmetry, cyclic group আর Lagrange-এর উপপাদ্য”-এ।

নিরাপত্তার কথা আগে: এই পর্বের সব cryptography গণিত বোঝার জন্য, ইচ্ছা করে ছোট সংখ্যায়। এমন “পাঠ্যবইয়ের” রূপ আসল ডেটা রক্ষায় কখনো ব্যবহার করবেন না। বাস্তব ব্যবস্থায় লাগে পরীক্ষিত library, মানসম্মত বড় parameter, সঠিক encoding আর authenticated encryption. আক্রমণ যা দেখানো হবে, তা শুধু নিজের বানানো খেলনা উদাহরণে, কেন parameter বড় হতে হয় তা বোঝাতে। বাস্তব ব্যবহার শিখুন Cybersecurity কোর্সের পর্ব ০৭, পর্ব ১০ আর পর্ব ১৪-এ।

২ · Field — যেখানে চার নিয়মই চলে

বাজারের হিসাবে আমরা যোগ, বিয়োগ, গুণ, ভাগ নির্ভাবনায় করি, কারণ মূলদ (ℚ) বা বাস্তব (ℝ) সংখ্যায় এই চার কাজ “স্বাভাবিক” নিয়ম মানে। পূর্ণসংখ্যা ℤ-এ কিন্তু ভাগ সবসময় চলে না: 1 ÷ 2 পূর্ণসংখ্যা নয়। এই “নিয়মগুলো”কে সংক্ষেপে লিখলে একটি field-এর সংজ্ঞা পাওয়া যায়।

সংজ্ঞা ২.১ (Field)

একটি সেট F, দুটি অপারেশন + আর ·, আর দুটি ভিন্ন উপাদান 0 ও 1. (F, +, ·) একটি field, যদি

  1. যোগ: associative, commutative, 0 হলো identity (a + 0 = a), আর প্রতিটি a-এর একটি −a আছে (a + (−a) = 0);
  2. গুণ: associative, commutative, 1 হলো identity, আর প্রতিটি অশূন্য a-এর একটি a−1 আছে (a · a−1 = 1);
  3. বণ্টন বিধি: a · (b + c) = a · b + a · c.

বিয়োগ মানে a − b = a + (−b), আর b ≠ 0 হলে ভাগ মানে a ÷ b = a · b−1.

ℚ, ℝ আর ℂ field; ℤ নয়, কারণ 2-এর গুণের inverse ℤ-এ নেই। কম্পিউটারের জন্য আকর্ষণীয় হলো সসীম field, কারণ সেখানে প্রতিটি উপাদান নির্দিষ্ট কয়েকটি bit-এ ধরে, কোনো rounding নেই, আর হিসাব নির্ভুল। প্রথম প্রার্থী পর্ব ২২-এর ℤn = {0, 1, …, n − 1}, যেখানে প্রতিটি যোগ আর গুণের পরে mod n নেওয়া হয়। যোগের নিয়মগুলো সবসময় খাটে; প্রশ্ন শুধু গুণের inverse নিয়ে।

উপপাদ্য ২.২ (ℤn কখন field)

n ≥ 2 হলে ℤn একটি field ⇔ n মৌলিক।

প্রমাণ: দুই দিক আলাদা করে।

  1. (⇐) n = p মৌলিক, আর a ∈ {1, …, p − 1}. p-এর একমাত্র ধনাত্মক ভাজক 1 আর p, আর p ∤ a, তাই gcd(a, p) = 1. — মৌলিকের সংজ্ঞা
  2. Bézout-এর অভেদে (পর্ব ২১) এমন পূর্ণসংখ্যা s, t আছে যাতে sa + tp = 1. mod p নিলে sa ≡ 1, তাই s mod p হলো a−1. — Bézout
  3. বাকি সব নিয়ম (associative, commutative, বণ্টন) ℤ-এ সত্য আর mod p নিলেও টিকে থাকে, কারণ congruence যোগ আর গুণ মানে (পর্ব ২২). তাই ℤp একটি field. — congruence-এর ধর্ম
  4. (⇒) n মৌলিক নয়, তাই n = rs, যেখানে 1 < r, s < n. তখন r ≢ 0, s ≢ 0, কিন্তু r · s ≡ 0 (mod n). — যৌগিকের সংজ্ঞা
  5. ধরা যাক r-এর inverse u আছে। তাহলে s ≡ (u · r) · s = u · (r · s) ≡ u · 0 = 0 (mod n), যা s ≢ 0-এর বিরোধী। তাই r-এর inverse নেই, আর ℤn field নয়। ∎ — associativity, contradiction

ধাপ ৪-এর r আর s-এর মতো উপাদানকে zero divisor বলে: দুটি অশূন্য সংখ্যার গুণফল শূন্য। ℤ15-এ 3 · 5 ≡ 0 আর 6 · 10 = 60 ≡ 0. ধাপ ৫ আসলে একটি সাধারণ সত্য দেখায়: কোনো field-এ zero divisor থাকতে পারে না (অনুশীলন ১). বাস্তবে এর মানে, ℤ15-এ “3x ≡ 1”-এর মতো সমীকরণের কোনো সমাধান নেই, আর পর্ব ২৩-এর linear congruence তখন হয় একাধিক সমাধান দেয়, নয়তো কোনোটিই না।

তাহলে কি finite field মানেই ℤp? না। নিচের উপপাদ্যটি পুরো ছবি দেয়; এর প্রমাণ এখানে বাদ, পর্ব ৭১-এর বিষয়।

উপপাদ্য ২.৩ (Finite field-এর শ্রেণিবিভাগ; বিবৃতি)

(ক) প্রতিটি finite field-এর উপাদানের সংখ্যা একটি মৌলিক সংখ্যার ঘাত pn (n ≥ 1). (খ) প্রতিটি মৌলিক p আর n ≥ 1-এর জন্য ঠিক pnটি উপাদানের একটি field আছে, আর একই আকারের যেকোনো দুটি field মূলত এক (শুধু উপাদানের নাম আলাদা)। একে লেখা হয় GF(pn) বা 𝔽pn.

GF মানে “Galois field”, ফরাসি তরুণ গণিতবিদ Évariste Galois-এর নামে, যিনি ১৮৩০ সালের দিকে এমন জগতের ধারণা দেন আর ২০ বছর বয়সে মারা যান (১৮৩২)। সব finite field যে এই তালিকাতেই পড়ে, তার পূর্ণ প্রমাণ সাধারণত E. H. Moore-এর ১৮৯৩ সালের কাজের সঙ্গে যুক্ত করা হয়। ফলে 6, 10 বা 12টি উপাদানের কোনো field নেই, কিন্তু 4, 8, 9, 256টির আছে। n = 1 হলে GF(p) = ℤp; কিন্তু GF(4) ≠ ℤ4, কারণ ℤ4-এ 2 · 2 ≡ 0. GF(4) বানাতে নতুন একটি কৌশল লাগে, যা পরের অংশে।

৩ · GF(2ⁿ) — bit-এর polynomial আর AES-এর byte

কম্পিউটারের স্বাভাবিক একক byte, অর্থাৎ 8টি bit, 256টি মান। 256 = 28, তাই উপপাদ্য ২.৩ অনুযায়ী 256টি উপাদানের একটি field আছে। কিন্তু ℤ256 সেই field নয় (2 · 128 ≡ 0). কৌশলটি হলো byte-কে সংখ্যা না ভেবে polynomial ভাবা।

ধাপ ১: GF(2)-এর ওপর polynomial

GF(2) = ℤ2 = {0, 1}, যেখানে 1 + 1 = 0. একটি byte b7b6…b0-কে পড়া হয় b7x7 + ⋯ + b1x + b0 হিসেবে। যেমন hex {57} = 0101 0111 = x6 + x4 + x2 + x + 1. দুটি polynomial যোগ করতে একই ঘাতের সহগ mod 2-এ যোগ হয়, অর্থাৎ bit-ধরে XOR: {57} + {83} = 0101 0111 ⊕ 1000 0011 = {d4}. কোনো “হাতে রাখা” (carry) নেই। লক্ষ করুন, এখানে a + a = 0, তাই বিয়োগ আর যোগ একই কাজ।

ধাপ ২: গুণ, তারপর একটি irreducible polynomial দিয়ে ভাগশেষ

দুটি 7 ঘাতের polynomial গুণ করলে 14 পর্যন্ত ঘাত আসতে পারে, যা আর এক byte-এ ধরে না। সমাধান পূর্ণসংখ্যার mod p-এর মতো: একটি নির্দিষ্ট 8 ঘাতের polynomial m(x) দিয়ে ভাগ করে ভাগশেষ রাখা। কিন্তু m(x) যেকোনো হলে চলবে না। ℤn-এ n-কে মৌলিক হতে হয়েছিল; এখানে m(x)-কে হতে হবে irreducible: GF(2)-এর ওপর তাকে দুটি ছোট ঘাতের (ঘাত ≥ 1) polynomial-এর গুণফল হিসেবে লেখা যায় না। কারণটি হুবহু উপপাদ্য ২.২-এর: m = f · g হলে f আর g zero divisor হয়ে যায়, আর m irreducible হলে Bézout-এর polynomial রূপ (polynomial-এর Euclid) প্রতিটি অশূন্য উপাদানের inverse দেয়।

সবচেয়ে ছোট উদাহরণ GF(4): m(x) = x2 + x + 1 (GF(2)-এ এর root নেই, আর ঘাত 2 বলে root না থাকলেই irreducible). উপাদান 0, 1, x, x + 1, আর x · x = x2 ≡ x + 1, x · (x + 1) = x2 + x ≡ 1. অর্থাৎ x আর x + 1 পরস্পরের inverse: চারটি উপাদানের একটি সত্যিকারের field, যা ℤ4 থেকে আলাদা।

সংজ্ঞা ৩.১ (AES-এর field)

AES-এ GF(28)-এর modulus

m(x) = x8 + x4 + x3 + x + 1 (hex {11B})

দুটি byte a, b-এর গুণফল = (a(x) · b(x)) mod m(x), সহগ mod 2.

AES (Advanced Encryption Standard) হলো বেলজিয়ামের Joan Daemen আর Vincent Rijmen-এর Rijndael নকশা, যা মার্কিন NIST ২০০১ সালে FIPS 197 হিসেবে প্রকাশ করে। মানপত্রটিতে উদাহরণ হিসেবে {57} · {83} = {c1} দেওয়া আছে। নিচের stepper সেই গুণটি হাতে করে, যেমন পরীক্ষার খাতায় করবেন।

1{57} = x⁶+x⁴+x²+x+12{83} = x⁷+x+1357·x⁷ ⊕ 57·x ⊕ 57·14= x¹³+x¹¹+x⁹+x⁸+x⁶5  +x⁵+x⁴+x³+16⊕ x⁵·m(x)7⊕ x³·m(x) → x⁷+x⁶+1
চলক
এই ধাপে
সর্বোচ্চ ঘাত
চলতি মান
  1. Polynomial-এ লেখা। {57} = 0101 0111 = x6 + x4 + x2 + x + 1, আর {83} = 1000 0011 = x7 + x + 1.
  2. আংশিক গুণফল। {83}-এর প্রতিটি পদ দিয়ে {57} গুণ: x7 দিয়ে x13 + x11 + x9 + x8 + x7, x দিয়ে x7 + x5 + x3 + x2 + x, আর 1 দিয়ে {57} নিজে।
  3. XOR-এ যোগ। তিন সারিতে x7, x2 আর x দুবার করে আসে, তাই বাদ (1 + 1 = 0). ফল x13 + x11 + x9 + x8 + x6 + x5 + x4 + x3 + 1, ঘাত 13.
  4. প্রথম কমানো। x13 সরাতে x5 · m(x) = x13 + x9 + x8 + x6 + x5 XOR করুন। বাকি থাকে x11 + x4 + x3 + 1.
  5. দ্বিতীয় কমানো। x3 · m(x) = x11 + x7 + x6 + x4 + x3 XOR করলে থাকে x7 + x6 + 1 = 1100 0001 = {c1}. ঘাত 7, তাই এটিই উত্তর, FIPS 197-এর উদাহরণের সঙ্গে মেলে।

এখানে “ভাগশেষ নেওয়া” মানে বারবার m(x)-এর উপযুক্ত x-ঘাতের গুণিতক XOR করে সর্বোচ্চ পদটি মুছে ফেলা, ঠিক পর্ব ২৬-এর CRC-এর লম্বা ভাগের মতো। কম্পিউটারে আরও সহজ একটি পথ আছে: b-এর bit ধরে ধরে a-কে বারবার x দিয়ে গুণ করা (এক bit বাঁয়ে সরানো), আর ঘাত 8 হলেই সঙ্গে সঙ্গে {11B} XOR করা। নিচের ব্লক সেভাবে গুণ করে, তারপর তিনটি দাবি পরীক্ষা করে: প্রতিটি অশূন্য byte-এর ঠিক একটি inverse আছে, AES-এর m(x)-এর কোনো ছোট উৎপাদক নেই, আর irreducible নয় এমন x8 + 1 নিলে zero divisor দেখা দেয়। প্রথমবার চালালে ব্রাউজারে Python (Pyodide) নামতে কয়েক সেকেন্ড লাগে।

AES_MOD = 0x11B                       # x^8 + x^4 + x^3 + x + 1

def gf_mul(a, b, mod=AES_MOD):        # multiply two bytes in GF(2^8)
    r = 0
    while b:
        if b & 1:
            r ^= a                    # add (XOR) this partial product
        a <<= 1; b >>= 1
        if a & 0x100:
            a ^= mod                  # reduce as soon as degree 8 appears
    return r

print("57 * 83 =", hex(gf_mul(0x57, 0x83)), "  57 * 13 =", hex(gf_mul(0x57, 0x13)))
print("57 + 83 =", hex(0x57 ^ 0x83), "(addition is XOR)")

inv = {a: [b for b in range(1, 256) if gf_mul(a, b) == 1] for a in range(1, 256)}
print("every nonzero byte has exactly one inverse:",
      all(len(v) == 1 for v in inv.values()), "  inverse of 53:", hex(inv[0x53][0]))

def poly_mod(f, g):                   # remainder of f / g, coefficients mod 2
    while f.bit_length() >= g.bit_length():
        f ^= g << (f.bit_length() - g.bit_length())
    return f
print("AES modulus has a factor of degree 1..4:",
      any(poly_mod(AES_MOD, g) == 0 for g in range(2, 32)))

bad = 0x101                           # x^8 + 1 = (x + 1)^8 is reducible
zd = [(a, b) for a in range(1, 256) for b in range(a, 256) if gf_mul(a, b, bad) == 0]
print("mod x^8 + 1: zero-divisor pairs", len(zd), " e.g.", [hex(t) for t in zd[0]])

def is_field(n):                      # Z_n: does every nonzero a have an inverse?
    return all(any(a * b % n == 1 for b in range(1, n)) for a in range(1, n))
print("n < 30 where Z_n is a field:", [n for n in range(2, 30) if is_field(n)])

আসল আউটপুট (ব্রাউজারের Python):

57 * 83 = 0xc1   57 * 13 = 0xfe
57 + 83 = 0xd4 (addition is XOR)
every nonzero byte has exactly one inverse: True   inverse of 53: 0xca
AES modulus has a factor of degree 1..4: False
mod x^8 + 1: zero-divisor pairs 392  e.g. ['0x3', '0xff']
n < 30 where Z_n is a field: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]

প্রথম লাইন stepper-এর {c1} আর FIPS 197-এর দ্বিতীয় উদাহরণ {57} · {13} = {fe} মেলায়। ২৫৫টি অশূন্য byte-এর প্রতিটির ঠিক একটি inverse আছে, যেমন {53}−1 = {ca}: এটিই field হওয়ার শর্ত। 8 ঘাতের polynomial-এর কোনো উৎপাদক থাকলে অন্তত একটির ঘাত 4 বা তার কম হতো, তাই ঘাত 1 থেকে 4-এর সব ৩০টি polynomial (g = 2 থেকে 31) দিয়ে ভাগ করে দেখাই যথেষ্ট; কোনোটিই মেলেনি, তাই m(x) irreducible. উল্টো দিকে x8 + 1 = (x + 1)8 (mod 2-এ) নিলে ৩৯২টি zero divisor-জোড়া, যেমন (x + 1)(x7 + ⋯ + 1) = x8 + 1 ≡ 0. শেষ লাইন উপপাদ্য ২.২: 30-এর নিচে ঠিক মৌলিক n-গুলোতেই ℤn field.

AES-এর S-box, অর্থাৎ যে টেবিল প্রতিটি byte বদলে দেয়, এই field-এর inverse (x ↦ x−1, আর 0 ↦ 0) নিয়ে তার ওপর একটি নির্দিষ্ট affine রূপান্তর চালিয়ে বানানো। inverse ফাংশনটি অত্যন্ত “অ-linear”, আর এই গুণই AES-কে নির্দিষ্ট কিছু গাণিতিক আক্রমণ থেকে রক্ষা করে বলে নকশাকারীরা যুক্তি দেন। AES কীভাবে ব্যবহার করতে হয় (mode, nonce, authenticated encryption), তা Cybersecurity কোর্সের পর্ব ০৮-এর বিষয়।

৪ · বাস্তব সংখ্যায় elliptic curve — chord আর tangent

নাম শুনে উপবৃত্ত (ellipse) মনে হলেও elliptic curve উপবৃত্ত নয়; নামটি এসেছে উপবৃত্তের পরিধি মাপার একটি পুরোনো integral থেকে। আমাদের জন্য একটি elliptic curve হলো এমন সমীকরণের সব বিন্দু:

y2 = x3 + ax + b, যেখানে 4a3 + 27b2 ≠ 0

একে Weierstrass রূপ বলে। দ্বিতীয় শর্তটি বলে, ডান পাশের ঘন polynomial-এর কোনো পুনরাবৃত্ত root নেই, ফলে curve-এ কোনো সূচালো কোণ বা নিজেকে কাটা বিন্দু নেই, আর প্রতিটি বিন্দুতে একটি নির্দিষ্ট স্পর্শক (tangent) আছে। নিচের ছবিতে a = −1, b = 1: 4(−1)3 + 27 = 23 ≠ 0. y-এর জায়গায় −y বসালে সমীকরণ বদলায় না, তাই curve x-অক্ষের সাপেক্ষে প্রতিসম।

Chord-এর নিয়ম: y² = x³ − x + 1-এ P + Q

P = (−1, 1) আর Q = (0, 1)-এর মধ্য দিয়ে রেখা y = 1 টানলে curve-কে তৃতীয়বার কাটে (1, 1)-এ। x-অক্ষে প্রতিফলন করলে P + Q = (1, −1).

Chord rule on y^2 = x^3 - x + 1: the line through P and Q meets the curve again at (1, 1); its reflection (1, -1) is P + Q x y 0 P Q তৃতীয় ছেদ (1, 1) P + Q = (1, −1) y = 1 O: খাড়া রেখার “শেষে”, অসীমে

যোগের নিয়ম

দুটি বিন্দু P আর Q দেওয়া থাকলে তাদের মধ্য দিয়ে একটি সরলরেখা (chord) টানুন। ঘন সমীকরণের রেখা curve-কে সাধারণত ঠিক তিনটি বিন্দুতে কাটে; তৃতীয়টিকে x-অক্ষে প্রতিফলন করলে যা পাওয়া যায়, তাকেই বলা হয় P + Q. P = Q হলে chord-এর বদলে P-বিন্দুতে স্পর্শক (tangent) টানা হয়, তাই একে “chord-and-tangent” নিয়ম বলে। আর P ও Q একই খাড়া রেখায় হলে (x সমান, y বিপরীত) রেখাটি আর কোথাও curve কাটে না। তখন তৃতীয় বিন্দু হিসেবে একটি বিশেষ বিন্দু যোগ করা হয়: অসীমের বিন্দু O, যাকে কল্পনা করা যায় সব খাড়া রেখার “শেষে”, ওপরে-নিচে অসীমে। O-ই এই যোগের শূন্য: P + O = P, আর (x, y)-এর বিপরীত −(x, y) = (x, −y).

উপপাদ্য ৪.১ (যোগের সূত্র)

P = (x1, y1), Q = (x2, y2) curve-এ, আর Q ≠ −P. ঢাল

λ = (y2 − y1) / (x2 − x1) যদি P ≠ Q, λ = (3x12 + a) / (2y1) যদি P = Q

হলে P + Q = (x3, y3), যেখানে x3 = λ2 − x1 − x2 আর y3 = λ(x1 − x3) − y1.

প্রমাণ (P ≠ Q, x1 ≠ x2; স্পর্শকের ক্ষেত্র একইভাবে, শুধু λ আসে implicit derivative 2y·y′ = 3x2 + a থেকে):

  1. P আর Q-এর মধ্য দিয়ে রেখা y = λ(x − x1) + y1, যেখানে λ দুই বিন্দুর ঢাল। — সরলরেখার সমীকরণ
  2. এটি curve-এ বসালে (λ(x − x1) + y1)2 = x3 + ax + b, অর্থাৎ x3 − λ2x2 + (নিচের ঘাতের পদ) = 0. ছেদবিন্দুর x-গুলো এই ঘন সমীকরণের root. — বদলে বসানো
  3. x1 আর x2 দুটি root, তাই তৃতীয় root x3ও আছে, আর monic ঘন সমীকরণে root-এর যোগফল = −(x2-এর সহগ) = λ2. তাই x1 + x2 + x3 = λ2. — root আর সহগের সম্পর্ক (Vieta)
  4. তৃতীয় ছেদবিন্দু রেখার ওপর: (x3, λ(x3 − x1) + y1). এর প্রতিফলনের y = −λ(x3 − x1) − y1 = λ(x1 − x3) − y1. ∎ — প্রতিফলন মানে y ↦ −y

ছবির উদাহরণে λ = 0, তাই x3 = 0 − (−1) − 0 = 1 আর y3 = 0 − 1 = −1: ঠিক (1, −1). লক্ষ করুন সূত্রে শুধু যোগ, বিয়োগ, গুণ আর ভাগ আছে, কোনো বর্গমূল বা দশমিক নেই। তাই একই সূত্র যেকোনো field-এ চলে, যেখানে 2 ≠ 0 আর 3 ≠ 0 (অর্থাৎ field-এর উপাদান-সংখ্যা 2 বা 3-এর ঘাত নয়; GF(2n)-এ curve-এর সমীকরণ একটু আলাদা রূপ নেয়)। এটিই পরের অংশের চাবি।

উপপাদ্য ৪.২ (Group law; বিবৃতি)

Curve-এর বিন্দুগুলো আর O মিলে এই যোগে একটি abelian group: যোগ বন্ধ (closure), O identity, প্রতিটি বিন্দুর বিপরীত আছে, P + Q = Q + P, আর (P + Q) + R = P + (Q + R).

প্রথম চারটি সূত্র থেকে সরাসরি আসে: Q আর P অদলবদল করলে λ আর x3 বদলায় না। কঠিন অংশ associativity; সূত্র দিয়ে সরাসরি যাচাই করা যায়, কিন্তু হাতে কয়েক পাতার বীজগণিত লাগে, আর সুন্দর প্রমাণগুলো projective geometry বা algebraic geometry ব্যবহার করে। তাই এখানে প্রমাণ বাদ; বদলে পরের অংশে কম্পিউটারে হাজার হাজার ক্ষেত্রে পরীক্ষা করা হবে।

৫ · GF(p)-এর ওপর curve — বিন্দুর তালিকা আর group

এবার x আর y বাস্তব সংখ্যা নয়, ℤp-এর উপাদান, আর সব হিসাব mod p. “ভাগ” মানে modular inverse দিয়ে গুণ, যা উপপাদ্য ২.২ নিশ্চিত করে। ছবিটি আর বক্ররেখা থাকে না, একটি ছড়ানো বিন্দুর ঝাঁক হয়ে যায়, কিন্তু উপপাদ্য ৪.১-এর সূত্র হুবহু একই, আর group law-ও টিকে থাকে। আমাদের খেলনা curve:

E: y2 ≡ x3 + 2x + 2 (mod 17)

4 · 8 + 27 · 4 = 140 ≡ 4 ≢ 0 (mod 17), তাই curve মসৃণ। x = 0 থেকে 16 প্রতিটির জন্য x3 + 2x + 2 mod 17 একটি বর্গ কি না দেখে বিন্দুগুলো গোনা যায়: মোট 18টি বিন্দু, আর O মিলিয়ে N = 19. G = (5, 1) নিয়ে বারবার যোগ করলে পাওয়া যায় 2G = (6, 3), 3G = (10, 6), 4G = (3, 1), …, 18G = (5, 16) = −G, আর 19G = O. 19 মৌলিক, তাই G থেকে সব বিন্দু আসে: group-টি cyclic, আর G একটি generator (পর্ব ২৪-এর primitive root-এর মতো)। নিচের stepper এই curve-এ 3G আর 4G যোগ করে।

1A = (10, 6), B = (3, 1)2λ = (1 − 6)/(3 − 10)3  = 12 · 10⁻¹ = 12 · 12 ≡ 84x₃ = 8² − 10 − 3 = 51 ≡ 05y₃ = 8(10 − 0) − 6 = 74 ≡ 66A + B = (0, 6) = 7G
চলক
λ
x₃
y₃
যাচাই
  1. বিন্দু যাচাই। A = (10, 6): 62 = 36 ≡ 2, আর 103 + 20 + 2 = 1022 ≡ 2 ✓. B = (3, 1): 1 আর 27 + 6 + 2 = 35 ≡ 1 ✓. x1 ≠ x2, তাই chord-এর সূত্র।
  2. ঢাল। λ = (1 − 6)/(3 − 10) = (−5)/(−7). mod 17-এ −5 ≡ 12 আর −7 ≡ 10. 10−1 ≡ 12 (কারণ 10 · 12 = 120 = 7 · 17 + 1). তাই λ ≡ 12 · 12 = 144 ≡ 8.
  3. x₃। x3 = λ2 − x1 − x2 = 64 − 10 − 3 = 51 = 3 · 17 ≡ 0.
  4. y₃। y3 = λ(x1 − x3) − y1 = 8 · 10 − 6 = 74 ≡ 74 − 68 = 6.
  5. ফল যাচাই। (0, 6): 62 = 36 ≡ 2, আর 0 + 0 + 2 = 2 ✓. G-এর গুণিতকের তালিকায় 7G = (0, 6), তাই 3G + 4G = 7G, যেমন হওয়ার কথা।

বিন্দুর সংখ্যা N কত বড় হতে পারে? প্রতিটি x-এর জন্য y বড়জোর দুটি, তাই N ≤ 2p + 1. মোটামুটি অর্ধেক অশূন্য ভাগশেষ বর্গ (পর্ব ২৪-এর Euler-এর criterion), তাই গড়ে প্রতিটি x একটি বিন্দু দেয় আর N ≈ p + 1 আশা করা যায়। আশ্চর্যের কথা, বিচ্যুতিও খুব ছোট।

উপপাদ্য ৫.১ (Hasse-এর সীমা; বিবৃতি)

p মৌলিক আর E একটি মসৃণ curve GF(p)-এর ওপর। O-সহ বিন্দুর সংখ্যা N হলে

|N − (p + 1)| ≤ 2√p

Helmut Hasse ১৯৩০-এর দশকে এটি প্রমাণ করেন; প্রমাণ এই কোর্সের বাইরে। আমাদের curve-এ p + 1 = 18, 2√17 ≈ 8.25, আর N = 19 সীমার ভেতরে। বাস্তবে N হুবহু জানা জরুরি, কারণ নিরাপত্তার জন্য N-এর একটি বড় মৌলিক উৎপাদক থাকতে হয় (পর্ব ২৯-এর Pohlig–Hellman-এর যুক্তি)। বড় p-এ N গোনার জন্য Schoof-এর ১৯৮৫ সালের polynomial-সময়ের algorithm আর তার উন্নত রূপ ব্যবহৃত হয়।

এখন group law-কে কম্পিউটারে পরীক্ষা করা যাক। নিচের ব্লক আরেকটি curve, y2 = x3 + 2x + 3 (mod 97)-এর সব বিন্দু তালিকা করে, Hasse-এর সীমা মেলায়, আর সব জোড়ায় closure ও commutativity, প্রতিটি বিন্দুর বিপরীত, আর ৩,০০০টি এলোমেলো তিন-বিন্দুতে associativity পরীক্ষা করে। pow(d, -1, p) হলো Python-এর modular inverse.

import random
random.seed(30)
p, a, b = 97, 2, 3                    # y^2 = x^3 + 2x + 3 over GF(97)
O = None                              # the point at infinity

def add(P, Q):
    if P is O: return Q
    if Q is O: return P
    (x1, y1), (x2, y2) = P, Q
    if x1 == x2 and (y1 + y2) % p == 0:
        return O                      # P + (-P) = O: a vertical line
    if P == Q:
        lam = (3 * x1 * x1 + a) * pow(2 * y1, -1, p) % p   # tangent slope
    else:
        lam = (y2 - y1) * pow(x2 - x1, -1, p) % p          # chord slope
    x3 = (lam * lam - x1 - x2) % p
    return (x3, (lam * (x1 - x3) - y1) % p)

print("4a^3 + 27b^2 mod p =", (4 * a**3 + 27 * b**2) % p, "(nonzero: a smooth curve)")
pts = [(x, y) for x in range(p) for y in range(p) if (y * y - x**3 - a * x - b) % p == 0]
E = pts + [O]
print("points:", len(pts), "+ O =", len(E), "  first five:", pts[:5])
print("Hasse: |N - (p + 1)| =", abs(len(E) - (p + 1)),
      "<= 2*sqrt(p) =", round(2 * p ** 0.5, 2))
on = set(E)
print("closure, all", len(E) ** 2, "pairs:", all(add(P, Q) in on for P in E for Q in E))
print("commutative:", all(add(P, Q) == add(Q, P) for P in E for Q in E))
print("every point has an inverse:", all(add(P, (P[0], -P[1] % p)) is O for P in pts))
trip = [random.sample(E, 3) for _ in range(3000)]
print("associative on 3000 random triples:",
      all(add(add(P, Q), R) == add(P, add(Q, R)) for P, Q, R in trip))

আসল আউটপুট (ব্রাউজারের Python):

4a^3 + 27b^2 mod p = 81 (nonzero: a smooth curve)
points: 99 + O = 100   first five: [(0, 10), (0, 87), (1, 43), (1, 54), (3, 6)]
Hasse: |N - (p + 1)| = 2 <= 2*sqrt(p) = 19.7
closure, all 10000 pairs: True
commutative: True
every point has an inverse: True
associative on 3000 random triples: True

৯৯টি সাধারণ বিন্দু আর O, মোট N = 100, যা p + 1 = 98 থেকে মাত্র 2 দূরে, সীমা 19.7-এর অনেক ভেতরে। লক্ষ করুন বিন্দুগুলো জোড়ায় আসে: (0, 10) আর (0, 87), কারণ 87 ≡ −10; এরা পরস্পরের বিপরীত। ১০,০০০টি জোড়ার প্রতিটির যোগফল আবার curve-এ (closure), আর ৩,০০০টি এলোমেলো তিন-বিন্দুর কোথাও associativity ভাঙেনি। এটি প্রমাণ নয়, কিন্তু উপপাদ্য ৪.২-এর একটি জোরালো পরীক্ষা; বিশেষ করে সূত্রে একটি চিহ্নের ভুল থাকলেই এই পরীক্ষা সঙ্গে সঙ্গে False দেখাত। এই group-এর N = 100 মৌলিক নয়, তাই বাস্তব কাজে এমন curve বাছা হয় না।

৬ · Scalar multiplication — double-and-add

পূর্ণসংখ্যা k ≥ 1 আর বিন্দু P-এর জন্য kP = P + P + ⋯ + P (k বার), আর 0P = O. একে scalar multiplication বলে। mod p-তে gk-এর মতো এখানেও k কয়েকশো bit লম্বা হতে পারে, তাই k − 1 বার যোগ অসম্ভব। পর্ব ২২-এর বারবার বর্গ করার কৌশলটি হুবহু এখানে খাটে, শুধু “বর্গ” হয় “দ্বিগুণ” আর “গুণ” হয় “যোগ”।

Algorithm ৬.১ (Double-and-add, বাঁ থেকে ডানে)

k-এর binary রূপ 1 bt−1 … b1 b0. R ← P. তারপর i = t − 1 থেকে 0 পর্যন্ত: R ← 2R; যদি bi = 1, তবে R ← R + P. শেষে R = kP.

সঠিকতার প্রমাণ (loop invariant, পর্ব ১৩-এর পদ্ধতিতে):

  1. k-এর প্রথম j-টি bit দিয়ে তৈরি সংখ্যাকে kj বলি (k1 = 1, আর kt+1 = k). দাবি: প্রতিটি পুনরাবৃত্তির শুরুতে R = kjP. শুরুতে j = 1, R = P = 1 · P ✓. — ভিত্তি
  2. পরের bit b যোগ করলে kj+1 = 2kj + b, কারণ binary-তে একটি অঙ্ক যোগ মানে আগের মান দ্বিগুণ করে নতুন অঙ্ক যোগ। — binary রূপ
  3. loop R-কে করে 2(kjP) + bP = (2kj + b)P = kj+1P. এখানে group-এর associativity লাগে, যাতে kjP-কে দুবার যোগ করা আর 2kj বার P যোগ করা একই হয়। — উপপাদ্য ৪.২
  4. শেষ bit-এর পরে R = kt+1P = kP. ধাপের সংখ্যা: t = ⌊log2 k⌋টি দ্বিগুণ, আর (k-এর binary-তে 1-এর সংখ্যা − 1)টি যোগ, মোট ≤ 2 log2 k. ∎ — গণনা

নিচের stepper আমাদের mod 17 curve-এ G = (5, 1)-এর জন্য 13G বের করে। 13 = 11012, তাই ধাপগুলো: 1 → 3 → 6 → 13 (bit ধরে kj: 1, 11, 110, 1101).

113 = 1101₂ ; R = G = (5, 1)2bit 1: R = 2R = (6, 3)3       R = R + G = (10, 6)4bit 0: R = 2R = (16, 13)5bit 1: R = 2R = (0, 11)6       R = R + G = (16, 4)
চলক
R
শেষ λ
মোট অপারেশন
  1. শুরু। 13 = 8 + 4 + 1 = 11012. প্রথম bit 1, তাই R = G = (5, 1). বাকি bit: 1, 0, 1.
  2. bit 1: দ্বিগুণ, তারপর যোগ। 2G-এ λ = (3 · 25 + 2)/(2 · 1) = 77 · 2−1 ≡ 9 · 9 = 81 ≡ 13, তাই 2G = (6, 3). তারপর (6, 3) + (5, 1)-এ λ = (1 − 3)/(5 − 6) = 2, ফল 3G = (10, 6).
  3. bit 0: শুধু দ্বিগুণ। λ = (3 · 100 + 2)/(2 · 6) = 302/12 ≡ 13 · 12−1 = 13 · 10 = 130 ≡ 11. x = 121 − 20 = 101 ≡ 16, y = 11(10 − 16) − 6 = −72 ≡ 13. R = 6G = (16, 13).
  4. bit 1: দ্বিগুণ। λ = (3 · 256 + 2)/(2 · 13) = 770/26 ≡ 5 · 9−1 = 5 · 2 = 10. x = 100 − 32 = 68 ≡ 0, y = 10 · 16 − 13 = 147 ≡ 11. R = 12G = (0, 11).
  5. …আর যোগ। (0, 11) + (5, 1)-এ λ = (1 − 11)/(5 − 0) ≡ 7 · 5−1 = 7 · 7 = 49 ≡ 15. x = 225 − 5 = 220 ≡ 16, y = 15(0 − 16) − 11 = −251 ≡ 4. তাই 13G = (16, 4): ৩টি দ্বিগুণ আর ২টি যোগ।

৭ · ECDLP আর ECDH — খোলা পথে একটি গোপন বিন্দু

Double-and-add দেখায়, k আর P জানা থাকলে Q = kP বের করা দ্রুত। উল্টোটা?

সংজ্ঞা ৭.১ (ECDLP)

Elliptic curve discrete logarithm problem: একটি curve, n order-এর একটি বিন্দু G আর একটি বিন্দু Q = kG দেওয়া থাকলে k (mod n) বের করা।

এটি পর্ব ২৯-এর discrete logarithm-এরই রূপ, শুধু “ঘাত” এখানে “গুণিতক”। সহজতম আক্রমণ G, 2G, 3G, … একে একে দেখা, যাতে গড়ে n/2 ধাপ লাগে। পর্ব ২৯-এর baby-step giant-step বা Pollard-এর rho পদ্ধতি এটিকে প্রায় √n ধাপে নামায়। ভালোভাবে বাছা curve-এ এর চেয়ে মূলগতভাবে দ্রুত কোনো সাধারণ পদ্ধতি জানা নেই; কিন্তু এটি একটি বিশ্বাস, প্রমাণ নয়। ECDLP কঠিন, এমন কোনো গাণিতিক প্রমাণ নেই।

ECDH: রিনা আর সুমনের key

পর্ব ২৯-এর Diffie–Hellman-এর হুবহু অনুবাদ হলো ECDH:

  1. সবাই জানে: curve, মৌলিক p, একটি বিন্দু G আর তার মৌলিক order n.
  2. রিনা গোপনে a ∈ {2, …, n − 1} বাছেন, আর খোলা পথে পাঠান A = aG. সুমন গোপনে b বাছেন, পাঠান B = bG.
  3. রিনা হিসাব করেন aB, সুমন হিসাব করেন bA.
উপপাদ্য ৭.২ (ECDH-এর সঠিকতা)

aB = bA = (ab)G.

প্রমাণ: (১) aB = a(bG). (২) a(bG) মানে bG-কে a বার যোগ, অর্থাৎ G-কে ab বার যোগ (associativity, উপপাদ্য ৪.২), তাই a(bG) = (ab)G. (৩) একইভাবে bA = b(aG) = (ba)G, আর ab = ba. ∎

খোলা পথে শোনা একজন দেখেন G, A আর B. তাঁকে (ab)G বের করতে হবে, যা ECDLP সমাধান করলে সম্ভব; এর চেয়ে সহজ পথ জানা নেই বলে বিশ্বাস করা হয়। তবে পর্ব ২৯-এর সতর্কবাণী এখানেও খাটে: মাঝখানে বসে কেউ নিজের বিন্দু পাঠালে (man-in-the-middle) রিনা টেরই পাবেন না, যদি না পাঠানো বিন্দুগুলো signature বা certificate দিয়ে প্রমাণিত হয়। গণিত শুধু শোনা ঠেকায়; পরিচয় যাচাই আলাদা কাজ। বাস্তবে ভাগ করা বিন্দুটিও সরাসরি key হিসেবে ব্যবহৃত হয় না, একটি key derivation function দিয়ে key বানানো হয়।

নিচের ব্লক আগে stepper-এর 13G আর 19G = O মেলায়, তারপর একটি খেলনা curve (p = 10007, N = 10091, একটি মৌলিক) নিয়ে রিনা আর সুমনের ECDH চালায়।

import random
random.seed(2026)
O = None
def add(P, Q):                        # group law; reads the curve p, a below
    if P is O: return Q
    if Q is O: return P
    (x1, y1), (x2, y2) = P, Q
    if x1 == x2 and (y1 + y2) % p == 0: return O
    if P == Q: lam = (3 * x1 * x1 + a) * pow(2 * y1, -1, p) % p
    else:      lam = (y2 - y1) * pow(x2 - x1, -1, p) % p
    x3 = (lam * lam - x1 - x2) % p
    return (x3, (lam * (x1 - x3) - y1) % p)

def mul(k, P):                        # double-and-add, bits of k from the left
    R, ops = P, 0                     # the leading bit 1 gives R = P
    for bit in bin(k)[3:]:
        R = add(R, R); ops += 1       # double
        if bit == "1":
            R = add(R, P); ops += 1   # add
    return R, ops
p, a = 17, 2                          # tiny curve y^2 = x^3 + 2x + 2 (mod 17)
print("13G on the mod-17 curve:", mul(13, (5, 1)), "  19G:", mul(19, (5, 1))[0])

p, a, b, N = 10007, 2, 30, 10091      # toy curve, N points (a prime)
x = 0
while True:                           # first point: square root, p % 4 == 3
    f = (x**3 + a * x + b) % p; y = pow(f, (p + 1) // 4, p)
    if y * y % p == f: G = (x, y); break
    x += 1
print("G =", G, "  N*G is O:", mul(N, G)[0] is O)
ka, kb = random.randrange(2, N), random.randrange(2, N)   # two secret keys
A, B = mul(ka, G)[0], mul(kb, G)[0]   # public values, sent in the open
print("public A =", A, "  public B =", B)
print("same shared point:", mul(ka, B)[0] == mul(kb, A)[0], mul(ka, B)[0])
print("double-and-add steps for ka:", mul(ka, G)[1], " instead of", ka - 1)

আসল আউটপুট (ব্রাউজারের Python):

13G on the mod-17 curve: ((16, 4), 5)   19G: None
G = (1, 283)   N*G is O: True
public A = (923, 9604)   public B = (2191, 4645)
same shared point: True (4650, 8090)
double-and-add steps for ka: 15  instead of 1952

প্রথম লাইন stepper-এর সঙ্গে মেলে: 13G = (16, 4), ৫টি অপারেশনে; আর 19G = O (Python-এ None), কারণ group-এর আকার 19. খেলনা curve-এ NG = O নিশ্চিত করে G-এর order N (N মৌলিক বলে order 1 বা N হতে পারে, আর G ≠ O). দুই পক্ষ আলাদা পথে একই বিন্দু (4650, 8090)-এ পৌঁছেছেন, যা উপপাদ্য ৭.২. শেষ লাইনে রিনার গোপন সংখ্যা a = 1953-এর জন্য double-and-add লেগেছে ১৫টি অপারেশন, সরাসরি যোগে লাগত ১,৯৫২টি। p এখানে মাত্র ১৪ bit, তাই এটি শুধু খেলনা।

কেন খেলনা? কারণ এত ছোট group-এ ECDLP সহজ। নিচের ব্লক আগে ছোট সব p-এর প্রতিটি মসৃণ curve-এ Hasse-এর সীমা মেলায়, তারপর তিনটি নিজের বানানো খেলনা curve-এ G, 2G, 3G, … করে নিজেদের গোপন সংখ্যা খুঁজে বের করে, যাতে দেখা যায় ধাপের সংখ্যা N-এর সঙ্গে কীভাবে বাড়ে।

import random
random.seed(5)
O = None
def add(P, Q, a, p):
    if P is O: return Q
    if Q is O: return P
    (x1, y1), (x2, y2) = P, Q
    if x1 == x2 and (y1 + y2) % p == 0: return O
    if P == Q: lam = (3 * x1 * x1 + a) * pow(2 * y1, -1, p) % p
    else:      lam = (y2 - y1) * pow(x2 - x1, -1, p) % p
    x3 = (lam * lam - x1 - x2) % p
    return (x3, (lam * (x1 - x3) - y1) % p)

def count(a, b, p):                   # 1 (for O) + points, via Euler's criterion
    n = 1
    for x in range(p):
        f = (x**3 + a * x + b) % p
        n += 1 if f == 0 else (2 if pow(f, (p - 1) // 2, p) == 1 else 0)
    return n

ok = all(abs(count(a, b, p) - (p + 1)) <= 2 * p ** 0.5
         for p in (5, 7, 11, 13, 17, 19, 23, 29, 31, 37)
         for a in range(p) for b in range(p) if (4 * a**3 + 27 * b * b) % p)
print("Hasse bound holds on every smooth curve, p <= 37:", ok)

for p, b in ((1019, 18), (10007, 30), (100003, 5)):     # all with a = 2
    N, x = count(2, b, p), 0
    while pow((x**3 + 2 * x + b) % p, (p - 1) // 2, p) != 1: x += 1
    G = (x, pow((x**3 + 2 * x + b) % p, (p + 1) // 4, p))
    k = random.randrange(N // 2, N)                     # our own toy secret
    A = G
    for _ in range(k - 1): A = add(A, G, 2, p)
    R, t = G, 1
    while R != A: R, t = add(R, G, 2, p), t + 1         # try 1G, 2G, 3G, ...
    print(f"p = {p:>6}  N = {N:>6}  brute force: {t:>6} additions, found k: {t == k}")

আসল আউটপুট (ব্রাউজারের Python):

Hasse bound holds on every smooth curve, p <= 37: True
p =   1019  N =   1013  brute force:    824 additions, found k: True
p =  10007  N =  10091  brute force:   7137 additions, found k: True
p = 100003  N =  99907  brute force:  98566 additions, found k: True

৩৭ পর্যন্ত দশটি মৌলিকের প্রতিটি মসৃণ curve (কয়েক হাজার curve) Hasse-এর সীমা মেনেছে। তিনটি খেলনা group-এর আকার মৌলিক (1013, 10091, 99907), আর প্রতিটির গোপন k খুঁজে পেতে লেগেছে k-এর সমান সংখ্যক যোগ: N দশ গুণ হলে কাজও প্রায় দশ গুণ। অর্থাৎ brute force-এর খরচ N-এর সমানুপাতিক, আর √N-এর পদ্ধতিতে খরচ √N. 256 bit-এর curve-এ N ≈ 2256, তাই √N ≈ 2128টি যোগ, যা আজকের সব কম্পিউটার মিলিয়েও নাগালের বাইরে বলে ধরা হয়। এই ব্লক শুধু নিজের বানানো খেলনা group-এ চলে; এর উদ্দেশ্য দেখানো যে parameter ছোট হলে নিরাপত্তা থাকে না।

৮ · কেন ছোট key, মানসম্মত curve আর quantum-এর পরে

mod p-এর discrete log (পর্ব ২৯) আর factoring-এর (পর্ব ২৫) জন্য index calculus আর number field sieve-এর মতো sub-exponential পদ্ধতি আছে: এগুলো সংখ্যার “ভেতরের গঠন” (ছোট মৌলিকে ভেঙে ফেলা) কাজে লাগায়। Elliptic curve-এর বিন্দুর এমন কোনো সাধারণ “ছোট উৎপাদক” নেই, আর ভালো curve-এ সবচেয়ে ভালো জানা আক্রমণ এখনো সাধারণ √N পদ্ধতি। তাই একই নিরাপত্তায় ECC-এর key অনেক ছোট। NIST-এর SP 800-57 Part 1 (Rev. 5, ২০২০)-এর সমতুল্যতার তালিকার সরল রূপ:

নিরাপত্তা (bit)RSA / mod p DHElliptic curve
1122048 bit224–255 bit
1283072 bit256–383 bit
1927680 bit384–511 bit
25615360 bit512 bit বা বেশি

“১২৮ bit নিরাপত্তা” মানে মোটামুটি 2128টি মৌলিক ধাপের কাজ, আর 256 bit-এর curve-এ √N ≈ 2128 ঠিক সেই হিসাব। এই তালিকা একটি নির্দিষ্ট সময়ের মূল্যায়ন; নতুন আক্রমণ বা নতুন নির্দেশিকা এলে সংখ্যা বদলায়, তাই বাস্তবে সবসময় বর্তমান মানপত্র দেখুন। প্রকাশিত রেকর্ডও এই ছবির সঙ্গে মেলে: ২০০৯ সালে একটি গবেষক দল PlayStation 3 যন্ত্রের গুচ্ছে ১১২ bit-এর একটি curve-এ ECDLP সমাধানের কথা প্রকাশ করে, যা 256 bit থেকে বহু দূরে।

মানসম্মত curve: কেন নিজে বানাবেন না

Curve বাছাই সূক্ষ্ম কাজ। কিছু curve-এ বিশেষ গঠনের কারণে ECDLP সহজ হয়ে যায়: যেমন N = p হলে (“anomalous” curve), বা কিছু “supersingular” curve-এ, যেখানে ১৯৯৩ সালের MOV আক্রমণ সমস্যাটিকে একটি finite field-এর সাধারণ discrete log-এ নামিয়ে আনে। তাই বাস্তবে নির্দিষ্ট, বহু বছর ধরে বিশ্লেষিত curve ব্যবহৃত হয়, শুধু নাম ধরে: NIST-এর P-256 (secp256r1 নামেও পরিচিত), আর Daniel J. Bernstein-এর Curve25519 (২০০৫–০৬), যার ওপর key exchange X25519 নামে RFC 7748 (২০১৬)-তে বর্ণিত। এগুলোর নিরাপত্তা নির্ভর করে শুধু curve-এর ওপর নয়, বাস্তবায়নের ওপরও: গোপন সংখ্যার random উৎস (পর্ব ২৬-এর CSPRNG), সময়-নির্ভর তথ্য ফাঁস না হওয়া, আর পাওয়া বিন্দু সত্যিই curve-এ আছে কি না যাচাই। এ কারণে Cybersecurity কোর্সের প্রথম নিয়ম: নিজের cryptography নিজে বানাবেন না, পরীক্ষিত library ব্যবহার করুন।

Quantum computer আর post-quantum পরিবর্তন

পর্ব ২৫-এ দেখেছেন, Peter Shor-এর ১৯৯৪ সালের quantum algorithm যথেষ্ট বড় quantum computer-এ factoring দ্রুত করে। একই algorithm discrete log, আর elliptic curve-এর discrete log-ও দ্রুত সমাধান করে। অর্থাৎ RSA, DH আর ECC, তিনটিই তখন ভাঙবে; এই পর্ব পর্যন্ত (২০২৬) এমন বড় quantum computer তৈরি হয়েছে বলে কোনো প্রকাশ্য প্রমাণ নেই। প্রস্তুতি হিসেবে NIST ২০২৪ সালের আগস্টে তিনটি post-quantum মান প্রকাশ করে: FIPS 203 (ML-KEM, key exchange-এর জন্য), FIPS 204 (ML-DSA) আর FIPS 205 (SLH-DSA), দুটিই signature-এর জন্য। এগুলো elliptic curve নয়, lattice আর hash-ভিত্তিক গণিতে দাঁড়ানো। বাস্তব রূপান্তরে অনেক ব্যবস্থা এখন X25519 আর ML-KEM একসঙ্গে (“hybrid”) ব্যবহার করে, যাতে একটি ভাঙলেও অন্যটি রক্ষা করে। বিস্তারিত Cybersecurity কোর্সের পর্ব ১৪-এ।

মনে রাখুন: এই পর্বের প্রতিটি curve আর field-এর হিসাব শেখার জন্য। খেলনা ECDH-এর p মাত্র ১৪ bit, আর কোনো authentication নেই; এমন কোড আসল ডেটায় ব্যবহার করলে তা প্রায় সঙ্গে সঙ্গে ভাঙা যায়। বাস্তবে TLS-এর মতো প্রতিষ্ঠিত protocol (Cybersecurity কোর্সের পর্ব ১২, Computer Networks কোর্সের পর্ব ৪৮) আর পরীক্ষিত library-ই একমাত্র পথ।

৯ · পরীক্ষার অঙ্ক আর একটি ভুল প্রমাণ

বিশ্ববিদ্যালয়, চাকরি বা ইন্টারভিউর লিখিত পরীক্ষায় এই বিষয়ের যে ধাঁচের অঙ্ক আসে, তার তিনটি পূর্ণ সমাধান। প্রতিটি সংখ্যা scratch-এ Python দিয়ে মেলানো।

অঙ্ক ১: AES-এর GF(2⁸)-এ {57} · {13} কত?

  1. {13} = 0001 0011 = x4 + x + 1. আংশিক গুণফল: {57} · x4 = x10 + x8 + x6 + x5 + x4, {57} · x = x7 + x5 + x3 + x2 + x, {57} · 1 = x6 + x4 + x2 + x + 1.
  2. XOR-এ x6, x5, x4, x2, x জোড়ায় বাদ: x10 + x8 + x7 + x3 + 1.
  3. x2 · m(x) = x10 + x6 + x5 + x3 + x2 XOR করলে x8 + x7 + x6 + x5 + x2 + 1. তারপর m(x) XOR করলে x7 + x6 + x5 + x4 + x3 + x2 + x = 1111 1110 = {fe}. ব্লক ১-এর আউটপুটের সঙ্গে মেলে।

অঙ্ক ২: y² = x³ + 2x + 2 (mod 17)-এ G = (5, 1) হলে 2G কত?

  1. P = Q, তাই tangent-এর সূত্র: λ = (3 · 52 + 2)/(2 · 1) = 77/2. mod 17-এ 77 ≡ 9, আর 2−1 ≡ 9 (2 · 9 = 18 ≡ 1). λ ≡ 81 ≡ 13.
  2. x3 = 132 − 2 · 5 = 169 − 10 = 159 ≡ 159 − 153 = 6.
  3. y3 = 13(5 − 6) − 1 = −14 ≡ 3. তাই 2G = (6, 3); যাচাই: 32 = 9, আর 216 + 12 + 2 = 230 ≡ 9 ✓.

অঙ্ক ৩: y² = x³ + x + 1 (mod 5)-এ কয়টি বিন্দু?

  1. 4 + 27 = 31 ≡ 1 ≢ 0, তাই curve মসৃণ। mod 5-এ বর্গগুলো: 0, 1, 4 (12 = 1, 22 = 4, 32 ≡ 4, 42 ≡ 1).
  2. x = 0: 1, y = 1, 4. x = 1: 3, বর্গ নয়। x = 2: 11 ≡ 1, y = 1, 4. x = 3: 31 ≡ 1, y = 1, 4. x = 4: 69 ≡ 4, y = 2, 3.
  3. মোট 8টি বিন্দু আর O, N = 9. Hasse: |9 − 6| = 3 ≤ 2√5 ≈ 4.47 ✓.

প্রমাণের ভুল ধরুন: “root নেই, তাই irreducible”

একজন লিখলেন: “দাবি: x4 + x2 + 1, GF(2)-এর ওপর irreducible, তাই এটি দিয়ে 16 উপাদানের একটি field GF(16) বানানো যায়। প্রমাণ: x = 0 বসালে মান 1, x = 1 বসালে 1 + 1 + 1 = 1. GF(2)-এ কোনো root নেই, তাই কোনো linear উৎপাদক নেই, তাই polynomial-টি irreducible. ∎” পড়ে ভুলটি নিজে খুঁজুন।

ভুল কোথায়: root না থাকা শুধু ঘাত 1-এর উৎপাদক বাদ দেয়। ঘাত 4-এর polynomial দুটি ঘাত-2 polynomial-এর গুণফলও হতে পারে, যাদের কারোরই root নেই। এখানে ঠিক তা-ই: (x2 + x + 1)2 = x4 + 2x3 + 3x2 + 2x + 1 ≡ x4 + x2 + 1 (mod 2). তাই এই modulus-এ x2 + x + 1 একটি zero divisor, আর ফল field নয়। “root নেই ⇒ irreducible” শুধু ঘাত 2 আর 3-এ সঠিক, কারণ তখন যেকোনো উৎপাদনে একটি উৎপাদকের ঘাত 1 হতেই হয়। সঠিক পরীক্ষা: ঘাত ≤ 2-এর সব polynomial দিয়ে ভাগ করে দেখা (ব্লক ১-এর মতো)। GF(16)-এর জন্য একটি সঠিক modulus x4 + x + 1.

আরও গভীরে: Elliptic curve শুধু cryptography-র যন্ত্র নয়, আধুনিক সংখ্যাতত্ত্বের কেন্দ্রেও। Andrew Wiles ১৯৯৪–৯৫ সালে Fermat-এর শেষ উপপাদ্য প্রমাণ করেন elliptic curve আর modular form-এর একটি গভীর সম্পর্কের (অংশত) প্রমাণ দিয়ে, আর curve-এর ওপর মূলদ বিন্দুর গঠন নিয়ে Birch–Swinnerton-Dyer অনুমান Clay Institute-এর সাতটি “Millennium Prize” সমস্যার একটি। কম্পিউটারে GF(28) আরও বহু জায়গায় আছে: QR code আর RAID-6 ডিস্কের Reed–Solomon ভুল-সংশোধন কোড এই field-এ চলে (ভিন্ন একটি irreducible polynomial নিয়ে), যার গণিত পর্ব ৭২ “Error-correcting code — parity, Hamming code আর Hamming distance”-এর পরের ধাপ।

পরীক্ষা ও ইন্টারভিউতে: বিশ্ববিদ্যালয়, চাকরি বা ইন্টারভিউর পরীক্ষায় এই ধরনের প্রশ্ন প্রায়ই আসে:

  • ℤn কখন field? ঠিক তখন, যখন n মৌলিক; যৌগিক n = rs-এ r, s zero divisor.
  • GF(2⁸)-এ যোগ আর গুণ কী? যোগ = XOR; গুণ = polynomial গুণ, তারপর x8 + x4 + x3 + x + 1 দিয়ে mod 2-এ ভাগশেষ।
  • Point addition-এর সূত্র? λ = (y2 − y1)/(x2 − x1) বা (3x12 + a)/(2y1); x3 = λ2 − x1 − x2, y3 = λ(x1 − x3) − y1, সব mod p.
  • Hasse-এর সীমা? |N − (p + 1)| ≤ 2√p.
  • ECC-তে key ছোট কেন? ভালো curve-এ শুধু √N-এর সাধারণ আক্রমণ জানা, তাই 256 bit-এর curve প্রায় 3072 bit-এর RSA-এর সমান (NIST SP 800-57).

১০ · AI-এর যুগে — field আর curve-এর হিসাব যাচাই

AI সহকারী elliptic curve-এর সূত্র মুখস্থের মতো বলে দেয়, কিন্তু mod p-এর ছোট হিসাবে আর শর্তে নিয়মিত ভুল করে। এগুলো চেনা থাকলে ধরতে এক মিনিট লাগে।

AI-এর ভুলকীভাবে ধরবেন
mod p-এ “ভাগ” করতে সাধারণ ভগ্নাংশ বা দশমিক নিয়ে round করাপ্রতিটি ভাগ pow(d, -1, p) দিয়ে গুণ কি না দেখুন; ফল বিন্দুটি curve-এর সমীকরণে বসিয়ে মেলান
P = Q হলেও chord-এর সূত্র লাগানো (শূন্য দিয়ে ভাগ), বা P + (−P)-এ O না দিয়ে একটি “বিন্দু” বানানোতিনটি ক্ষেত্র আলাদা করে পরীক্ষা করুন: P ≠ ±Q, P = Q, P = −Q
“root নেই, তাই irreducible” বা “x⁸ + 1 দিয়েও field হয়”-এর মতো ভুলঘাত ≤ n/2-এর সব polynomial দিয়ে ভাগ করুন; zero divisor খুঁজুন
শর্ত বাদ দিয়ে উপপাদ্য বলা: 4a³ + 27b² ≠ 0 ছাড়া curve, p মৌলিক ছাড়া “ℤn field”, Hasse-এ p-এর জায়গায় যেকোনো nপ্রতিটি উপপাদ্যের পূর্ণ hypothesis চেয়ে নিন আর সংখ্যায় মিলিয়ে দেখুন
Double-and-add-এ bit-এর ক্রম গুলিয়ে ফেলা (ডান থেকে পড়ে বাঁ থেকে ডানের নিয়ম চালানো)ছোট k-এ (যেমন 13) ফলকে k − 1 বার সরাসরি যোগের সঙ্গে মেলান
Key-আকার, মানপত্রের নম্বর বা curve-এর ইতিহাস বানিয়ে বলাNIST, RFC বা মূল প্রবন্ধে মিলিয়ে নিন; নিশ্চিত না হলে দাবিটি বাদ দিন
শেখার কোডকে “production-ready” বলানিজের লেখা curve-কোড কখনো আসল ডেটায় নয়; পরীক্ষিত library আর মানসম্মত protocol চান

AI-এর কাছে এই ধরনের হিসাব চাইলে এমন কাঠামো দিন, যাতে প্রতিটি ধাপ আলাদা করে পরীক্ষা করা যায়:

নিচের finite field বা elliptic curve-এর হিসাবটি ধাপে ধাপে করো: প্রশ্ন: [যেমন GF(2^8)-এ {57}·{83}, বা y^2 = x^3 + 2x + 2 (mod 17)-এ (10, 6) + (3, 1)] ১. কোন field আর কোন modulus (মৌলিক p, বা irreducible polynomial) ব্যবহার করছ, লেখো; polynomial হলে কেন irreducible তা দেখাও। ২. curve হলে 4a^3 + 27b^2 mod p হিসাব করে দেখাও যে এটি শূন্য নয়, আর দেওয়া বিন্দুগুলো সমীকরণে বসিয়ে যাচাই করো। ৩. প্রতিটি ভাগকে modular inverse দিয়ে গুণ হিসেবে লেখো, আর inverse-টি গুণ করে 1 পাওয়া যায় তা দেখাও। ৪. P = Q, P = −Q আর সাধারণ ক্ষেত্র, কোনটি প্রযোজ্য তা স্পষ্ট বলো। ৫. শেষে ফলাফল যাচাইয়ের একটি ছোট Python কোড দাও (শুধু standard library), যা সরাসরি যোগ বা brute force দিয়ে মেলায়।

AI-এর উত্তর হাতে পেলে — যাচাইয়ের চেকলিস্ট

এই পর্বের প্রায় প্রতিটি দাবি ছোট p-এ এক সেকেন্ডে brute force করা যায়; AI-এর “সবসময়” বা “কখনো না” পেলে আগে ছোট ক্ষেত্রে counterexample খুঁজুন।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন, তারপর “→ উত্তর” চাপুন।

প্র ০১প্রায় দুশো বছর আগের Galois-এর বিমূর্ত ধারণা কীভাবে আজকের প্রতিটি ফোনের encryption-এ পৌঁছাল? Finite field-এর আকার কেন সবসময় মৌলিকের ঘাত?

Évariste Galois ১৮৩০ সালের দিকে বহুপদী সমীকরণের সমাধান নিয়ে কাজ করতে গিয়ে এমন “কাল্পনিক” সংখ্যার জগৎ বিবেচনা করেন, যেখানে mod p-এর হিসাব একটি irreducible polynomial-এর root দিয়ে বাড়ানো হয়। তাঁর জীবন ছিল ছোট আর অস্থির; ১৮৩২ সালে এক দ্বন্দ্বযুদ্ধে আহত হয়ে মাত্র ২০ বছর বয়সে মারা যান, আর তাঁর কাজ বড় পরিসরে স্বীকৃতি পায় কয়েক দশক পরে। ১৮৯৩ সালে E. H. Moore দেখান যে সব finite field এই ধাঁচেরই, আর তখন থেকে এগুলো “Galois field” নামে পরিচিত।

আকার কেন pn, তার যুক্তির কাঠামো এই পর্বের ভাষাতেই বোঝা যায়। একটি finite field-এ 1, 1 + 1, 1 + 1 + 1, … যোগ করতে থাকলে কোনো এক সময় 0 আসবেই, কারণ উপাদান সসীম। যে সবচেয়ে ছোট সংখ্যা p-তে প্রথম 0 আসে, তা মৌলিক হতেই হয়: p = rs হলে (r · 1)(s · 1) = 0, অর্থাৎ zero divisor, যা field-এ অসম্ভব (উপপাদ্য ২.২-এর যুক্তি)। এই p-কে field-এর characteristic বলে, আর field-টি তখন GF(p)-এর ওপর একটি vector space; n মাত্রার vector space-এ ঠিক pnটি উপাদান। পূর্ণ প্রমাণ পর্ব ৭১-এর বিষয়।

প্রায় দেড়শো বছর পরে এই বিমূর্ত গণিত প্রকৌশলের প্রয়োজনে কেন্দ্রে এল। প্রথমে ভুল-সংশোধনী কোডে: ১৯৬০ সালে Irving Reed আর Gustave Solomon-এর কোড finite field-এর polynomial ব্যবহার করে, যা পরে CD, মহাকাশযানের যোগাযোগ আর QR code-এ পৌঁছায়। তারপর cryptography-তে: Rijndael-এর নকশাকারীরা byte-এর জন্য GF(28) বেছে নেন, কারণ সেখানে প্রতিটি byte-এর inverse আছে আর হিসাব মানে শুধু shift আর XOR, যা চিপে খুব সস্তা। ২০০১ সালে AES হিসেবে মানপত্র হওয়ার পর আজ বহু প্রসেসরে AES-এর জন্য বিশেষ hardware নির্দেশও আছে।

মূল উপলব্ধি: “কোন সেটে চার নিয়ম চলে” এই বিশুদ্ধ প্রশ্নের উত্তর (শুধু pn আকারে) আজ নির্ধারণ করে কম্পিউটার কোন আকারের এককে নির্ভুল ও উল্টানো যায় এমন হিসাব করতে পারে, আর byte-এর 256 = 28 এই তালিকায় আছে বলেই AES এত সহজে চলে।

প্র ০২Elliptic curve cryptography প্রস্তাবিত হয় ১৯৮৫ সালে, কিন্তু ব্যাপক ব্যবহারে আসতে প্রায় দুই দশক লাগে। কেন এত সময়, আর কী বদলাল?

১৯৮৫ সালের দিকে Neal Koblitz আর Victor Miller আলাদাভাবে প্রস্তাব করেন যে finite field-এর ওপর elliptic curve-এর group-এ Diffie–Hellman চালানো যায়। ধারণাটি গাণিতিকভাবে আকর্ষণীয় ছিল, কারণ mod p-এর জন্য তখনই জানা index calculus-এর মতো আক্রমণ curve-এ খাটে বলে মনে হচ্ছিল না। কিন্তু একটি নতুন cryptography-কে বিশ্বাস করতে সময় লাগে, আর সেই সময়টি এখানে লেগেছে কয়েক কারণে।

প্রথমত, গাণিতিক আস্থা। একটি সমস্যা কঠিন কি না, তার কোনো প্রমাণ থাকে না; আস্থা আসে বহু বছর ধরে বহু গবেষকের আক্রমণের চেষ্টা ব্যর্থ হওয়া থেকে। এই সময়েই কিছু দুর্বল শ্রেণি ধরা পড়ে, যেমন ১৯৯৩ সালের MOV আক্রমণ supersingular curve-এ, আর ১৯৯০-এর দশকের শেষে anomalous curve-এর আক্রমণ। এগুলো দেখায় কোন curve এড়াতে হবে, আর তাতে বাকিগুলোর ওপর আস্থা বরং বাড়ে। দ্বিতীয়ত, বাস্তব হিসাব: বিন্দুর সংখ্যা N গোনা, যা নিরাপত্তার জন্য জরুরি, ১৯৮৫ সালের Schoof-এর algorithm আর পরের উন্নতির আগে কঠিন ছিল। তৃতীয়ত, আইনি অনিশ্চয়তা: ECC-এর নানা কৌশলে patent ছিল বলে অনেক প্রতিষ্ঠান সতর্ক ছিল বলে জানা যায়।

পরিবর্তন আসে ২০০০-এর দশকে। NIST-এর মানপত্রে নির্দিষ্ট curve (যেমন P-256) আসে, মার্কিন NSA ২০০৫ সালে “Suite B”-এ ECC সুপারিশ করে বলে উল্লেখিত, আর মোবাইল যন্ত্র ছড়িয়ে পড়ায় ছোট key আর দ্রুত হিসাবের দাম বাড়ে। Bernstein-এর Curve25519 (২০০৫–০৬) দ্রুত আর ভুল-সহনশীল বাস্তবায়নের পথ দেখায়। TLS 1.3 (RFC 8446, ২০১৮)-এ key exchange কার্যত সবসময় ephemeral (প্রতি সংযোগে নতুন) Diffie–Hellman, আর বাস্তবে বেশিরভাগই elliptic curve-এ।

মূল উপলব্ধি: cryptography-তে একটি ভালো গাণিতিক ধারণা যথেষ্ট নয়; আক্রমণের বছরের পর বছর, মানসম্মত parameter, নিরাপদ বাস্তবায়ন আর বাস্তব প্রয়োজন মিলেই তা দৈনন্দিন যন্ত্রে পৌঁছায়।

প্র ০৩একটি মানসম্মত curve-এর ধ্রুবকগুলো কোথা থেকে এল, তা কেন গুরুত্বপূর্ণ? “Nothing-up-my-sleeve” ধারণা আর বিশ্বাসের প্রশ্নটি ব্যাখ্যা করুন।

একটি curve বাছাই মানে কয়েকটি সংখ্যা ঠিক করা: p, a, b, generator G আর তার order. এই পর্বে দেখেছেন, কিছু বিশেষ curve-এ ECDLP সহজ। প্রশ্ন জাগে: যদি কেউ এমন কোনো দুর্বলতা জানেন যা বাকিরা জানে না, তিনি কি এমন curve “মানসম্মত” হিসেবে চালিয়ে দিতে পারেন? এর বিরুদ্ধে প্রচলিত রক্ষাকবচ হলো “nothing-up-my-sleeve” সংখ্যা: ধ্রুবকগুলো এমন উৎস থেকে নেওয়া, যা সবাই যাচাই করতে পারে আর যেখানে লুকানোর জায়গা নেই, যেমন π-এর অঙ্ক বা “সবচেয়ে ছোট যে সংখ্যাটি সব শর্ত মানে”।

NIST-এর P-256-এর মতো curve-এর b একটি hash-এর আউটপুট থেকে আসে, যার ইনপুট একটি নির্দিষ্ট “seed”; কিন্তু seed-টি কেন সেই নির্দিষ্ট মান, তা প্রকাশিত হয়নি। এ নিয়ে আশঙ্কা জোরালো হয় ২০১৩ সালের পরে, যখন Dual_EC_DRBG নামের একটি elliptic-curve-ভিত্তিক random number generator নিয়ে প্রকাশিত নথির ভিত্তিতে ব্যাপক অভিযোগ ওঠে যে এর ধ্রুবকে একটি গোপন “পেছনের দরজা” থাকতে পারে; NIST ২০১৪ সালে এর সুপারিশ প্রত্যাহার করে। লক্ষ করুন, P-256-এর বিরুদ্ধে এমন কোনো দুর্বলতা আজও প্রকাশ্যে দেখানো হয়নি, আর বহু বিশেষজ্ঞ একে নিরাপদ মনে করেন; প্রশ্নটি প্রমাণের নয়, যাচাইযোগ্যতার।

এই প্রেক্ষাপটে Bernstein আর Tanja Lange “SafeCurves” মানদণ্ড প্রস্তাব করেন, যেখানে curve-এর প্রতিটি ধ্রুবক একটি সরল, ব্যাখ্যাযোগ্য নিয়ম থেকে আসে (“rigidity”), আর curve এমন যাতে সাধারণ বাস্তবায়নের ভুলে তথ্য ফাঁস না হয়। Curve25519-এর p = 2255 − 19 আর তার ধ্রুবক এভাবে বাছা। RFC 7748 (২০১৬) এই curve-কে Internet-এর মানে আনে। একই নীতি অন্য জায়গাতেও খাটে: AES-এর S-box-এর পেছনে একটি প্রকাশ্য গাণিতিক নির্মাণ (GF(28)-এর inverse) আছে, তাই সবাই যাচাই করতে পারে যে টেবিলে কিছু লুকানো নেই।

মূল উপলব্ধি: cryptography-র নিরাপত্তা শুধু গণিতের কঠিনতায় নয়, parameter কে আর কীভাবে বেছেছে তার স্বচ্ছতাতেও; যাচাইযোগ্য ধ্রুবক অবিশ্বাস দূর করার সবচেয়ে সস্তা উপায়।

প্র ০৪256 bit-এর elliptic curve কীভাবে 3072 bit-এর RSA-এর সমান নিরাপত্তা দেয়? “Index calculus” কেন mod p-তে কাজ করে কিন্তু curve-এ করে না?

সব discrete log সমস্যার জন্য একটি “সাধারণ” আক্রমণ আছে, যা group-এর কোনো বিশেষ গঠন জানে না, শুধু গুণ বা যোগ করতে পারে: baby-step giant-step আর Pollard-এর ১৯৭৮ সালের rho পদ্ধতি, দুটিই প্রায় √N ধাপে চলে। ১৯৯৭ সালে Victor Shoup প্রমাণ করেন যে এমন “generic” পদ্ধতির পক্ষে √N-এর চেয়ে মূলগতভাবে কম সময় অসম্ভব। তাই যদি একটি group-এ শুধু generic আক্রমণ সম্ভব হয়, তবে N ≈ 2256 নিলে 2128 নিরাপত্তা মেলে।

mod p-এর গুণের group-এ কিন্তু একটি অতিরিক্ত গঠন আছে: প্রতিটি উপাদান একটি সাধারণ পূর্ণসংখ্যা, যাকে ছোট মৌলিকের গুণফলে ভাঙার চেষ্টা করা যায়। Index calculus পদ্ধতি প্রথমে ছোট মৌলিকগুলোর discrete log বের করে (অনেক “মসৃণ” সংখ্যা সংগ্রহ করে একটি linear সমীকরণ-ব্যবস্থা সমাধান করে), তারপর যেকোনো উপাদানকে ছোট মৌলিকে ভেঙে তার log বের করে। এর খরচ sub-exponential, অর্থাৎ √p-এর চেয়ে অনেক কম, আর factoring-এর number field sieve-এর সঙ্গে ঘনিষ্ঠ। তাই mod p-এর DH বা RSA-তে 128 bit নিরাপত্তার জন্য 3072 bit লাগে।

Elliptic curve-এর একটি বিন্দু (x, y)-কে “ছোট বিন্দুর যোগফলে” ভাঙার কোনো কার্যকর উপায় সাধারণ curve-এ জানা নেই; বিন্দুর মধ্যে মৌলিক উৎপাদনের মতো কোনো ধারণা কাজ করে না। দুর্বলতা আসে শুধু বিশেষ curve-এ: supersingular curve-এ MOV আক্রমণ ECDLP-কে একটি ছোট finite field-এর DLP-তে নামায়, যেখানে index calculus আবার চলে; anomalous curve-এ (N = p) সমস্যাটি আরও সহজ। মানসম্মত curve এই শ্রেণিগুলো এড়িয়ে বাছা হয়। প্রকাশিত রেকর্ডও এই ছবি সমর্থন করে: সমাধান হওয়া সবচেয়ে বড় সাধারণ ECDLP-গুলো ১১০–১২০ bit-এর কাছাকাছি, যেখানে mod p-এর DLP-এর রেকর্ড কয়েকশো দশমিক অঙ্কের।

মূল উপলব্ধি: নিরাপত্তা নির্ভর করে group-এর ভেতরের গঠন আক্রমণকারী কতটা কাজে লাগাতে পারে তার ওপর; curve-এর group “গঠনহীন” আচরণ করে বলেই ছোট key-তে একই নিরাপত্তা, যদিও এটি প্রমাণিত নয়, বহু দশকের অভিজ্ঞতা-নির্ভর বিশ্বাস।

প্র ০৫বড় quantum computer RSA আর ECC দুটিই ভাঙবে, অথচ এখনো তা তৈরি হয়নি। তাহলে আজই post-quantum-এ যাওয়ার তাড়া কেন, আর রূপান্তরটি কেমন হচ্ছে?

Peter Shor-এর ১৯৯৪ সালের algorithm একটি group-এ “লুকানো পর্যায়” খুঁজে বের করে; factoring আর discrete log, দুটিই এই কাঠামোয় পড়ে, আর elliptic curve-এর group-ও ব্যতিক্রম নয়। কিছু গবেষণা-অনুমান অনুযায়ী একই নিরাপত্তার RSA-র চেয়ে ECC ভাঙতে কম qubit লাগতে পারে, কারণ সংখ্যাগুলো ছোট; তবে এমন অনুমান quantum hardware-এর অগ্রগতির সঙ্গে বারবার বদলায়, তাই সতর্কভাবে পড়তে হয়। এই পর্ব পর্যন্ত এমন বড়, ভুল-সংশোধিত quantum computer-এর প্রকাশ্য প্রমাণ নেই।

তবু তাড়ার কারণ একটি সহজ হিসাব, যাকে প্রায়ই “harvest now, decrypt later” বলা হয়: কেউ আজকের এনক্রিপ্টেড ট্রাফিক সংরক্ষণ করে রাখলে ভবিষ্যতে quantum computer হাতে পেলে তা খুলতে পারবে। যে তথ্য দশ-বিশ বছর গোপন রাখতে হয় (স্বাস্থ্য, সরকারি নথি, ব্যবসার গোপন পরিকল্পনা), তার জন্য ঝুঁকি আজই শুরু। তার ওপর বড় ব্যবস্থার cryptography বদলাতে বহু বছর লাগে; SHA-1 বা পুরোনো TLS সরাতে কত সময় লেগেছে, ইতিহাস তা দেখিয়েছে।

NIST ২০১৬ সালে একটি উন্মুক্ত প্রতিযোগিতা শুরু করে, আর ২০২৪ সালের আগস্টে প্রথম তিনটি মান প্রকাশ করে: FIPS 203 (ML-KEM, lattice-ভিত্তিক key encapsulation), FIPS 204 (ML-DSA, lattice-ভিত্তিক signature) আর FIPS 205 (SLH-DSA, hash-ভিত্তিক signature). এদের key আর বার্তা ECC-এর চেয়ে বড়, তাই রূপান্তরে ধীরে ধীরে চলা হচ্ছে। এখনকার প্রচলিত পথ “hybrid” key exchange: X25519 আর ML-KEM দুটিই চালিয়ে দুটির ফল মিলিয়ে key বানানো, যাতে নতুন algorithm-এ অজানা দুর্বলতা পাওয়া গেলেও পুরোনোটি রক্ষা করে, আর quantum এলে নতুনটি। বড় ব্রাউজার আর সার্ভার সফটওয়্যারে এমন hybrid ব্যবস্থা ২০২৪ সাল থেকে চালু হতে শুরু করেছে বলে জানা যায়।

মূল উপলব্ধি: cryptography-র সিদ্ধান্ত নিতে হয় তথ্যের আয়ু আর রূপান্তরের সময় মিলিয়ে, শুধু আজকের হুমকি দেখে নয়; তাই elliptic curve শেখা জরুরি, কিন্তু তার উত্তরসূরিদের দিকেও চোখ রাখতে হয়।

অনুশীলন

আগে খাতায় করুন, তারপর উত্তর খুলে মেলান।

  1. প্রমাণ: প্রমাণ করুন, যেকোনো field F-এ a · b = 0 হলে a = 0 অথবা b = 0. এর থেকে দেখান, ℤ21 একটি field নয়।
    1. ধরা যাক ab = 0 আর a ≠ 0. তাহলে a-এর inverse a−1 আছে। — field-এর সংজ্ঞা
    2. প্রথমে দেখাই 0 · x = 0: 0 · x = (0 + 0) · x = 0 · x + 0 · x, আর দুই পাশে −(0 · x) যোগ করলে 0 = 0 · x. — বণ্টন বিধি
    3. b = 1 · b = (a−1a)b = a−1(ab) = a−1 · 0 = 0. তাই a = 0 অথবা b = 0. ∎ — associativity আর ধাপ ২

    ℤ21-এ 3 ≢ 0 আর 7 ≢ 0, কিন্তু 3 · 7 = 21 ≡ 0. তাই প্রমাণিত ধর্মটি ভাঙে, আর ℤ21 field হতে পারে না (উপপাদ্য ২.২-এর সঙ্গে মেলে, কারণ 21 মৌলিক নয়)।

  2. হিসাব: (ক) GF(28)-এ (AES-এর modulus) {02} · {87} কত? (খ) y2 = x3 + 2x + 2 (mod 17)-এ (6, 3)-কে দ্বিগুণ করুন। (গ) p = 101 হলে Hasse অনুযায়ী N-এর সম্ভাব্য পরিসর কী? (ঘ) Double-and-add-এ 100P বের করতে কয়টি দ্বিগুণ আর কয়টি যোগ লাগে?

    (ক) {02} মানে x দিয়ে গুণ, অর্থাৎ এক bit বাঁয়ে সরানো: 1000 0111 → 1 0000 1110. ঘাত 8 এসেছে, তাই {11B} = 1 0001 1011 XOR করুন: 0001 0101 = {15}.

    (খ) λ = (3 · 36 + 2)/(2 · 3) = 110/6. 110 ≡ 8, আর 6−1 ≡ 3 (6 · 3 = 18 ≡ 1), তাই λ ≡ 24 ≡ 7. x3 = 49 − 12 = 37 ≡ 3, y3 = 7(6 − 3) − 3 = 18 ≡ 1. ফল (3, 1), যা 4G-এর সঙ্গে মেলে (2G-এর দ্বিগুণ)।

    (গ) p + 1 = 102 আর 2√101 ≈ 20.10, তাই 81.9 ≤ N ≤ 122.1, অর্থাৎ পূর্ণসংখ্যা N ∈ {82, …, 122}.

    (ঘ) 100 = 11001002, ৭টি bit আর তিনটি 1. দ্বিগুণ 7 − 1 = 6টি, যোগ 3 − 1 = 2টি, মোট ৮টি অপারেশন (৯৯টি সরাসরি যোগের বদলে)। সব সংখ্যা scratch-এ Python দিয়ে যাচাই করা।

  3. আউটপুট অনুমান: কোড না চালিয়ে বলুন কী ছাপা হবে। তারপর যেকোনো Python-এ চালিয়ে মেলান।
    def xtime(b):
        b <<= 1
        return b ^ 0x11B if b & 0x100 else b
    print([hex(xtime(b)) for b in (0x57, 0xAE, 0x47, 0x8E)])
    print([a * b % 6 for a in (2, 3) for b in (3, 4)])
    ['0xae', '0x47', '0x8e', '0x7']
    [0, 2, 3, 0]

    প্রথম লাইন: xtime মানে GF(28)-এ {02} দিয়ে গুণ। {57} → {ae} (ঘাত 8 আসেনি); {ae} → 1 0101 1100, তাতে {11B} XOR করে {47}; {47} → {8e}; {8e} → 1 0001 1100 ⊕ 1 0001 1011 = {07}. এটি FIPS 197-এর {57} · {13}-এর হিসাবেও ব্যবহৃত ধারা। দ্বিতীয় লাইন ℤ6-এর zero divisor দেখায়: 2 · 3 ≡ 0 আর 3 · 4 = 12 ≡ 0, কারণ 6 মৌলিক নয়।

  4. প্রমাণের ভুল ধরুন: একজন লিখলেন: “দাবি: যেকোনো field-এ 1 + 1 ≠ 0. প্রমাণ: 1 + 1 = 2, আর 2 ≠ 0. ∎ তাই elliptic curve-এর দ্বিগুণের সূত্র λ = (3x12 + a)/(2y1) যেকোনো field-এ চলে (y1 ≠ 0 হলে)।” ভুল কোথায়, আর একটি counterexample দিন।
    • ভুল: “2” এখানে পূর্ণসংখ্যা 2 নয়, field-এর উপাদান 1 + 1; আর “2 ≠ 0” পূর্ণসংখ্যার সত্য, field-এর নয়। প্রমাণটি যা প্রমাণ করার কথা, তা-ই ধরে নিয়েছে (circular reasoning).
    • Counterexample: GF(2)-এ 1 + 1 = 0, আর AES-এর GF(28)-এও প্রতিটি a-তে a + a = 0 (XOR). তখন 2y1 = 0, আর দ্বিগুণের সূত্রে শূন্য দিয়ে ভাগ হয়।
    • সংশোধন: সূত্রটি চলে যদি field-এর characteristic 2 বা 3 না হয় (যেমন GF(p), p > 3). GF(2n)-এর ওপর curve-এর জন্য আলাদা সমীকরণ (যেমন y2 + xy = x3 + ax2 + b) আর আলাদা সূত্র ব্যবহৃত হয়।

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমখোলা পথে ECDH দিয়ে একটি গোপন key বানানোর ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. দুই পক্ষ প্রকাশ্যে একটি মানসম্মত curve, মৌলিক p আর মৌলিক order-এর বিন্দু G ঠিক করে
  2. প্রত্যেকে গোপনে একটি এলোমেলো সংখ্যা বাছে (a আর b)
  3. double-and-add দিয়ে aG আর bG হিসাব করে খোলা পথে পাঠায়
  4. প্রত্যেকে পাওয়া বিন্দুকে নিজের গোপন সংখ্যা দিয়ে গুণ করে (aB, bA)
  5. দুজনের একই বিন্দু (ab)G থেকে key derivation function দিয়ে key বানানো হয়

নিচের কোনটি একটি field?

  • ℤ15
  • ℤ16
  • ℤ17
  • ℤ21

AES-এর GF(28)-এ দুটি byte {57} আর {83}-এর যোগফল কত?

  • {da}
  • {d4}
  • {c1}
  • {03}

y2 = x3 + 2x + 2 (mod 17) curve-এ (5, 1) + (5, 16) কত?

  • অসীমের বিন্দু O
  • (5, 0)
  • (10, 0)
  • (5, 17)

p = 101 মৌলিক। GF(101)-এর ওপর একটি মসৃণ elliptic curve-এর বিন্দুর সংখ্যা N (O-সহ) কোনটি হতে পারে না?

  • 90
  • 102
  • 115
  • 130

বাঁ থেকে ডানের double-and-add-এ (শুরু R = P) 13P বের করতে কয়টি দ্বিগুণ আর কয়টি যোগ লাগে?

  • 0টি দ্বিগুণ, 12টি যোগ
  • 3টি দ্বিগুণ, 2টি যোগ
  • 3টি দ্বিগুণ, 3টি যোগ
  • 4টি দ্বিগুণ, 2টি যোগ

একই নিরাপত্তায় elliptic curve-এর key RSA বা mod p Diffie–Hellman-এর চেয়ে অনেক ছোট হয় কেন?

  • ভালো curve-এ শুধু প্রায় √N ধাপের সাধারণ আক্রমণ জানা, mod p-এর মতো sub-exponential আক্রমণ জানা নেই
  • ECDLP যে কঠিন, তা গাণিতিকভাবে প্রমাণিত
  • Quantum computer ECC ভাঙতে পারে না
  • Curve-এর প্রতিটি যোগ এক ধাপের সাধারণ গুণের চেয়ে দ্রুত

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন, অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. Field: যোগ, বিয়োগ, গুণ আর অশূন্য দিয়ে ভাগ চলে। ℤn field ⇔ n মৌলিক; field-এ zero divisor নেই। Finite field-এর আকার শুধু pn.
  2. GF(2⁸): byte = mod 2 সহগের polynomial; যোগ XOR, গুণের পরে irreducible m(x) = x8 + x4 + x3 + x + 1 দিয়ে ভাগশেষ। {57} · {83} = {c1}.
  3. Curve-এর যোগ: λ = chord বা tangent-এর ঢাল, x3 = λ2 − x1 − x2, y3 = λ(x1 − x3) − y1; P + (−P) = O. বিন্দু আর O মিলে abelian group.
  4. GF(p)-এ: সব ভাগ modular inverse দিয়ে; |N − (p + 1)| ≤ 2√p. kP-এর জন্য double-and-add, ≤ 2 log2 k ধাপ।
  5. ECDLP আর নিরাপত্তা: kG থেকে k বের করা কঠিন বলে বিশ্বাস; ECDH-এ aB = bA = (ab)G. খেলনা সংখ্যা শুধু শেখার জন্য; বাস্তবে মানসম্মত curve, পরীক্ষিত library, আর সামনে post-quantum (FIPS 203–205, ২০২৪).

পরের পর্বে: পর্ব ৩১ “গণনার মূল নিয়ম — যোগ, গুণ, বিয়োগ আর ভাগ”: মডিউল ৬-এর শুরু, যেখানে পাসওয়ার্ড, কুপন কোড আর ডেলিভারির রুট গোনার চারটি মৌলিক নিয়ম শিখবেন, আর দেখবেন এই মডিউলের “2128টি ধাপ”-এর মতো বড় সংখ্যা কীভাবে গোনা হয়।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান