পাঠ ৩৮ · ৬০-এর মধ্যে · মডিউল ৭
Home / Courses / Cybersecurity & Ethical Hacking / TLS হ্যান্ডশেক

TLS হ্যান্ডশেক গভীরভাবে

The TLS handshake in depth
৯ মিনিট পড়া মধ্যম · Intermediate Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • TLS হ্যান্ডশেকের চারটি ধাপ, ধাপে-ধাপে
  • সার্টিফিকেট যাচাই ঠিক কোথায় হ্যান্ডশেকের মধ্যে ঘটে
  • কীভাবে দুই পক্ষ সিক্রেট নিজে না পাঠিয়েও একটি অভিন্ন শেয়ার্ড কী-তে পৌঁছায় (Diffie-Hellman-এর মূল ধারণা)
  • TLS 1.3, TLS 1.2-এর তুলনায় কীভাবে দ্রুত ও নিরাপদ

১ · হ্যান্ডশেকের চারটি ধাপ

একটি TLSTransport Layer Securityইন্টারনেটে ডেটা ট্রান্সমিশন এনক্রিপ্ট ও প্রমাণীকরণ করার প্রোটোকল — HTTPS-এর "S" এটাই। সংযোগ শুরু হওয়ার আগে ক্লায়েন্ট (যেমন আপনার ব্রাউজার) ও সার্ভার একটি "হ্যান্ডশেক" সম্পন্ন করে — একে অপরের সাথে পরিচিত হয়ে একটি নিরাপদ চ্যানেল প্রতিষ্ঠা করে। উচ্চ-স্তরে (byte-level নয়), এটি চারটি ধাপে ঘটে:

  1. ClientHello — ক্লায়েন্ট প্রস্তাব করে সে কোন TLS ভার্সন ও কোন cipher suite-গুলো সমর্থন করে।
  2. ServerHello + সার্টিফিকেট — সার্ভার একটি cipher suite চূড়ান্ত করে এবং নিজের X.509 সার্টিফিকেট পাঠায় (L37-এর ট্রাস্ট চেইন যাচাই এখানেই ঘটে)।
  3. কী এক্সচেঞ্জ — ক্লায়েন্ট ও সার্ভার (Diffie-Hellman বা RSA-ভিত্তিক পদ্ধতিতে) স্বাধীনভাবে গণনা করে একটি অভিন্ন শেয়ার্ড সিক্রেটে পৌঁছায়, সিক্রেটটি নিজে কখনো নেটওয়ার্কে পাঠানো ছাড়াই।
  4. এনক্রিপ্টেড যোগাযোগ শুরু — শেয়ার্ড সিক্রেট থেকে তৈরি একটি সিমেট্রিক সেশন কী দিয়ে বাকি পুরো সেশনের ডেটা এনক্রিপ্ট হয়।
কেন এটাই L35-এর hybrid approach-এর বাস্তব উদাহরণ

L35-এ আমরা বলেছিলাম বাস্তব সিস্টেম অ্যাসিমেট্রিক ও সিমেট্রিক এনক্রিপশন — দুটোই ব্যবহার করে: অ্যাসিমেট্রিক (ধীরগতির কিন্তু কী-বিতরণ সমস্যা সমাধান করে) হ্যান্ডশেকের জন্য, সিমেট্রিক (দ্রুতগতির) আসল ডেটার জন্য। ধাপ ৩ অ্যাসিমেট্রিক/DH-ভিত্তিক গণনা ব্যবহার করে শুধু একটি ছোট সিক্রেট নিরাপদে স্থাপন করতে, আর ধাপ ৪ সেই সিক্রেট থেকে পাওয়া সিমেট্রিক কী দিয়ে বাকি বিশাল ডেটা দ্রুত এনক্রিপ্ট করে। এটাই ঠিক hybrid approach।

ClientHello ১ ServerHello + সার্টিফিকেট ২ কী এক্সচেঞ্জ ৩ এনক্রিপ্টেড যোগাযোগ ৪ · বাকি পুরো সেশন
চারটি ধাপ সবসময় এই ক্রমেই ঘটে — কী এক্সচেঞ্জ সম্পন্ন না হয়ে এনক্রিপ্টেড যোগাযোগ শুরু হতে পারে না।

২ · সিক্রেট না পাঠিয়েও একটি অভিন্ন সিক্রেটে পৌঁছানো — Diffie-Hellman-এর ধারণা

ধাপ ৩-এর সবচেয়ে চমকপ্রদ অংশ হলো — ক্লায়েন্ট ও সার্ভার একবারও শেয়ার্ড সিক্রেটটি নিজে নেটওয়ার্কে না পাঠিয়েই একটি অভিন্ন মানে পৌঁছায়। Diffie-HellmanDiffie-Hellman Key Exchangeএকটি গাণিতিক পদ্ধতি যা দুই পক্ষকে একটি পাবলিক চ্যানেলের উপর দিয়ে একটি অভিন্ন সিক্রেট প্রতিষ্ঠা করতে দেয়, সিক্রেটটি নিজে কখনো ট্রান্সমিট না করেই। এটাই সম্ভব করে — মডুলার এক্সপোনেনশিয়েশনের একটি গাণিতিক বৈশিষ্ট্য ব্যবহার করে, যেখানে দুই দিক থেকে গণনা করলেও ফলাফল একই আসে, কিন্তু শুধু পাবলিক মানগুলো দেখে (নিজের গোপন সংখ্যা ছাড়া) সেই ফলাফল বের করা কম্পিউটেশনালি অসম্ভব-প্রায়।

নিচে একটি অত্যন্ত ছোট, শুধুমাত্র শিক্ষামূলক (textbook-scale) সংখ্যা দিয়ে একটি উদাহরণ দেওয়া হলো — বাস্তব TLS হাজার হাজার বিটের সংখ্যা ব্যবহার করে, কিন্তু গাণিতিক ধারণাটা অভিন্ন। ধরা যাক একটি পাবলিক বেস $g = 5$ এবং একটি পাবলিক মডুলাস (মৌলিক সংখ্যা) $p = 23$। ক্লায়েন্টের একটি গোপন সংখ্যা $6$, সার্ভারের গোপন সংখ্যা $15$ — এই দুটো সংখ্যা কখনোই নেটওয়ার্কে পাঠানো হয় না, শুধু নিচের কোড সেলে গণনা করে দেখানো হচ্ছে।

Python
handshake_steps = {
    "1. ClientHello": "ক্লায়েন্ট সমর্থিত TLS ভার্সন ও cipher suite প্রস্তাব করে",
    "2. ServerHello + সার্টিফিকেট": "সার্ভার cipher suite চূড়ান্ত করে ও X.509 সার্টিফিকেট পাঠায় (L37-এর ট্রাস্ট চেইন যাচাই হয়)",
    "3. কী এক্সচেঞ্জ": "উভয় পক্ষ স্বাধীনভাবে গণনা করে একই শেয়ার্ড সিক্রেটে পৌঁছায়, সিক্রেট নিজে ট্রান্সমিট না করেই",
    "4. এনক্রিপ্টেড যোগাযোগ শুরু": "শেয়ার্ড সিক্রেট থেকে তৈরি সিমেট্রিক সেশন কী দিয়ে বাকি সেশন এনক্রিপ্ট হয় (L35)",
}

for step, desc in handshake_steps.items():
    print(step, "->", desc)

print()
print("--- টয় Diffie-Hellman উদাহরণ (শুধুই শিক্ষামূলক, ছোট সংখ্যায়) ---")

g, p = 5, 23              # পাবলিক, উভয় পক্ষ ও যে কেউ দেখতে পারে
client_secret = 6         # গোপন, ক্লায়েন্ট কখনো পাঠায় না
server_secret = 15        # গোপন, সার্ভার কখনো পাঠায় না

client_public = pow(g, client_secret, p)   # নেটওয়ার্কে পাঠানো হয় (গোপন নয়)
server_public = pow(g, server_secret, p)   # নেটওয়ার্কে পাঠানো হয় (গোপন নয়)

shared_client = pow(server_public, client_secret, p)   # ক্লায়েন্টের হিসাব
shared_server = pow(client_public, server_secret, p)   # সার্ভারের হিসাব

print("client_public  =", client_public)
print("server_public  =", server_public)
print("shared (ক্লায়েন্ট হিসাব করেছে) =", shared_client)
print("shared (সার্ভার হিসাব করেছে)   =", shared_server)
print("দুই পক্ষ কি স্বাধীনভাবে একই সিক্রেটে পৌঁছেছে?", shared_client == shared_server)

    
কোড চালালে দেখা যাবে client_public = 8, server_public = 19, এবং দুই পক্ষই স্বাধীনভাবে গণনা করে একই শেয়ার্ড সিক্রেট 2-এ পৌঁছায় — যদিও 6 ও 15 সংখ্যা দুটো কখনো নেটওয়ার্কে পাঠানো হয়নি, শুধু client_public ও server_public (পাবলিক মান) আদান-প্রদান হয়েছে। বাস্তব TLS-এ $g$, $p$ এবং গোপন সংখ্যাগুলো শত শত বিটের হয় — তখন শুধু পাবলিক মান দেখে গোপন সংখ্যা বের করা (discrete logarithm problem) কম্পিউটেশনালি অসম্ভব-প্রায় হয়ে যায়, যদিও গাণিতিক নীতিটা এই ছোট উদাহরণের মতোই।

৩ · TLS 1.3 — দ্রুততর ও পরিষ্কার

TLS 1.3 (আধুনিক ওয়েবের বর্তমান স্ট্যান্ডার্ড) TLS 1.2-এর তুলনায় দুটি বড় উন্নতি এনেছে — সংক্ষেপে মনে রাখার মতো:

কম রাউন্ড-ট্রিপ
TLS 1.2-এ হ্যান্ডশেক সম্পন্ন হতে একাধিক নেটওয়ার্ক রাউন্ড-ট্রিপ লাগত; TLS 1.3 তা কমিয়ে সাধারণত একটি রাউন্ড-ট্রিপে নামিয়ে এনেছে — দ্রুত পেজ লোড।
দুর্বল cipher বাদ
পুরনো, ইতিমধ্যে-ভাঙা বা দুর্বল cipher suite (যেমন RC4, পুরনো DES-ভিত্তিক পদ্ধতি) TLS 1.3 থেকে সম্পূর্ণ সরিয়ে দেওয়া হয়েছে — শুধু আধুনিক, শক্তিশালী অ্যালগরিদম সমর্থিত।
মূল কথা · Key takeaway

TLS হ্যান্ডশেক আসলে তিনটি পূর্ববর্তী পাঠের মিলিত ফলাফল — L35-এর hybrid approach, L36-এর ডিজিটাল সিগনেচার (সার্টিফিকেট স্বাক্ষরে), এবং L37-এর ট্রাস্ট চেইন (সার্টিফিকেট যাচাইয়ে) — সবকিছু একত্রে মিলে একটি ব্রাউজার ট্যাব খোলার মুহূর্তে ঘটে যায়, মিলিসেকেন্ডের মধ্যে।

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

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ client_public ও server_public মান দুটো একজন আক্রমণকারী পুরোপুরি দেখতে পারলেও কেন সে shared secret বের করতে পারবে না?

shared secret বের করতে হলে হয় client_secret অথবা server_secret জানা দরকার — কিন্তু শুধু client_public, server_public, $g$ ও $p$ দেখে গোপন সংখ্যা (এক্সপোনেন্ট) বের করা একটি গাণিতিক সমস্যা যাকে বলা হয় discrete logarithm problem। ছোট সংখ্যায় (যেমন এই উদাহরণে) এটি সহজে ব্রুট-ফোর্স করা সম্ভব, কিন্তু বাস্তব TLS-এ ব্যবহৃত শত শত বিটের সংখ্যায় এটি বর্তমান কম্পিউটিং শক্তি দিয়ে কার্যত অসম্ভব — এটাই Diffie-Hellman-এর নিরাপত্তার ভিত্তি।

প্র ০২ ধাপ ২-এ সার্টিফিকেট যাচাই ব্যর্থ হলে (L37-এর ট্রাস্ট চেইন ভাঙলে) কি হ্যান্ডশেক তবুও ধাপ ৩-এ এগিয়ে যাওয়া উচিত?

না। যদি সার্টিফিকেট যাচাই ব্যর্থ হয় (এক্সপায়ার্ড, অজানা CA, বা ডোমেইন-নাম অমিল), ব্রাউজারের এখানেই থেমে যাওয়া উচিত এবং ব্যবহারকারীকে সতর্ক করা উচিত — কারণ পরবর্তী ধাপে (কী এক্সচেঞ্জ) আপনি হয়তো একজন আক্রমণকারীর সাথেই "নিরাপদ" চ্যানেল প্রতিষ্ঠা করছেন এটা না জেনেই। এনক্রিপশন নিজে শক্তিশালী হলেও, যদি আপনি ভুল পক্ষের সাথে এনক্রিপ্ট করছেন, তাহলে গোপনীয়তা কোনো কাজেই আসে না — এটাই কেন পরিচয়-যাচাই (ধাপ ২) কী এক্সচেঞ্জের (ধাপ ৩) আগে ঘটে।

প্র ০৩ TLS 1.3-এ কম রাউন্ড-ট্রিপ লাগা কেন শুধু "দ্রুত" নয়, একটি নিরাপত্তা সুবিধাও হতে পারে?

একটি হ্যান্ডশেক যত বেশি সময় ধরে চলে ("in progress" অবস্থায় থাকে), আক্রমণকারীর জন্য downgrade বা interference-এর সুযোগ তত বেশি থাকে (যদিও TLS 1.3 নিজেই এই ধরনের আক্রমণ প্রতিরোধে ডিজাইন করা)। এছাড়া, TLS 1.3-এ পুরনো দুর্বল cipher suite সম্পূর্ণ বাদ দেওয়ার কারণে হ্যান্ডশেকের সময় ভুলবশত কোনো দুর্বল অ্যালগরিদম বেছে নেওয়ার সম্ভাবনাই থাকে না — গতি ও নিরাপত্তা এখানে একসাথে বেড়েছে, একে অপরের বিনিময়ে নয়।

অনুশীলন

  1. পরীক্ষা করুন: উপরের কোড সেলে client_secret-এর মান 6 থেকে 10-এ পরিবর্তন করুন (server_secret অপরিবর্তিত রেখে) এবং Run চেপে দেখুন shared secret-এর মান বদলায় কি না, কিন্তু দুই পক্ষের হিসাব তবুও মেলে কি না।

    shared secret-এর মান বদলে যাবে (যেহেতু গোপন ইনপুট বদলেছে), কিন্তু shared_client == shared_server তবুও True থাকবে — কারণ গাণিতিক সম্পর্কটি যেকোনো বৈধ গোপন-সংখ্যা জোড়ার জন্যই সত্য, শুধু নির্দিষ্ট এই দুটো সংখ্যার জন্য নয়। এটি দেখায় Diffie-Hellman একটি সাধারণ (general) পদ্ধতি, একটি বিশেষ কেসের কাকতালীয় মিল নয়।

  2. চিন্তা করুন: যদি $p$ (মডুলাস) অনেক ছোট রাখা হয় (যেমন এই উদাহরণে $23$), একজন আক্রমণকারী কীভাবে সম্ভাব্য সব গোপন সংখ্যা ব্রুট-ফোর্স করে shared secret বের করতে পারে? বাস্তব TLS এটা কীভাবে প্রতিরোধ করে?

    যেহেতু $p=23$ ছোট, সম্ভাব্য গোপন সংখ্যার পরিসরও ছোট (0 থেকে 22 পর্যন্ত) — একজন আক্রমণকারী প্রতিটি সম্ভাব্য মান চেষ্টা করে pow(g, guess, p) == client_public মিলিয়ে দেখতে পারে, মাত্র কয়েক মুহূর্তে। বাস্তব TLS এই সমস্যা এড়ায় শত শত বিটের বিশাল $p$ ব্যবহার করে — তখন সম্ভাব্য মানের সংখ্যা এত বিশাল যে ব্রুট-ফোর্স করা মহাবিশ্বের বয়সের চেয়েও বেশি সময় নেবে বর্তমান কম্পিউটিং শক্তিতে (ঠিক L39-এ যা আমরা key-space নিয়ে আলোচনা করব)।

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

আগের পাঠ
PKI ও সার্টিফিকেট — X.509, CA ট্রাস্ট চেইন