Python - zajęcia 7
1) Kwestionariusz - rozwinięcie


Oczekiwania i rozwiązania - przemieszanie pytań i losowa kolejność. Pytanie z odpowiedziami przechowuje w krotce, a samo pytanie jest listą. Odpowiedzi przechowywane jako krotka razem z punktacja za odpowiedz.
2) Podsumowanie - pętle
a) FOR

· "wykonaj coś tyle razy ile jest elementów w"
· preferowany rodzaj pętli w Pythonie
· wymaga iterowalnego elementu, po którym się przemieszczamy
b) WHILE

· "... wykonuj tak długo aż"
· pętla wykorzystywana m.in. do tworzenia pętli nieskończonych
· wymaga warunku
3) Szyfrowanie
Używamy gdy potrzebujemy przekazać jakieś dane w sposób poufny. Umożliwia nam takie przekazanie danych aby w idealnej sytuacji tylko konkretny odbiorca mógł daną wiadomość odczytać. Dla reszty ta informacja będzie niezrozumiała / trudna do odczytania.
Czyli bierzemy jakieś dane, zamieniamy je na "bełkot" ALE ten proces jest odwracalny.

Jeśli chcemy żeby ktoś mógł coś rozszyfrować to powinniśmy dać mu klucz szyfrujący żeby mógł odczytać.
To jest proces odwracalny.
Nie można zostawiać tylnej furtki, bo to niszczy całe bezpieczeństwo
4) Funkcja skrótu (hash)
NIE należy mylić jej z szyfrowaniem. Funkcja skrótu zamienia nam dane w "bełkot" ALE PROCES TEN JEST NIEODWRACALNY.
Możemy jednak zawsze stwierdzić, czy dany hash powstał na podstawie konkretnych danych wejściowych. W najprostszej postaci - te same dane zawsze zwracają ten sam hash.
Te same dane zazwyczaj zwracają ten sam hash. Jesteśmy w stanie stwierdzić czy hash powstał na podstawie konkretnych danych wejściowych.
W bazach danych nie przechowują hasła, tylko hash'e do tych haseł
5) Check sum – suma kontrolna

Sprawdzanie czy plik nie był zmodyfikowany. np. poniżej informacja ze jak użyjemy algorytmu SHA256 na pliku Rocky-9 to powinniśmy dostać taki wynik jak w linijce 2 zaznaczone. Jak dostajemy cos innego znaczy ze był modyfikowany.

Każda strona powinna mieć certyfikat. On się składa z kluczy szyfrujących etc. Po to żebyśmy wiedzieli ze nikt nie dłubał przy stronie.
Strona - certyfikat teles

Słowniki i zbiory korzystają z funkcji skrótu do wskazania miejsca, gdzie można znaleźć nasze dane (to dzięki temu słowniki są szybsze od list przy dużej ilości elementów).
6) Szyfr Cezara
Każdy znak jest dla komputera jakąś liczbą w jakiejś tablicy znaków (np. ascii i unicode). Użytkownik chcąc zaszyfrować wiadomość poda jakąś liczbę. Każdy ze znaków zostanie podmieniony na odpowiednik w tablicy przesunięty o tę właśnie liczbę np.
lista_znaków = ["a", "b", "c"....."z"] klucz = 1

Oznacza, że jeśli zaszyfrujemy "a" wykorzystując klucz 1 to litera "a" zostanie podmieniona na "b".
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",
"Ą",
"ą",
"Ć",
"ć",
"Ę",
"ę",
"Ł",
"ł",
"Ń",
"ń",
"Ó",
"ó",
"Ś",
"ś",
"Ź",
"ź",
"Ż",
"ż",
" ",
".",
"?",
"!",
]
wiadomosc_do_zaszyfrowania = input ("Wpisz hasło, które chcesz zaszyfrować:")
klucz = int(input("Wpisz klucz:"))
wiadomosc_do_zaszyfrowania = ""
for litera in wiadomosc_do_zaszyfrowania:
# powyższa lista znaków ułatwi
# ż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}")
7) Szyfrowanie symetryczne
• ten sam klucz jest wykorzystywany do szyfrowania i deszyfrowania danych.
Obie strony (nadawca i odbiorca wiadomości) dzielą się tym samym sposobem (“hasłem” / “kluczem”) umożliwiającym zakodowanie i odkodowanie wiadomości. Pojawia się więc problem - jak przekazać bezpiecznie ten klucz? Zwłaszcza gdy pracują ze sobą na odległość. Szyfrowanie tego rodzaju jest stosowane m.in. ze względu na szybkość.

8) Szyfrowanie asymetryczne
• wykorzystuje dwa oddzielne klucze, jeden służy do szyfrowania danych, drugi do odszyfrowania
Sposób działania jest troche inny niż w symetrycznym. Jest jakby kłódka (klucz publiczny) i klucz (klucz prywatny). Kłódkę udostępniamy publicznie, a klucz mają tylko wybrane osoby i tylko on otwiera (odszyfrowuje) dane zaszyfrowane z pomocą “kłódki”. Nie ma problemu z przekazaniem sposobu odszyfrowania wiadomości.
Jeśli komunikacja ma zachodzić dwukierunkowo obie strony wysyłają sobie nawzajem “kłódki” (tzw. klucze publiczne). Ta metoda mocno obciąża nasze komputery. Można jednak wykorzystać wolne szyfrowanie asymetryczne, żeby podzielić się z kimś szybkim kluczem symetrycznym.


Łączenie się z serwerem — szyfrowanie asymetryczne. Ssh protokół

Zazwyczaj korzystamy z gotowych algo/protokołów szyfrujących
9) Zadanie domowe - Książka kontaktowa.
Skonstruować książkę kontaktową - przechowującą np. imię / nazwisko i numer telefonu. Chcemy żeby program nie kończył pracy po wejściu do menu / wybrania jakiejś operacji - potrzebna jest pętla nieskończonej. Wyjście nastąpi tylko wtedy gdy użytkownik wybierze odpowiedni wariant w menu.
from os import system, name
# Przyjmijmy prosty schemat wpisu do ksiazki:
# klucz to ciąg znaków imienia (string)
# - jak ktoś wpisze imie i nazwisko też będzie ok ,
# wartością będą dane kontaktowe (string)
ksiazka_tele = {"Jan":"123658"}
while True:
# Zapytanie o wybranie operacji
operacja = input("""
Wybierz operację do wykonania:
1 - dopisanie pozycji do książki
2 - aktualizacja pozycji książki
3 - usunięcie pozycji książki
4 - wydruk imion z książki
5 - wydruk całej książki kontaktowej
6 - koniec programu
Podaj kod operacji = """
)
if not operacja:
break
# Wykonanie wybranej operacji
if operacja == "1":
print("Wybrano 1 - dopisanie pozycji do książki")
nowe_imie = input("Wpisz imie/nazwe dla nowego wpisu: ")
kontakt = input("wpisz dane kontaktowe: ")
ksiazka_tele[nowe_imie] = kontakt
elif operacja == "2":
print("Wybrano 2 - aktualizacja pozycji książki")
aktualizowana_nazwa = input("Podaj nazwe, ktora chcesz zaktualizowac: ")
nowa_wartosc = input("wpisz nowe dane kontaktowe: ")
ksiazka_tele[aktualizowana_nazwa] = nowa_wartosc
elif operacja == "3":
print("Wybrano 3 - usunięcie pozycji książki")
usuwana_nazwa = input("Podaj nazwe, ktora chcesz usunac: ")
ksiazka_tele.pop(usuwana_nazwa)
elif operacja == "4":
print("Wybrano 4 - wydruk imion z książki")
for imie in ksiazka_tele.keys():
print(imie)
elif operacja == "5":
print(ksiazka_tele)
print("Wybrano 5 - wydruk całej książki kontaktowej")
for imie in ksiazka_tele:
print(imie)
print(ksiazka_tele[imie])
print("***")
elif operacja == "6":
print("6 - koniec programu")
break
else:
print("\nPodano błędny kod operacji")
# Koniec programu
print("\nKoniec programu")