1"""
2TLS and Certificate Demo
3=========================
4
5Educational demonstration of TLS/SSL concepts:
6- Certificate parsing from a live server
7- TLS connection information display
8- Self-signed certificate generation commands
9- Certificate chain verification concepts
10
11Uses only Python standard library (ssl, socket).
12No external dependencies required.
13
14Note: Requires internet connection for live server examples.
15"""
16
17import ssl
18import socket
19import datetime
20import textwrap
21import hashlib
22
23print("=" * 65)
24print(" TLS and Certificate Demo")
25print("=" * 65)
26print()
27
28
29# ============================================================
30# Section 1: TLS Connection to a Live Server
31# ============================================================
32
33print("-" * 65)
34print(" Section 1: TLS Connection Information")
35print("-" * 65)
36
37hostname = "www.google.com"
38port = 443
39
40print(f"\n Connecting to {hostname}:{port}...")
41print()
42
43try:
44 context = ssl.create_default_context()
45
46 with socket.create_connection((hostname, port), timeout=5) as sock:
47 with context.wrap_socket(sock, server_hostname=hostname) as tls_sock:
48 # Connection info
49 print(f" TLS Version: {tls_sock.version()}")
50 print(f" Cipher Suite: {tls_sock.cipher()[0]}")
51 print(f" Cipher Bits: {tls_sock.cipher()[2]}")
52 print()
53
54 # Certificate info
55 cert = tls_sock.getpeercert()
56
57 # Subject
58 subject = dict(x[0] for x in cert.get("subject", ()))
59 print(f" Subject:")
60 for key, value in subject.items():
61 print(f" {key}: {value}")
62
63 # Issuer
64 issuer = dict(x[0] for x in cert.get("issuer", ()))
65 print(f"\n Issuer:")
66 for key, value in issuer.items():
67 print(f" {key}: {value}")
68
69 # Validity period
70 not_before = cert.get("notBefore", "N/A")
71 not_after = cert.get("notAfter", "N/A")
72 print(f"\n Valid From: {not_before}")
73 print(f" Valid Until: {not_after}")
74
75 # Serial number
76 serial = cert.get("serialNumber", "N/A")
77 print(f" Serial Number: {serial}")
78
79 # Subject Alternative Names
80 sans = cert.get("subjectAltName", ())
81 if sans:
82 san_list = [v for _, v in sans[:5]]
83 print(f"\n Subject Alt Names ({len(sans)} total):")
84 for san in san_list:
85 print(f" - {san}")
86 if len(sans) > 5:
87 print(f" ... and {len(sans) - 5} more")
88
89 # DER-encoded certificate for fingerprint
90 der_cert = tls_sock.getpeercert(binary_form=True)
91 sha256_fp = hashlib.sha256(der_cert).hexdigest()
92 sha1_fp = hashlib.sha1(der_cert).hexdigest()
93 print(f"\n SHA-256 Fingerprint:")
94 print(f" {':'.join(sha256_fp[i:i+2] for i in range(0, 32, 2))}...")
95 print(f" SHA-1 Fingerprint:")
96 print(f" {':'.join(sha1_fp[i:i+2] for i in range(0, len(sha1_fp), 2))}")
97
98except socket.timeout:
99 print(" Connection timed out. Skipping live server demo.")
100except Exception as e:
101 print(f" Connection failed: {e}")
102 print(" (This section requires internet access)")
103
104print()
105
106
107# ============================================================
108# Section 2: TLS Protocol Details
109# ============================================================
110
111print("-" * 65)
112print(" Section 2: TLS Protocol & Supported Configurations")
113print("-" * 65)
114
115print(f"""
116 Python SSL module information:
117 - OpenSSL version: {ssl.OPENSSL_VERSION}
118 - Default protocol: TLS (auto-negotiated)
119""")
120
121# Show supported protocols
122ctx = ssl.create_default_context()
123print(f" Default context settings:")
124print(f" Protocol: TLSv1.2+ (minimum)")
125print(f" Verify mode: {ctx.verify_mode.name}")
126print(f" Check hostname: {ctx.check_hostname}")
127print()
128
129# Demonstrate cipher suite listing
130print(" Enabled cipher suites (top 10):")
131ciphers = ctx.get_ciphers()
132for i, c in enumerate(ciphers[:10]):
133 protocol = c.get("protocol", "?")
134 name = c.get("name", "?")
135 bits = c.get("alg_bits", 0)
136 print(f" {i+1:2}. [{protocol}] {name} ({bits}-bit)")
137if len(ciphers) > 10:
138 print(f" ... and {len(ciphers) - 10} more")
139print()
140
141
142# ============================================================
143# Section 3: Certificate Chain Concepts
144# ============================================================
145
146print("-" * 65)
147print(" Section 3: Certificate Chain of Trust")
148print("-" * 65)
149
150print("""
151 Certificate Chain Structure:
152 ============================
153
154 +---------------------------+
155 | Root CA Certificate | Self-signed, pre-installed
156 | (e.g., DigiCert Root) | in OS/browser trust store
157 +---------------------------+
158 |
159 | signs
160 v
161 +---------------------------+
162 | Intermediate CA Cert | Signed by Root CA
163 | (e.g., DigiCert G2) | Provides operational isolation
164 +---------------------------+
165 |
166 | signs
167 v
168 +---------------------------+
169 | Server Certificate | Signed by Intermediate CA
170 | (e.g., *.google.com) | Presented during TLS handshake
171 +---------------------------+
172
173 Verification Process:
174 1. Server sends its certificate + intermediate cert(s)
175 2. Client finds the issuer of each cert in the chain
176 3. Client verifies each signature using issuer's public key
177 4. Chain must end at a trusted Root CA in the trust store
178 5. Client checks: expiration, revocation (CRL/OCSP), hostname
179""")
180
181# Show trusted CA count
182default_certs = ssl.create_default_context()
183ca_certs = default_certs.get_ca_certs()
184print(f" Trusted Root CAs in system store: {len(ca_certs)}")
185if ca_certs:
186 print(f"\n Sample trusted CAs:")
187 seen = set()
188 count = 0
189 for ca in ca_certs:
190 org = dict(x[0] for x in ca.get("issuer", ())).get(
191 "organizationName", "Unknown"
192 )
193 if org not in seen:
194 seen.add(org)
195 print(f" - {org}")
196 count += 1
197 if count >= 8:
198 break
199 print(f" ... and more")
200print()
201
202
203# ============================================================
204# Section 4: Self-Signed Certificate Commands
205# ============================================================
206
207print("-" * 65)
208print(" Section 4: Self-Signed Certificate Generation (OpenSSL)")
209print("-" * 65)
210
211print("""
212 The following OpenSSL commands create certificates for
213 development/testing. NOT for production use.
214
215 --- Generate Private Key ---
216 $ openssl genrsa -out server.key 2048
217
218 --- Generate Self-Signed Certificate (valid 365 days) ---
219 $ openssl req -new -x509 -key server.key -out server.crt \\
220 -days 365 -subj "/CN=localhost/O=Dev/C=US"
221
222 --- Generate with Subject Alternative Names ---
223 $ openssl req -new -x509 -key server.key -out server.crt \\
224 -days 365 -subj "/CN=localhost" \\
225 -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
226
227 --- View Certificate Details ---
228 $ openssl x509 -in server.crt -text -noout
229
230 --- Verify Certificate Chain ---
231 $ openssl verify -CAfile ca.crt server.crt
232
233 --- Test TLS Connection ---
234 $ openssl s_client -connect example.com:443 -servername example.com
235
236 --- Generate Let's Encrypt Certificate (production) ---
237 $ certbot certonly --standalone -d yourdomain.com
238
239 Note: For Python development servers:
240 context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
241 context.load_cert_chain('server.crt', 'server.key')
242""")
243
244
245# ============================================================
246# Section 5: TLS Handshake Visualization
247# ============================================================
248
249print("-" * 65)
250print(" Section 5: TLS 1.3 Handshake Overview")
251print("-" * 65)
252
253print("""
254 TLS 1.3 Handshake (1-RTT):
255 ===========================
256
257 Client Server
258 | |
259 | ClientHello |
260 | + supported_versions (TLS 1.3) |
261 | + key_share (X25519/P-256) |
262 | + signature_algorithms |
263 | + cipher_suites |
264 | ---------------------------------> |
265 | |
266 | ServerHello |
267 | + selected version |
268 | + selected key_share |
269 | {EncryptedExtensions} |
270 | {Certificate} |
271 | {CertificateVerify} |
272 | {Finished} |
273 | <--------------------------------- |
274 | |
275 | {Finished} |
276 | ---------------------------------> |
277 | |
278 | [Application Data] <============> |
279 | (encrypted with derived keys) |
280
281 Key improvements in TLS 1.3:
282 - 1-RTT handshake (was 2-RTT in TLS 1.2)
283 - 0-RTT resumption (with replay protection caveats)
284 - Removed insecure algorithms (RC4, 3DES, SHA-1, RSA key transport)
285 - Forward secrecy mandatory (ephemeral DH only)
286 - Simplified cipher suites (only 5 defined)
287""")
288
289
290# ============================================================
291# Section 6: Summary
292# ============================================================
293
294print("=" * 65)
295print(" Summary")
296print("=" * 65)
297print("""
298 TLS Best Practices:
299 - Minimum TLS 1.2, prefer TLS 1.3
300 - Use strong cipher suites (AES-GCM, ChaCha20-Poly1305)
301 - Enable HSTS (HTTP Strict Transport Security)
302 - Use certificate pinning for mobile apps
303 - Monitor certificate expiration
304 - Use Let's Encrypt for free production certificates
305 - Never disable certificate verification in production
306 (ssl._create_unverified_context is for testing ONLY)
307
308 Common SSL/TLS Errors:
309 - CERTIFICATE_VERIFY_FAILED: CA not trusted or expired
310 - HOSTNAME_MISMATCH: cert CN/SAN doesn't match hostname
311 - TLSV1_ALERT_PROTOCOL_VERSION: server requires newer TLS
312""")