Security13 min readJun 2026 Last verified Jun 2026
HTTPS, TLS & Encryption Basics
Base64 is not encryption, and you must never encrypt a password. A from-scratch tour of TLS, certificates, symmetric vs asymmetric keys, and the difference between hashing, encryption, and encoding every engineer needs.
Encoding, hashing, and encryption are three different things, and mixing them up breaks security. Understand the TLS handshake, certificates, and symmetric vs asymmetric keys, and why you always hash passwords and never encrypt them.
01Base64 is not encryption
A junior engineer once shipped a feature that stored API tokens "encrypted" in a database column. Code review looked clean. Then someone pasted one value into an online decoder, hit a button, and the raw token appeared in plain text. The "encryption" was Base64, a format that anyone can reverse in one click, with no key, no secret, nothing. The data had never been protected at all.
This mistake is everywhere, and it comes from blurring three words that sound similar but do completely different jobs: encoding, encryption, and hashing. Get them confused and you ship things that *look* secure and protect nothing. This article untangles them, then walks through how HTTPS actually protects data on the wire with TLS.
Who this is for
Engineers who use HTTPS every day but have never seen what happens during the handshake, and anyone who has ever wondered whether they should encrypt a password (you should not). No cryptography background needed; if you can read a function, you can follow this.
02A postcard versus a sealed envelope
Encryption turns readable data into unreadable data using a key, such that only someone with the right key can turn it back. Without encryption in transit, every byte you send is a postcard.
Plain HTTP is a postcard. Every router, Wi-Fi access point, and ISP between you and the server can read, and rewrite, everything: the page you requested, the form you submitted, the session cookie that proves who you are. Nothing stops a coffee-shop attacker from copying it as it passes.
HTTPS is a sealed, tamper-evident envelope. TLS (Transport Layer Security, the protocol behind the "S") does three things at once: it encrypts the contents so onlookers see scrambled bytes, it authenticates the server so you know you are really talking to your bank and not an impostor, and it provides integrity so any tampering en route is detected and the connection is dropped.
Sealed envelope nobody can read throughEncryption, contents are unreadable in transit
Return address you trust and can verifyAuthentication, the certificate proves server identity
Tamper-evident seal that shows if openedIntegrity, any modification breaks the connection
A postcard anyone in the mail chain can readPlain HTTP, every hop sees and can alter the data
Three properties of a sealed envelope map directly to the three guarantees of TLS.
03What happens when you connect (the TLS handshake)
Before any real data flows, the client and server run a short negotiation called the handshake. Its job is to verify the server's identity and agree on a shared secret key, all over an untrusted network where an attacker may be listening. Here is the flow at a high level.
A TLS connection: the client verifies the certificate, both sides exchange keys, then all traffic flows through an encrypted channel.
1
ClientHello
The browser opens with the TLS versions and cipher suites it supports, plus a random value. This is the menu of cryptography it is willing to use.
2
ServerHello + Certificate
The server picks a cipher suite and sends back its certificate, a signed document containing its public key and domain name.
3
Verify the certificate
The browser checks the certificate is for the right domain, not expired, and signed by a Certificate Authority it already trusts. If any check fails, you get the scary red warning page.
4
Key exchange
Using the server's public key (asymmetric crypto), both sides securely agree on the same secret session key. Modern TLS uses ephemeral exchange so each session gets a fresh key.
5
Switch to the session key
From here on, both sides encrypt with that one shared symmetric key, fast, and impossible to read without it.
6
Encrypted application data
Your actual HTTP request and the server's response now travel through the sealed channel. The handshake is done in a few milliseconds.
04Certificates and Certificate Authorities
Encryption alone is not enough, you also need to know *who* you are encrypting to. A certificate is the server's identity document: it binds a domain name to a public key and is digitally signed by a Certificate Authority (CA), an organization your operating system and browser already trust out of the box.
When the browser verifies a certificate, it follows the chain of trust: the site's cert is signed by an intermediate CA, which is signed by a root CA whose public key ships inside your device. If the chain leads back to a trusted root and nothing is expired or mismatched, the identity is accepted. A self-signed certificate has no such chain, which is why browsers reject it for public sites.
Free, automated certs
There is no excuse for plain HTTP anymore. Let's Encrypt issues trusted certificates for free and tools like Certbot renew them automatically. HTTPS everywhere is the baseline, not a premium feature.
05Symmetric vs asymmetric keys
TLS uses two kinds of cryptography, and the handshake is clever precisely because it combines them. Symmetric encryption uses one shared key for both locking and unlocking, it is fast, but both sides must somehow already share the secret. Asymmetric encryption uses a key pair: a public key anyone can use to encrypt, and a matching private key only the owner holds to decrypt.
Asymmetric crypto solves the chicken-and-egg problem of "how do we share a secret over a network we do not trust?", but it is slow. So TLS uses asymmetric crypto *once* during the handshake to safely agree on a symmetric session key, then uses the fast symmetric key for all the actual data. Best of both worlds: secure setup, fast transfer.
06Hashing vs encryption vs encoding
This is the table to memorize. Three operations, three completely different purposes. The single most common security bug in junior code is reaching for the wrong one.
Purpose
Reversible?
Use case
Encoding
Represent data in a format for safe transport or storage
Yes, no key needed, anyone can reverse it
Base64 in a data URL, URL-encoding, UTF-8. Not security at all.
Encryption
Keep data confidential from anyone without the key
Yes, but only with the correct key
TLS in transit, encrypting a database or secrets at rest.
Hashing
Produce a fixed, irreversible fingerprint of data
No, one-way by design
Storing passwords, verifying file integrity, digital signatures.
Same input, very different guarantees. Reversibility is the dividing line.
Read the middle column slowly. Encoding is reversible by anyone, it is a format, not a lock, so it provides *zero* confidentiality. Encryption is reversible only with the key, so it protects data you need to read back later. Hashing is *not reversible at all*, which is exactly why it is the right tool for passwords.
07Why you hash passwords and never encrypt them
You never need to recover a user's original password, you only need to check that the password they typed at login matches the one they set. That is a comparison, not a retrieval, which is precisely what a one-way hash gives you. If you *encrypted* passwords instead, the key that decrypts them exists somewhere, and the day your database leaks alongside that key, every password is exposed in plain text.
But a plain hash is not enough either. Two users with the same password would get the same hash, and attackers precompute huge "rainbow tables" of common passwords. The fix is a salt, a unique random value mixed into each password before hashing, plus a deliberately *slow* algorithm so brute-forcing is expensive. Use a purpose-built password hash like bcrypt, scrypt, or Argon2; never a fast general hash like MD5 or SHA-1.
passwords.py
python
import bcrypt
defhash_password(plaintext: str) -> bytes:
# bcrypt generates a random salt and embeds it in the output.# The work factor (rounds) makes each hash deliberately slow.
salt = bcrypt.gensalt(rounds=12)
return bcrypt.hashpw(plaintext.encode("utf-8"), salt)
defverify_password(plaintext: str, stored_hash: bytes) -> bool:
# We never decrypt anything. We hash the input the same way# and compare. bcrypt reads the salt back out of stored_hash.return bcrypt.checkpw(plaintext.encode("utf-8"), stored_hash)
# Sign-up: store ONLY the hash, never the plaintext.
stored = hash_password("correct horse battery staple")
# Login: compare, do not retrieve.print(verify_password("correct horse battery staple", stored)) # Trueprint(verify_password("wrong password", stored)) # False
There is no decrypt() here on purpose
Notice the code never recovers the original password. If you ever find yourself wanting a function that returns a user's password in plain text, stop, you are about to build the breach.
08In transit vs at rest
Encryption protects data in two different states, and you need both. In transit means data moving across a network, protected by TLS, the encrypted channel from the handshake above. At rest means data sitting in storage: a database, a disk, an S3 bucket, a backup, protected by encrypting the storage itself, so a stolen drive or leaked snapshot is unreadable.
They cover different threats. TLS does nothing for a backup file someone copies off your server; disk encryption does nothing for a token sniffed on open Wi-Fi. A secure system encrypts in transit *and* at rest. For protecting whole APIs end to end, see our companion piece on Secure API Design.
09Common mistakes that cost hours (or breaches)
1Treating encoding as encryption. Base64 and hex are formats, not locks. If there is no key, there is no protection, anyone can decode it instantly.
2Encrypting passwords instead of hashing them. Reversible storage means a leaked key exposes every password. Hash with bcrypt, scrypt, or Argon2 and a per-user salt.
3Using fast hashes for passwords. MD5 and SHA-1 are built for speed, which is exactly what an attacker wants. Use a slow, salted password hash.
4Allowing weak or old TLS. SSL, TLS 1.0, and TLS 1.1 are deprecated and exploitable. Require TLS 1.2 or 1.3 and modern cipher suites only.
5Self-signed certificates in production. They break the chain of trust and train users to click through warnings. Use a real CA, Let's Encrypt is free.
6Disabling certificate verification to "make it work." Turning off validation in an HTTP client silently removes the authentication guarantee and invites man-in-the-middle attacks.
10Takeaways
The whole article in seven lines
HTTPS = HTTP inside TLS, which gives you encryption, server authentication, and integrity.
The TLS handshake verifies a certificate, then agrees on a shared key over an untrusted network.
Certificates bind a domain to a public key and are trusted via a CA chain back to a root your device already trusts.
Asymmetric keys set up the connection securely; the fast symmetric session key carries the actual data.
Encoding is reversible by anyone (a format), encryption is reversible with a key, hashing is one-way.
Hash passwords with a salt and a slow algorithm (bcrypt/scrypt/Argon2), never encrypt them.
Encrypt data both in transit (TLS) and at rest (storage), they defend against different threats.
11Where to go next
Encryption basics are the foundation of nearly every security topic above them. From here, build outward into how you design protected systems and networks.
Secure API Design, apply these primitives to authentication, authorization, and protecting endpoints end to end.
You have a value to protect and are unsure whether to encode, encrypt, or hash it. Which do you reach for?
Check your understanding
1. An engineer stores tokens 'encrypted' but they turn out to be Base64. What mistake does this illustrate?
2. What three things does TLS do at once when it secures a connection?
Frequently asked questions
Why is Base64 not encryption?
Base64 is an encoding, a format anyone can reverse in one click with no key and no secret. Data stored in Base64 has never been protected, even though it looks scrambled at a glance.
What is the difference between encoding, encryption, and hashing?
Encoding just changes the format and is freely reversible. Encryption turns readable data into unreadable data using a key, and only someone with the right key can reverse it. Hashing is a one-way transformation that cannot be reversed back to the original.
Why should you hash passwords instead of encrypting them?
You never need to recover the original password, you only need to check whether a login attempt matches, so a one-way hash is the right tool. Encryption is reversible, which means anyone who obtains the key can recover every password, making it the wrong choice for storing them.
What does the TLS handshake actually accomplish?
Before any real data flows, the client and server run a short negotiation that verifies the server's identity and agrees on a shared secret key over an untrusted network. This is what lets TLS encrypt the contents, authenticate the server, and detect any tampering in transit.
Was this article helpful?
Want to go deeper?
This article covers concepts taught hands-on in the Cloud Engineer and DevOps career paths, with real terminal labs, production scenarios, and structured lessons.