#
TLS/SSL Basics: Understanding Secure Web Communication
HTTPS FOUNDATION NETWORK ENCRYPTION ESSENTIAL KNOWLEDGE
Every HTTPS Website Uses This
TLS/SSL is the cryptographic protocol that powers every secure website you visit. Understanding TLS is fundamental to web security - it protects trillions of dollars in transactions daily and billions of users worldwide.
#
What is TLS/SSL?
CORE DEFINITION
Simple Definition: TLS (Transport Layer Security) and its predecessor SSL (Secure Sockets Layer) are cryptographic protocols that provide secure communication over computer networks. When you see the padlock icon and "HTTPS" in your browser, that's TLS in action.
What TLS Does:
- Encrypts data so eavesdroppers can't read it
- Verifies server identity to prevent impersonation
- Detects tampering to ensure data integrity
- Establishes secure keys for the session
Real-World Analogy
Think of TLS like a secure courier service:
- HTTP = Sending a postcard (anyone can read it)
- HTTPS/TLS = Locked, tamper-evident box with verified delivery
- Only sender and recipient have keys to the box
- Courier verifies recipient identity before delivery
- Tamper-evident seal shows if anyone opened it
SSL IS DEPRECATED DON'T USE SSL
SSL is Completely Obsolete
SSL (all versions) is deprecated and insecure! Modern systems use TLS 1.2 or TLS 1.3. The term "SSL" is still commonly used for historical reasons, but always use TLS in practice.
- SSL 2.0 - Broken (DROWN attack)
- SSL 3.0 - Broken (POODLE attack)
- TLS 1.2 - Secure (current standard)
- TLS 1.3 - Most secure (recommended)
#
Why TLS/SSL Matters
CRITICAL SECURITY
Without TLS, the Internet Would Be Unusable
Before widespread TLS adoption, every password, credit card, and private message was visible to anyone on the network. TLS made online banking, shopping, and private communication possible.
#
Without TLS/SSL (HTTP)
INSECURE
Three Critical Vulnerabilities:
Eavesdropping - Anyone on the network can read your data in plain text Tampering - Attackers can modify data in transit without detection Impersonation - No way to verify you're actually talking to the real server
GET /login HTTP/1.1
Host: bank.com
Content-Type: application/x-www-form-urlencoded
username=john&password=secret123
Who Can See This Unencrypted Data?
- :icon-wifi: WiFi hotspot operator - Coffee shop, airport, hotel
- ISP (Internet Service Provider) - Your network provider
- Government agencies - Network monitoring, surveillance
- Hackers on the same network - Packet sniffing attacks
- Anyone between you and the server - Every router, every hop
With HTTP, your password is as visible as this text you're reading now!
#
With TLS/SSL (HTTPS)
SECURE
Three Security Guarantees:
Confidentiality - Data is encrypted with AES-256 or similar Integrity - Detects any tampering with HMAC or AEAD Authentication - Verifies server identity with certificates
16 03 03 00 a5 01 00 00 a1 03 03 5f 4e 8c 3a b2 8d 6f 3c 4a 9e 2f 1b 7d ...
c3 5a 8f 2e 9b 4d 7c 1a 6e 3f 8c 2d 9f 5b 4e 7a 1c 6d 3e 8f 2c 9b ...
Complete Protection
Encrypted gibberish to anyone intercepting!
- Eavesdroppers see only random bytes
- Tampering is immediately detected
- Certificate proves server identity
- Keys change for every session
Even if an attacker records all traffic, they cannot decrypt it without the session keys - which are negotiated securely and never transmitted!
#
TLS/SSL Version History
PROTOCOL EVOLUTION
30 Years of Security Evolution
TLS/SSL has evolved over 30 years, with each version addressing discovered vulnerabilities. This history teaches us that cryptographic protocols must be regularly updated as attacks improve.
#
Evolution of Security Protocols
Only Use TLS 1.2 and TLS 1.3
All SSL versions and TLS 1.0/1.1 are deprecated and insecure!
- SSL 2.0/3.0 - Broken by multiple attacks
- TLS 1.0/1.1 - Banned by PCI-DSS since June 2018
- TLS 1.2 - Minimum for production (properly configured)
- TLS 1.3 - Preferred (faster, more secure, simpler)
Compliance Requirements:
- PCI-DSS 3.2.1: TLS 1.2+ only (credit card processing)
- HIPAA: TLS 1.2+ recommended (healthcare)
- NIST: TLS 1.2+ required for government systems
Major TLS Vulnerabilities Over Time
SSL/TLS has been attacked repeatedly - stay updated!
2014 POODLE - SSL 3.0 padding oracle attack 2014 Heartbleed - OpenSSL bug leaked memory (not protocol flaw) 2016 DROWN - SSL 2.0 cross-protocol attack 2016 SWEET32 - 64-bit block cipher weakness (3DES) 2011 BEAST - TLS 1.0 CBC vulnerability
These attacks drove the deprecation of old versions and the development of TLS 1.3!
#
How TLS/SSL Works
CORE MECHANISMS
Three Pillars of TLS Security
TLS provides three fundamental security guarantees. Remove any one of these and the entire system becomes vulnerable. All three work together to create truly secure communication.
#
The Three Goals of TLS
Goal: Keep data secret from eavesdroppers
How: Symmetric encryption algorithms (AES-256-GCM, ChaCha20-Poly1305)
Plaintext: "Hello, World!"
↓
[Encryption with AES-256-GCM]
↓
Ciphertext: "8f3a9c7e2d1b5a4f9e3c7d2a..."
How It Works
After the initial handshake, TLS uses symmetric encryption (like AES-256) for all data because it's extremely fast. The encryption keys are negotiated during the handshake and change for every session.
Key Point: Only sender and receiver can read the data. Even if an attacker records all traffic, they cannot decrypt it without the session keys.
Real-World Impact:
- Credit card numbers encrypted during purchase
- Passwords hidden when logging in
- Private messages unreadable by ISP
- File uploads/downloads protected
Goal: Detect if data was tampered with during transmission
How: Message Authentication Codes (HMAC) or Authenticated Encryption (AEAD like GCM)
Message: "Transfer $100 to Bob"
↓
MAC: HMAC-SHA256(message, secret_key)
= "a5f9c3e7b2..."
If attacker changes to "Transfer $1000 to Eve":
→ MAC won't match: "a5f9c3e7b2..." ≠ "x7k2m9n4p1..."
→ Tampering detected!
→ Connection terminated immediately
Why Integrity Matters
Without integrity checking, an attacker could modify encrypted data in transit. Even though they can't read it, they could change amounts, flip bits, or inject malicious data. The MAC prevents this!
Key Point: Any modification - even a single bit - will be instantly detected and the connection terminated.
Attacks Prevented:
- Changing transaction amounts
- Injecting malicious code
- Bit-flipping attacks
- Replay attacks (reusing old messages)
Goal: Verify you're talking to the real server, not an imposter
How: Digital certificates signed by trusted Certificate Authorities (CAs)
🌐 Browser: "Prove you're really bank.com"
↓
🏦 Server: "Here's my certificate signed by DigiCert"
↓
🔍 Browser: Checks certificate:
- Is it signed by a trusted CA? ✅ (DigiCert)
- Is it for bank.com domain? ✅
- Is it still valid (not expired)? ✅
- Has it been revoked? ✅ (Check CRL/OCSP)
↓
✅ Browser: "I trust DigiCert, so I trust you're really bank.com"
↓
🔒 Secure connection established
Without Authentication
Without certificate verification, you could be connected to:
- Fake website (phishing)
- Man-in-the-middle attacker
- Malicious proxy server
- Government surveillance
The padlock in your browser means the certificate was verified!
Key Point: Prevents impersonation and man-in-the-middle attacks. You know you're talking to the real server.
Certificate Chain of Trust:
- Root CA (DigiCert, Let's Encrypt) - Trusted by browser
- Intermediate CA - Signs server certificates
- Server Certificate - Proves server identity
#
The TLS Handshake
The TLS handshake is the process of establishing a secure connection. Think of it as a secret handshake before sharing secrets.
#
TLS 1.2 Handshake (Legacy)
Client Server
1. ClientHello
- Supported versions: TLS 1.2
- Cipher suites: [list]
- Random: 28 bytes
────────────────>
2. ServerHello
- Selected cipher suite
- Random: 28 bytes
3. Certificate
- Server's certificate chain
4. ServerKeyExchange
- Key exchange parameters
5. ServerHelloDone
<────────────────
6. ClientKeyExchange
- Client's key exchange data
7. ChangeCipherSpec
8. Finished
- Encrypted handshake verification
────────────────>
9. ChangeCipherSpec
10. Finished
- Encrypted handshake verification
<────────────────
[Application Data - Encrypted Communication]
<══════════════>
Time: 2 round-trips (2-RTT) before data transfer
#
TLS 1.3 Handshake (Modern)
Client Server
1. ClientHello
- Supported versions: TLS 1.3
- Cipher suites: [list]
- Extensions: SNI, ALPN
- Key share (ECDHE public key)
────────────────>
2. ServerHello
- Selected cipher suite
- Key share (ECDHE public key)
{EncryptedExtensions}
{Certificate}
{CertificateVerify}
{Finished}
<────────────────
{Finished}
────────────────>
[Application Data - Encrypted Communication]
<══════════════>
Time: 1 round-trip (1-RTT) before data transfer
TLS 1.3 Improvements:
- 50% faster - Only 1 round-trip
- Encrypted earlier - More of handshake is encrypted
- Simpler - Removed weak algorithms
- Always forward secrecy - Ephemeral keys required
For resuming previous connections:
Client Server
ClientHello
+ EarlyData (Application Data!)
──────────────────>
ServerHello
{EncryptedExtensions}
{Finished}
<──────────────────
{Finished}
──────────────────>
[More Application Data]
Benefits:
- Zero latency - Instant data transmission
- Perfect for APIs and mobile apps
Risks:
- Replay attacks - 0-RTT data can be replayed
- Not idempotent - Only use for safe operations (GET, not POST)
Recommendation: Disable 0-RTT unless you understand the risks.
#
Detailed Handshake Messages
#
ClientHello
The client starts the handshake by sending supported options:
{
"version": "TLS 1.3",
"random": "28 bytes of random data",
"session_id": "for session resumption",
"cipher_suites": [
"TLS_AES_256_GCM_SHA384",
"TLS_CHACHA20_POLY1305_SHA256",
"TLS_AES_128_GCM_SHA256"
],
"compression_methods": [0], // No compression (CRIME attack)
"extensions": {
"server_name": "example.com", // SNI
"supported_groups": ["x25519", "secp256r1"],
"signature_algorithms": ["rsa_pss_rsae_sha256", "ecdsa_secp256r1_sha256"],
"key_share": {
"group": "x25519",
"public_key": "client's ephemeral public key"
}
}
}
#
ServerHello
The server responds with selected options:
{
"version": "TLS 1.3",
"random": "28 bytes of random data",
"session_id": "echo from ClientHello",
"cipher_suite": "TLS_AES_256_GCM_SHA384",
"compression_method": 0,
"extensions": {
"key_share": {
"group": "x25519",
"public_key": "server's ephemeral public key"
}
}
}
#
Certificate
Server sends its certificate chain:
{
"certificates": [
{
"certificate": "--- Leaf Certificate (example.com) ---",
"extensions": {
"status_request": "OCSP staple (optional)"
}
},
{
"certificate": "--- Intermediate Certificate ---"
}
// Root certificate not included (already trusted)
]
}
#
CertificateVerify
Server proves it owns the private key:
{
"algorithm": "rsa_pss_rsae_sha256",
"signature": "Digital signature over handshake transcript"
}
Verification:
1. Client has server's public key (from certificate)
2. Client verifies signature using public key
3. Signature valid → Server owns private key ✓
#
Finished
Both parties send Finished message:
{
"verify_data": "HMAC over entire handshake transcript"
}
Purpose: Ensures handshake wasn't tampered with.
#
Key Generation
After the handshake, both parties derive symmetric encryption keys:
#
Key Derivation Process
Pre-Shared Key (PSK) or 0
|
v
Extract (HKDF-Extract)
|
v
Early Secret
|
+-----> Derive Early Traffic Keys (0-RTT)
|
(Derive more secrets)
|
v
Handshake Secret
|
+-----> Client Handshake Traffic Secret
+-----> Server Handshake Traffic Secret
|
(Derive more secrets)
|
v
Master Secret
|
+-----> Client Application Traffic Secret
+-----> Server Application Traffic Secret
+-----> Resumption Master Secret
# After ECDHE key exchange
shared_secret = ecdhe_compute_shared(client_private, server_public)
# Extract
early_secret = HKDF_Extract(salt=0, ikm=PSK or 0)
# Derive handshake secret
handshake_secret = HKDF_Extract(
salt=derive_secret(early_secret, "derived"),
ikm=shared_secret
)
# Derive traffic keys
client_handshake_key = HKDF_Expand_Label(
handshake_secret,
"c hs traffic",
ClientHello...ServerHello,
key_length
)
server_handshake_key = HKDF_Expand_Label(
handshake_secret,
"s hs traffic",
ClientHello...ServerHello,
key_length
)
# Derive application traffic keys
master_secret = HKDF_Extract(
salt=derive_secret(handshake_secret, "derived"),
ikm=0
)
client_app_key = HKDF_Expand_Label(
master_secret,
"c ap traffic",
ClientHello...ServerFinished,
key_length
)
server_app_key = HKDF_Expand_Label(
master_secret,
"s ap traffic",
ClientHello...ServerFinished,
key_length
)
#
Multiple Keys for Different Purposes
Why multiple keys?
Benefits:
- Separation - Compromise of one key doesn't affect others
- Independence - Each direction uses different keys
- Nonce uniqueness - IVs ensure no key reuse
#
Session Resumption
Problem: Full handshake is expensive (CPU + latency)
Solution: Resume previous sessions without full handshake
#
Session IDs (TLS 1.2)
First Connection:
Client → Server: ClientHello (session_id = empty)
Server → Client: ServerHello (session_id = 1234)
[Full handshake]
Server stores session 1234 with master secret
Resumed Connection:
Client → Server: ClientHello (session_id = 1234)
Server finds session 1234 in cache
Server → Client: ServerHello (session_id = 1234)
ChangeCipherSpec
Finished
[Skip certificate exchange, use cached master secret]
Benefit: Saves 1 round-trip and CPU (no public key crypto)
#
Session Tickets (TLS 1.2 & 1.3)
First Connection:
Client → Server: ClientHello
Server → Client: ServerHello
[Full handshake]
NewSessionTicket
(Encrypted session state)
Client stores encrypted ticket
Resumed Connection:
Client → Server: ClientHello
+ Encrypted ticket
Server decrypts ticket, retrieves session state
Server → Client: ServerHello
[Abbreviated handshake]
Benefits:
- Stateless - Server doesn't store sessions
- Scalable - No session cache coordination
- Encrypted - Ticket is encrypted with server's key
Security Note: Rotate ticket encryption keys regularly!
#
PSK (Pre-Shared Key) Resumption - TLS 1.3
Client → Server: ClientHello
+ PSK identity
+ PSK binder (proves PSK knowledge)
Server → Client: ServerHello
+ Selected PSK
[Skip certificate, use PSK as master secret]
Even faster than session tickets!
#
Basic TLS Implementation
#
Client Example
import ssl
import socket
# Create SSL context
context = ssl.create_default_context()
# Optional: Verify certificate
context.check_hostname = True
context.verify_mode = ssl.CERT_REQUIRED
# Connect to server
with socket.create_connection(('example.com', 443)) as sock:
with context.wrap_socket(sock, server_hostname='example.com') as ssock:
# Print connection info
print(f"TLS Version: {ssock.version()}")
print(f"Cipher: {ssock.cipher()}")
# Get certificate
cert = ssock.getpeercert()
print(f"Server: {cert['subject']}")
# Send HTTP request
ssock.sendall(b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")
# Receive response
response = ssock.recv(4096)
print(response.decode())
const tls = require('tls');
const fs = require('fs');
const options = {
host: 'example.com',
port: 443,
// Verify certificate
rejectUnauthorized: true,
// Optional: Custom CA
ca: fs.readFileSync('ca-cert.pem'),
};
const socket = tls.connect(options, () => {
console.log('Connected');
console.log('TLS Version:', socket.getProtocol());
console.log('Cipher:', socket.getCipher());
// Verify certificate
if (!socket.authorized) {
console.error('Certificate not authorized:', socket.authorizationError);
}
// Send data
socket.write('GET / HTTP/1.1\r\nHost: example.com\r\n\r\n');
});
socket.on('data', (data) => {
console.log(data.toString());
});
socket.on('end', () => {
console.log('Disconnected');
});
import javax.net.ssl.*;
import java.io.*;
public class TLSClient {
public static void main(String[] args) throws Exception {
// Create SSL context
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, null, null);
// Create socket factory
SSLSocketFactory factory = sslContext.getSocketFactory();
// Connect to server
try (SSLSocket socket = (SSLSocket) factory.createSocket("example.com", 443)) {
// Print connection info
SSLSession session = socket.getSession();
System.out.println("Protocol: " + session.getProtocol());
System.out.println("Cipher: " + session.getCipherSuite());
// Send HTTP request
PrintWriter out = new PrintWriter(socket.getOutputStream());
out.println("GET / HTTP/1.1");
out.println("Host: example.com");
out.println();
out.flush();
// Read response
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream())
);
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
}
}
}
#
Server Example
import ssl
import socket
# Create SSL context
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
# Load certificate and private key
context.load_cert_chain('cert.pem', 'key.pem')
# Optional: Set TLS version
context.minimum_version = ssl.TLSVersion.TLSv1_2
context.maximum_version = ssl.TLSVersion.TLSv1_3
# Optional: Set cipher suites
context.set_ciphers('ECDHE+AESGCM:ECDHE+CHACHA20')
# Create socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.bind(('0.0.0.0', 443))
sock.listen(5)
print("TLS Server listening on port 443...")
while True:
conn, addr = sock.accept()
with context.wrap_socket(conn, server_side=True) as ssock:
print(f"Connection from {addr}")
print(f"TLS Version: {ssock.version()}")
print(f"Cipher: {ssock.cipher()}")
# Receive data
data = ssock.recv(1024)
print(f"Received: {data.decode()}")
# Send response
response = b"HTTP/1.1 200 OK\r\n\r\nHello from TLS server!"
ssock.sendall(response)
const tls = require('tls');
const fs = require('fs');
const options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem'),
// Optional: Certificate chain
ca: fs.readFileSync('chain.pem'),
// TLS versions
minVersion: 'TLSv1.2',
maxVersion: 'TLSv1.3',
// Cipher suites
ciphers: 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384',
// Client certificate (optional)
requestCert: false,
rejectUnauthorized: false
};
const server = tls.createServer(options, (socket) => {
console.log('Client connected');
console.log('TLS Version:', socket.getProtocol());
console.log('Cipher:', socket.getCipher());
socket.on('data', (data) => {
console.log('Received:', data.toString());
socket.write('HTTP/1.1 200 OK\r\n\r\nHello from TLS server!');
});
socket.on('end', () => {
console.log('Client disconnected');
});
});
server.listen(443, () => {
console.log('TLS Server listening on port 443');
});
#
Quick Reference
#
TLS Versions
NEVER USE
- SSL 2.0, SSL 3.0
- TLS 1.0, TLS 1.1
USE THESE
- TLS 1.2 (with strong ciphers)
- TLS 1.3 (recommended)
#
Handshake Speed
#
Key Algorithms
Recommended:
- ECDHE (Ephemeral Diffie-Hellman with Elliptic Curves)
- AES-GCM (256-bit or 128-bit)
- ChaCha20-Poly1305
Avoid:
- RSA key exchange
- RC4, 3DES
- MD5, SHA1
#
Next Steps
#
Related Topics
HSTS - HTTP Strict Transport Security Certificate Chain of Trust - Understanding PKI SNI (Server Name Indication) - Multiple HTTPS sites on one IP Certificate Revocation - CRL and OCSP Forward Secrecy - Perfect Forward Secrecy Cipher Suites - Understanding encryption recipes
#
Learning Resources
Books:
- "Bulletproof SSL and TLS" by Ivan Ristić
- "Network Security with OpenSSL" by Viega, Messier & Chandra
Tools:
#
Protected by Layerd AI
Layerd AI Guardian Proxy provides comprehensive TLS/SSL security:
TLS Enforcement - Blocks non-HTTPS connections Version Control - Blocks outdated protocols (TLS 1.0, 1.1) Certificate Validation - Verifies certificate chains Real-time Monitoring - Alerts on certificate expiry
Learn more about Layerd AI Protection →
Last updated: November 2025