🐍Python🐍 zajęcia 7 + zadanie
pętle * szyfrowanie symetryczne & asymetryczne * funkcje skrótu * szyfr Cezara * książka adresowa
📌 1. Funkcje skrótu (hashujące)
Funkcje skrótu to funkcje jednokierunkowe – nie można z nich odzyskać oryginalnej wiadomości. Używane np. do haszowania haseł.
🔒 2. Szyfrowanie symetryczne – cryptography.fernet
ten sam klucz do szyfrowania i odszyfrowania
✅ Zalety (plusy):
- Szybkość
- Bardzo szybkie szyfrowanie i odszyfrowywanie, nawet dużych ilości danych.
- Idealne do szyfrowania plików, dysków, transmisji strumieniowej.
- Prostota implementacji
- Łatwiejsze do zaimplementowania niż asymetryczne.
- Mniejsze zużycie zasobów
- Zużywa mniej CPU i pamięci niż szyfrowanie asymetryczne (np. RSA).
❌ Wady (minusy):
- Problem z dystrybucją klucza (Key Distribution Problem)
- Obie strony muszą posiadać ten sam tajny klucz, a jego bezpieczne przekazanie jest trudne (szczególnie przez internet).
- Brak weryfikacji tożsamości
- Samo szyfrowanie symetryczne nie zapewnia, kto wysłał dane. Może być potrzebne dodatkowe uwierzytelnienie.
- Brak rozdzielenia ról
- Każdy, kto ma klucz, może szyfrować i odszyfrowywać – trudniej kontrolować dostępność i uprawnienia.
- Nieodporność na podsłuch bez dodatkowych mechanizmów
- Jeśli klucz zostanie przechwycony, cała komunikacja jest zagrożona.
🔑 3. Szyfrowanie asymetryczne – cryptography.hazmat
(RSA)
para kluczy: publiczny i prywatny
✅ Zalety (plusy):
- Brak problemu z przesyłaniem klucza
- Klucz publiczny można bezpiecznie udostępniać każdemu – tylko klucz prywatny musi być chroniony.
- Rozwiązuje problem dystrybucji klucza znany z szyfrowania symetrycznego.
- Możliwość podpisu cyfrowego
- Umożliwia uwierzytelnianie nadawcy i integralność danych.
- Klucz prywatny służy do podpisywania, a publiczny do weryfikacji.
- Rozdzielenie funkcji szyfrowania i odszyfrowywania
- Jedna strona szyfruje, druga odszyfrowuje – większa kontrola.
- Bezpieczne kanały komunikacji
- Podstawa działania HTTPS, SSL, VPN, PGP.
❌ Wady (minusy):
- Wolniejsze działanie
- Dużo wolniejsze niż szyfrowanie symetryczne, zwłaszcza przy dużych danych.
- Często używane tylko do szyfrowania klucza sesyjnego, a reszta danych szyfrowana jest już symetrycznie (np. w HTTPS).
- Złożoność algorytmów
- Trudniejsze do zaimplementowania i zrozumienia.
- Wymaga dłuższych kluczy (np. 2048 bitów dla RSA), co wpływa na wydajność.
- Zwiększone zużycie zasobów
- Większe obciążenie procesora i pamięci, szczególnie na urządzeniach o ograniczonej mocy
Szyfr cezara
- szyfr przesuwający
- jest szczególnym przypadkiem szyfru podstawieniowego, w którym każdy znak szyfrowanej wiadomości jest zastępowany innym, oddalonym od niego w alfabecie o określoną odległość
Przykład:
szyfr = 3:
Alfabet: AĄBC ĆDEĘ FGHI JKLŁ MNŃO ÓPRS ŚTUW YZŹŻ
Szyfr: CĆDE ĘFGH IJKL ŁMNŃ OÓPR SŚTU WYZŹ ŻAĄB
Program szyfrujący
ZNAKI = (
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
"Ą",
"ą",
"Ć",
"ć",
"Ę",
"ę",
"Ł",
"ł",
"Ń",
"ń",
"Ó",
"ó",
"Ś",
"ś",
"Ź",
"ź",
"Ż",
"ż",
" ",
".",
"?",
"!",
)
# powyższa lista znaków ułatwi stworzenie kodu odpowiedzialnego za szyfrowanie
# żeby przy bardzo dużym kluczu , lub przy zamianie znaku z końca listy nie wyjść za nią
# można skorzystać z operatora modulo (to ten od reszty z dzielenia)
# wg. schematu (indeksznaku + klucz) % len(ZNAKI)
# indeksznaku = ZNAKI.index("!")
# print(f"Indeks znaku ! to: {indeksznaku}")
# klucz = 3
# nowy_indeks = (indeksznaku + klucz) % len(ZNAKI)
# print(f"Po przesunieciu o {klucz} uzyskamy {nowy_indeks}")
# znak= (input('Jaki jest Twoj znak?'))
# for
# zakodowany_znak= int(znak) + (klucz)
# print(zakodowany_znak)
##### ROZWIĄZANIE 1 dla liter
# znak= (input('Jaki jest Twoj znak?'))
# if znak in ZNAKI:
# liczba_szyfrujaca = ZNAKI.index(znak)
# print(f'Liczba szyfrująca tego znaku to: {liczba_szyfrujaca}')
# else:
# print('Ten znak nie znajduje się na liście!')
# klucz = 3
# nowy_indeks = (liczba_szyfrujaca + klucz) % len(ZNAKI)
# print(f"Po przesunieciu o {klucz} uzyskamy {nowy_indeks}")
# nowy_znak = ZNAKI[nowy_indeks]
# print(f"Znak po przesunięciu to: {nowy_znak}")
##### Rozwiązanie 2 dla słów
# do_zaszyfrowania = input("wprowadż tekst do zaszyfrowania: ")
# klucz = int(input("wprowadź liczbę będącą liczbą szyfrującą: "))
# #ADA
# for kazda_litera in do_zaszyfrowania:
# indeks_znaku = ZNAKI.index(kazda_litera)
# indeks_zaszyfrowany = (indeks_znaku + klucz) % len(ZNAKI)
# print("Indeks przed zaszyfrowaniu:", indeks_znaku)
# print("Indeks po szyfrowaniu:", indeks_zaszyfrowany)
# znak_zaszyfrowany = ZNAKI[indeks_zaszyfrowany]
# print(znak_zaszyfrowany)
##### Rozwiązanie 3 do tekstów
do_zaszyfrowania = input("wprowadż tekst do zaszyfrowania: ")
klucz = int(input("wprowadź liczbę będącą liczbą szyfrującą: "))
zaszyfrowany = "" #Twrorzę zmienną zaszyfrowany, która jest pusta. Do niej potem wrzucany jest tekst zaszyfrowany
for kazda_litera in do_zaszyfrowania:
indeks_znaku = ZNAKI.index(kazda_litera)
indeks_zaszyfrowany = (indeks_znaku + klucz) % len(ZNAKI)
znak_zaszyfrowany = ZNAKI[indeks_zaszyfrowany]
zaszyfrowany += znak_zaszyfrowany
print("Zaszyfrowany tekst: ", zaszyfrowany)
Zadanie - książka adresowa
struktura danych:
- słownik
kontakty = {imie_1 : email_1, imie_2 : email_2 ...}
funkcje:
- usuwanie elementu z listy:
"jeśli imię jest w kontaktach, usuń ("del") kontakty[imie]

- aktualizacja:

# Książka adresowa
kontakty = {
"Kasia": "[email protected]",
"Basia": "[email protected]",
"Brad" : "[email protected]"
}
while True:
menu = '''
Menu
1 - dopisanie pozycji do książki
2 - aktualizacja pozycji książki
3 - usunięcie pozycji z książki
4 - wydruk imion z książki
5 - wydruk całej książki z kontaktami
6 - koniec programu
'''
print(menu)
wybor = int(input("Podaj numer operacji, którą chcesz wykonać: "))
if wybor == 1:
imie = input("Podaj imię: ")
if imie not in kontakty:
email = input(f"Podaj email dla kontaktu {imie}: ")
kontakty[imie] = email
print("Dodano kontakt.")
else:
print("Ta pozycja już istnieje.")
elif wybor == 2:
imie = input("Podaj imię kontaktu do aktualizacji: ")
if imie in kontakty:
nowy_email = input("Podaj nowy e-mail: ")
kontakty[imie] = nowy_email
print("Zaktualizowano kontakt.")
else:
print("Nie znaleziono takiego kontaktu.")
elif wybor == 3:
imie = input("Kogo chcesz usunąć? ")
if imie in kontakty:
del kontakty[imie]
print(f"Usunięto kontakt: {imie}")
else:
print("Nie znaleziono takiego kontaktu.")
elif wybor == 4:
for imie in kontakty:
print(imie, end=", ")
elif wybor == 5:
print(kontakty)
else:
print("Dziękuję za skorzystanie z aplikacji. ")
break
Do dodania:
- wersja 3: Mając bazowy produkt warto się zastanowić co może pójść w trakcie korzystania z aplikacji nie tak. Warto obsłużyć takie sytuacje - np. gdy użytkownik spróbuje usunąć kontakt który nie istnieje należy to sprawdzić - i jeśli faktycznie kontaktu nie ma wyświetlić odpowiedni komunikat bez podejmowania próby usunięcia wpisu (co “wywaliłoby” nasz program)
- kosmetyka: Tu możemy się zająć tym jak wyświetlić poszczególne wybory menu w bardziej przyjazny dla odbiorcy sposób np. wybierając opcję “Wyświetl całą książkę z kontaktami” fajnie jeśli użytkownik otrzyma nie po prostu wydruk słownika, tylko np. nazwę, poniżej danej kontaktowe, poniżej jakieś rozdzielenie (np. serię *), po czym następny kontakt.