Skip to main content

Command Palette

Search for a command to run...

Understanding SSL/TLS: The Complete Developer's Guide

Updated
9 min read
Understanding SSL/TLS: The Complete Developer's Guide
D

Heya! 👋 I love helping people, and one of the best ways I do this is by sharing my knowledge and experiences. My journey reflects the power of growth and transformation, and I’m here to document and share it with you.

I started as a pharmacist, practicing at a tertiary hospital in the Northern Region of Ghana. There, I saw firsthand the challenges in healthcare delivery and became fascinated by how technology could offer solutions. This sparked my interest in digital health, a field I believe holds the key to revolutionizing healthcare.

Determined to contribute, I taught myself programming, mastering tools like HTML, CSS, JavaScript, React, PHP, and more. But I craved deeper knowledge and practical experience. That’s when I joined the ALX Software Engineering program, which became a turning point. Spending over 70 hours a week learning, coding, and collaborating, I transitioned fully into tech.

Today, I am a Software Engineer and Digital Health Solutions Architect, building and contributing to innovative digital health solutions. I combine my healthcare expertise with technical skills to create impactful tools that solve real-world problems in health delivery.

Imposter syndrome has been part of my journey, but I’ve learned to embrace it as a sign of growth. Livestreaming my learning process, receiving feedback, and building in public have been crucial in overcoming self-doubt. Each experience has strengthened my belief in showing up, staying consistent, and growing through challenges.

Through this platform, I document my lessons, challenges, and successes to inspire and guide others—whether you’re transitioning careers, exploring digital health, or diving into software development.

I believe in accountability and the value of shared growth. Your feedback keeps me grounded and motivated to continue this journey. Let’s connect, learn, and grow together! 🚀

I was today years old when I learned that SSL is obsolete.

For the longest time, I knew you needed an SSL certificate to make your website "secure." I understood the basic idea: data between your browser and server gets encrypted. But I never actually understood how it worked until I started setting up an AWS ALB and became curious about what happens under the hood.

When I started writing down my questions, I realized how much I didn't know. If you're like me, this post will fill that gap.

What You'll Learn

By the end of this post, you'll understand:

  • Why you see that lock icon in your browser (and when)

  • What actually happens during a TLS handshake

  • How encryption and decryption really work

  • Why HTTPS is considered secure despite being used over the public internet

  • How to actually set up TLS on your own infrastructure

Let's start with what you see every day.

The Lock Icon Mystery

Every time you visit an HTTPS website, your browser shows a lock icon. But here's the question most developers never ask: at what point does the browser decide "this is secure"?

Most people assume it's after the server responds. It's not.

The browser makes this decision before sending any request to the server. In fact, before your application code even runs.

Here's what actually happens when you type https://example.com into your browser:

  1. Browser resolves the DNS name to an IP address

  2. Browser connects to the server on port 443 (the HTTPS port)

  3. Browser and server perform a TLS handshake

  4. Browser checks if the certificate is valid

  5. Only if all checks pass does the lock icon appear and the request gets encrypted

If the certificate is invalid or expired, the browser stops. It shows a warning. The request never reaches your server.

This is important: TLS security happens at the transport layer, before your code touches it.

The TLS Handshake: What's Actually Happening

The TLS handshake is a conversation between your browser and the server. Its job is to agree on how to encrypt the conversation that follows.

Step 1: The Browser Says Hello

The browser sends a message to the server that essentially says:

"Hi, I want to communicate securely. Here are the encryption methods I support."

This message includes things like TLS version (1.2, 1.3, etc.) and encryption algorithms (like AES, ChaCha20).

Step 2: The Server Responds with Its Certificate

The server sends back:

"Great. Here's my certificate proving I own this domain. And here's the encryption method I've chosen from your list."

The certificate is crucial. It's a signed document that says "this server is legitimately example.com" and it's signed by a trusted authority.

Step 3: The Browser Verifies the Certificate

This is where the security actually comes from.

The browser checks:

  • Does the domain name in the certificate match the domain you're visiting?

  • Is the certificate signed by a trusted Certificate Authority (CA)?

  • Has the certificate expired?

  • Has the certificate been revoked?

If any of these checks fail, the browser stops. It doesn't show the lock icon. It doesn't send the request.

If all checks pass, the browser continues.

Step 4: Key Exchange

Now something clever happens. The browser and server agree on a shared secret without actually sending that secret over the network.

This is asymmetric cryptography in action. The server's certificate includes a public key. The browser uses this public key to encrypt a secret value and sends it to the server. Only the server can decrypt it because only the server has the corresponding private key.

Now both the browser and server have this shared secret.

Step 5: Switching to Symmetric Encryption

From this point forward, all data is encrypted using the shared secret with a fast symmetric algorithm like AES.

Why both? Asymmetric crypto (the public/private key stuff) is slow. It's only used to establish trust and exchange the secret. Once they have a shared secret, they use symmetric encryption because it's blazingly fast.

This is why HTTPS is both secure and performant.

Why This is Secure

At this point, you might ask: what stops someone from intercepting the traffic and decrypting it?

Three things work together:

Confidentiality: The data is encrypted with a key that only the browser and server know. Even if someone intercepts the traffic, they see random bytes. Without the key, the data is useless.

Integrity: The encrypted data includes a code that detects tampering. If even one byte is modified, the code doesn't match and the recipient knows the data was altered.

Authentication: The certificate proves the server is who it claims to be. You're not just encrypting to a stranger on the internet. You're encrypting to someone whose identity has been verified.

Breaking all three would require stealing the server's private key, breaking modern cryptography (impossible with current math), or tricking the browser into trusting a fake certificate.

All three are very hard.

What About Man-in-the-Middle Attacks?

They can happen. But they don't work the way most people think.

A true MITM attack doesn't break the cryptography. It breaks trust.

Here's how a real MITM attack succeeds:

Scenario 1: Compromised Certificate Authority A CA issues a fraudulent certificate for example.com. The attacker has a valid certificate signed by someone the browser trusts. The browser sees it as legitimate and trusts it. MITM succeeds.

(This is rare but has happened historically.)

Scenario 2: User Installs Malicious Root Certificate On a corporate network or malware-infected machine, the user's browser is told to trust a certificate from the company or attacker. Now any certificate signed by that root is trusted. MITM succeeds.

Scenario 3: User Ignores Browser Warnings Browser says "this certificate is invalid, proceed anyway?" User clicks yes. MITM succeeds.

Scenario 4: DNS Poisoning + Trust Abuse Attacker redirects traffic to their server and presents a certificate they control. If the browser trusts it (Scenarios 1-2), MITM succeeds.

What MITM cannot do: decrypt valid HTTPS traffic by just listening on the network. The crypto is sound. The attack works by manipulating trust, not breaking encryption.

Now Let's Make It Real: The EC2 + NGINX Setup

Theory is good. But how does this actually work when you're running a server?

Let's say you have an EC2 instance running NGINX as a reverse proxy. Your setup looks like:

Browser (client)
    ↓ HTTPS (encrypted)
NGINX on EC2 (reverse proxy)
    ↓ HTTP or HTTPS
Backend service

Here's what happens:

  1. Browser connects to NGINX on port 443

  2. TLS handshake happens between browser and NGINX

  3. Browser and NGINX agree on encryption method and shared secret

  4. Browser sends encrypted request to NGINX

  5. NGINX decrypts the request using the shared secret

  6. NGINX now sees plain HTTP data and can route it forward

  7. NGINX may forward to backend as HTTP or create a new encrypted connection

This decryption step is called TLS termination. The encrypted connection ends at NGINX. The name comes from the fact that TLS is being terminated (ended) at that point.

But here's the key question: how does NGINX know how to decrypt the data?

How NGINX Actually Decrypts

NGINX doesn't invent cryptography. It uses OpenSSL, a battle-tested cryptography library.

You configure NGINX with two files:

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

The certificate (.crt or .pem) is the public part. It proves your identity.

The private key (.key) is the secret. Only your server has it. This key is what allows NGINX to:

  • Prove it's legitimate when browsers connect

  • Decrypt the secrets sent by browsers during the handshake

The private key never leaves your server. If someone steals it, they can impersonate your server. This is why it's called "private."

During the TLS handshake, when the browser encrypts a secret using your public key, only NGINX (with the private key) can decrypt it. This is how the shared secret is established securely.

Once established, NGINX uses that shared secret to decrypt all incoming requests.

Getting the Certificate: Certbot and Let's Encrypt

Now you need these files. Where do they come from?

This is where Certbot enters the picture.

Certbot is a tool that automates three things:

1. Proving You Own the Domain Certbot contacts Let's Encrypt and says "I want a certificate for example.com." Let's Encrypt says "prove it." Certbot does this by creating a file at a specific URL on your domain. Let's Encrypt accesses that URL. If it finds the file, you own the domain.

(There are other methods too, like DNS challenges, but the idea is the same: prove ownership without a human involved.)

2. Getting a Signed Certificate Once Let's Encrypt verifies ownership, it creates a certificate and signs it with their private key. This signature proves that Let's Encrypt (a trusted authority) verified your domain.

3. Installing the Files Certbot takes the certificate and generates a private key, then installs both to a directory on your server (usually /etc/letsencrypt/live/yourdomain/).

Certbot also sets up automatic renewal. Certificates expire (typically after 90 days), so Certbot automatically renews them before expiration.

When you add these lines to your NGINX config:

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

You're telling NGINX where to find these files. NGINX loads them into memory when it starts. When a browser connects, NGINX uses the certificate to prove its identity and the private key to decrypt the browser's secrets.

Putting It All Together

When you type https://example.com into your browser:

  1. Browser resolves DNS

  2. Browser connects to your EC2 instance on port 443

  3. TLS handshake begins

  4. Your NGINX has the certificate (from Certbot/Let's Encrypt) and private key

  5. Browser verifies the certificate is valid and signed by a trusted CA

  6. Browser and NGINX exchange secrets using public/private key crypto

  7. They agree on a shared secret for symmetric encryption

  8. Lock icon appears in browser

  9. All subsequent data is encrypted with that shared secret

  10. NGINX decrypts incoming requests

  11. NGINX routes decrypted requests to your backend

The entire flow from step 2 to step 8 happens in milliseconds. The browser does all this before your application code runs.

This is why HTTPS is secure. The encryption happens at the transport layer, independent of your application logic. A misconfigured API won't accidentally expose encrypted data because it never sees the encrypted data in the first place.

A Few Final Insights

Why is it called SSL if we use TLS? SSL is the old name. It's obsolete and has known vulnerabilities. TLS replaced it. But the terminology stuck. When people say "enable SSL," they mean TLS. When configuration files say ssl_, they're actually doing TLS. It's a historical quirk.

Why does the browser check the certificate before sending anything? Because if the certificate is invalid, there's no one to trust. Sending encrypted data to the wrong person is pointless. The browser validates first to ensure it's actually talking to the real server.

Why is the private key so sensitive? If someone has your private key, they can impersonate your server. They can decrypt traffic meant for your domain. They can forge certificates. The private key is the crown jewel of your infrastructure.

What if you're inside a private network? HTTPS still matters. Internal networks are not automatically safe. Malicious employees, compromised machines, and network-level attacks happen. HTTPS protects you even inside your own infrastructure.


Before I learned this, TLS felt like magic. Now it feels like a well-designed system that solves a genuinely hard problem.

The next time you see a lock icon, you'll know exactly what happened in those invisible milliseconds.

More from this blog

D

Dr. Ehoneah Obed

75 posts

Software engineer writing about systems: in code, in learning, in life. I reverse-engineer complex problems into frameworks. Pharmacist → SWE → Founder.