Wprowadzenie do certyfikatów i HTTPS#
Autor: Bartosz Naskręcki
Cel sesji: w przystępny sposób zrozumieć po co są certyfikaty, jak budują zaufanie w HTTPS i gdzie spotykamy je na co dzień.
Techniczne szczegóły ukryliśmy w sekcjach „Dla ciekawskich” — możesz je rozwinąć tylko wtedy, gdy będzie czas lub padnie pytanie.
Plan 60 minut#
Czas |
Temat |
---|---|
5» |
Wstęp: dlaczego szyfrowanie i zaufanie? |
10» |
Podstawy: szyfrowanie symetryczne vs asymetryczne |
15» |
Certyfikaty X.509 i łańcuch zaufania |
15» |
HTTPS/TLS w praktyce: co się dzieje podczas połączenia |
10» |
Zastosowania + mini‑demo (podpis cyfrowy, analiza certyfikatu) |
(Opcjonalnie) Przygotowanie środowiska#
Jeśli chcesz uruchomić ćwiczenia w Pythonie, potrzebny będzie pakiet cryptography
.
W wierszu poleceń (lub w komórce notebooka) możesz wykonać:
pip install cryptography
Jeśli nie masz internetu lub nie chcesz instalować — nadal możesz prowadzić zajęcia, korzystając z samych slajdów/sekcji markdown.
# Szybki test środowiska (uruchom tę komórkę)
from importlib.util import find_spec
has_crypto = find_spec("cryptography") is not None
print("Pakiet 'cryptography' dostępny:" , has_crypto)
if not has_crypto:
print("Aby uruchomić ćwiczenia kodowe, zainstaluj pakiet: pip install cryptography")
1) Dlaczego potrzebujemy szyfrowania i zaufania w sieci?#
Bez HTTPS dane płynęłyby jawnie (podsłuch, podmiana treści).
HTTPS zapewnia poufność, integralność i uwierzytelnienie serwera.
Wbudowane listy zaufanych Urzędów Certyfikacji (CA) w przeglądarkach pozwalają zweryfikować, że „to naprawdę ta strona”.
Dla ciekawskich: SSL vs TLS w jednym akapicie
Dziś mówimy o TLS (następca przestarzałego SSL). „HTTPS” to po prostu HTTP przez TLS. W praktyce nazwa „SSL” bywa używana potocznie na określenie całej warstwy szyfrowania.
2) Podstawy kryptografii — bardzo krótko#
Symetryczne: jeden wspólny sekret (szybkie; dobre do transmisji danych).
Asymetryczne: para klucz publiczny / prywatny (wolniejsze; świetne do wymiany sekretów i podpisów).
Podpis cyfrowy: nadawca podpisuje skrót wiadomości kluczem prywatnym; każdy może zweryfikować podpis jego kluczem publicznym.
Dla ciekawskich: intuicja RSA i podpisu
W RSA bezpieczeństwo opiera się o trudność faktoryzacji dużych liczb. Podpis polega na zaszyfrowaniu skrótu wiadomości kluczem prywatnym; odbiorca weryfikuje go kluczem publicznym. W HTTPS algorytmy asymetryczne służą głównie do ustalenia klucza sesyjnego, a sama treść leci już szybko dzięki szyfrowaniu symetrycznemu.
Mini‑demo: podpis i weryfikacja (RSA)#
Uruchom, jeśli masz zainstalowany
cryptography
.
# Podpis i weryfikacja RSA
try:
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes
# generowanie kluczy
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
public_key = private_key.public_key()
message = b"Hello, Cyber AMU!"
# podpisanie
signature = private_key.sign(
message,
padding.PKCS1v15(),
hashes.SHA256()
)
# weryfikacja (rzuci wyjątek, jeśli niepoprawne)
public_key.verify(signature, message, padding.PKCS1v15(), hashes.SHA256())
print("Podpis zweryfikowany poprawnie!")
except Exception as e:
print("Nie udało się wykonać demonstracji:", e)
Dla ciekawskich: krótki przykład szyfrowania symetrycznego (Fernet/AES)
Poniższe ćwiczenie pokaże, że ten sam klucz służy do zaszyfrowania i odszyfrowania danych.
# (Opcjonalnie) Szyfrowanie symetryczne z Fernet
try:
from cryptography.fernet import Fernet
key = Fernet.generate_key()
f = Fernet(key)
token = f.encrypt(b"tajny komunikat")
plain = f.decrypt(token)
print("Szyfrogram:", token[:32], "...")
print("Odszyfrowano:", plain)
except Exception as e:
print("Aby uruchomić ten przykład, zainstaluj 'cryptography' (pip install cryptography).")
3) Certyfikaty X.509 — co, po co i jak?#
X.509 wiąże tożsamość (np. nazwę domeny) z kluczem publicznym i jest podpisany przez CA.
Przeglądarka sprawdza ważność i łańcuch zaufania — od certyfikatu serwera aż do zaufanego „roota”.
Znajdziesz tam m.in. okres ważności, nazwy domen (SAN), dopuszczalne zastosowania klucza.
Ćwiczenie bez kodu (na żywo): otwórz dowolną stronę → ikona kłódki → „Certyfikat” → odczytaj Issuer, Validity, Subject Alternative Name.
Mini‑demo: odczyt pól z certyfikatu (wklej PEM)#
Skopiuj certyfikat w formacie PEM (np. z narzędzia openssl s_client -showcerts -connect example.com:443
) i wklej go do zmiennej cert_pem
niżej, a następnie uruchom dwie komórki.
# Wklej tu swój certyfikat PEM (włącznie z liniami -----BEGIN CERTIFICATE----- / -----END CERTIFICATE-----)
cert_pem = """
-----BEGIN CERTIFICATE-----
(Wklej tu certyfikat)
-----END CERTIFICATE-----
"""
# Odczyt podstawowych informacji z certyfikatu
try:
from cryptography import x509
from cryptography.x509.oid import ExtensionOID
import textwrap
if "BEGIN CERTIFICATE" not in cert_pem:
raise ValueError("Nie wklejono certyfikatu PEM do zmiennej 'cert_pem'.")
cert = x509.load_pem_x509_certificate(cert_pem.encode())
print("Temat (Subject):", cert.subject.rfc4514_string())
print("Wystawca (Issuer):", cert.issuer.rfc4514_string())
print("Ważny od:", cert.not_valid_before)
print("Ważny do:", cert.not_valid_after)
try:
san = cert.extensions.get_extension_for_oid(ExtensionOID.SUBJECT_ALTERNATIVE_NAME).value
dns = san.get_values_for_type(x509.DNSName)
print("SAN (DNS):", ", ".join(dns) if dns else "—")
except x509.ExtensionNotFound:
print("SAN: —")
print("Algorytm podpisu:", getattr(cert.signature_algorithm_oid, "_name", cert.signature_algorithm_oid.dotted_string))
except Exception as e:
print("Nie udało się sparsować certyfikatu:", e)
4) HTTPS/TLS — co naprawdę się dzieje?#
Klient mówi „Cześć” i podaje listę obsługiwanych wersji/szyfrów.
Serwer wybiera parametry i przesyła certyfikat.
Klient weryfikuje certyfikat i uzgadnia tajny klucz sesyjny.
Od tej chwili dane lecą szyfrowane symetrycznie — szybko i bezpiecznie.
Dla ciekawskich: TLS 1.3 vs 1.2 w pigułce
W TLS 1.3 uproszczono „handshake”, wymuszono krzywe (EC)DHE i usunięto słabe szyfry. Zyskujemy krótki i nowoczesny start sesji oraz tzw. Perfect Forward Secrecy.
Mini‑demo: wspólny sekret (ECDH → klucz sesyjny)#
# Wspólny sekret z ECDH i wyprowadzenie klucza sesyjnego
try:
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from cryptography.hazmat.primitives import hashes
# Klient i serwer generują swoje pary kluczy
sk_client = ec.generate_private_key(ec.SECP256R1())
sk_server = ec.generate_private_key(ec.SECP256R1())
# Wymiana kluczy publicznych -> obie strony liczą tajny wspólny sekret
shared_client = sk_client.exchange(ec.ECDH(), sk_server.public_key())
shared_server = sk_server.exchange(ec.ECDH(), sk_client.public_key())
assert shared_client == shared_server
# Z tajnego sekretu wyprowadzamy 32‑bajtowy klucz sesyjny (HKDF+SHA256)
session_key = HKDF(algorithm=hashes.SHA256(), length=32, salt=None, info=b"tls-handshake").derive(shared_client)
print("Ustalony klucz sesyjny (hex, początek):", session_key.hex()[:32], "...")
except Exception as e:
print("Aby uruchomić ten przykład, zainstaluj 'cryptography'. Błąd:", e)
5) Sprzętowe klucze i karty: PIV / YubiKey (opcjonalnie)#
PIV: standard kart tożsamości (z certyfikatami, kluczami i PIN‑em) — przykład silnego, wieloskładnikowego uwierzytelniania.
YubiKey (interfejs PIV): działa jak karta inteligentna; klucz prywatny nigdy nie opuszcza urządzenia.
Dla ciekawskich: do czego to się przydaje?
Podpisywanie i odszyfrowywanie (RSA/ECC) po stronie sprzętu, integracja z PKCS#11, użycie do logowania, S/MIME, SSH, podpisywania kodu itp.
6) C2PA i „Content Credentials” — skąd wiesz, że zdjęcie jest prawdziwe?#
C2PA to otwarty standard, który dodaje do treści wiarygodne metadane o pochodzeniu i edycjach.
Dzięki podpisom kryptograficznym możesz sprawdzić „kto i czym dotykał” materiał — pomocne w walce z dezinformacją.
Mini‑demonstracje „na żywo” (bez instalacji)#
Przeglądarka → kłódka → Certyfikat: pokaż Issuer, Validity, SAN.
Porównanie stron: z certyfikatem „zielonym” (ważny) i przeterminowanym (ostrzeżenie).
Pytanie do sali: dlaczego nie widzimy już kłódki EV (Extended Validation)? Czy to zmieniło użyteczność?
Jeśli masz terminal i OpenSSL:
openssl s_client -showcerts -connect example.com:443 | openssl x509 -noout -issuer -subject -dates -ext subjectAltName
Ćwiczenia dla uczestników (proste)#
Znajdź w certyfikacie ulubionej strony Issuer i Subject.
Sprawdź, czy data ważności „Not After” jest przyszła.
Oszacuj, do czego mógłbyś użyć klucza sprzętowego (PIV/YubiKey) w swojej pracy.
Dla ciekawskich: samodzielne utworzenie self‑signed certyfikatu w Pythonie
Poniższa komórka tworzy parę kluczy i lokalny certyfikat „self‑signed” z nazwą CN=example.com
.
# (Opcjonalnie) generowanie self-signed cert w Pythonie
try:
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography import x509
from cryptography.x509.oid import NameOID
from datetime import datetime, timedelta
# klucz
key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
subject = issuer = x509.Name([
x509.NameAttribute(NameOID.COUNTRY_NAME, u"PL"),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Demo"),
x509.NameAttribute(NameOID.COMMON_NAME, u"example.com"),
])
cert = (
x509.CertificateBuilder()
.subject_name(subject)
.issuer_name(issuer)
.public_key(key.public_key())
.serial_number(x509.random_serial_number())
.not_valid_before(datetime.utcnow() - timedelta(minutes=1))
.not_valid_after(datetime.utcnow() + timedelta(days=30))
.add_extension(x509.SubjectAlternativeName([x509.DNSName(u"example.com")]), critical=False)
.sign(private_key=key, algorithm=hashes.SHA256())
)
pem_key = key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()
)
pem_cert = cert.public_bytes(serialization.Encoding.PEM)
# Zapis do plików roboczych
from pathlib import Path
Path("demo_key.pem").write_bytes(pem_key)
Path("demo_cert.pem").write_bytes(pem_cert)
print("Zapisano: demo_key.pem oraz demo_cert.pem")
print(pem_cert.decode()[:200], "...")
except Exception as e:
print("Aby uruchomić ten przykład, zainstaluj 'cryptography'. Błąd:", e)
Notatki dla prowadzącego#
Główna narracja: „zaufanie i prosty model mentalny” zamiast matematyki.
Przeplataj opowieść krótkimi pytaniami do grupy („co się stanie, jeśli…?”).
Jeśli coś nie zadziała — przejdź do sekcji bez kodu; cały materiał jest autonomiczny.
FAQ (podchwytliwe pytania)
Czy certyfikat „szyfruje” stronę? — Nie. Certyfikat uwierzytelnia serwer i pozwala uzgodnić klucz; szyfrowanie robi TLS i szyfry symetryczne.
Czy EV daje więcej bezpieczeństwa? — Weryfikuje organizację, ale praktycznie nie wpływa na UI/UX przeglądarek; większość użytkowników i tak patrzy na kłódkę/domenę.
Po co PIV/YubiKey? — Chronią klucz prywatny sprzętowo; idealne do podpisów, logowania, SSH, S/MIME.
Linki i materiały do dalszej nauki#
Dokumentacja
cryptography
: https://cryptography.io/Przykładowe polecenia OpenSSL:
man x509
,man s_client
Standard X.509 (wprowadzenie) i TLS — materiały popularnonaukowe znajdziesz w sieci oraz dokumentacji przeglądarek.