Zum Inhalt

Kryptographie

Die Wissenschaft der Kryptographie befasst sich mit der Kunst, einen Text so zu verändern (zu verschlüsseln), dass ihn jeder, der möchte, sehen kann, aber nur der bestimmte Empfänger auch verstehen (also entschlüsseln) kann.

Im folgenden Diagramm siehst du den schematischen Ablauf einer typischen kryptographischen Anwendung. Ein Text, der geheim gehalten werden soll (Klartext genannt, weil es sich um einen lesbaren, z.B. deutschen Text handelt), soll an jemand anderes verschickt werden, ohne dass ein Fremder den Text lesen kann.

Dazu wird der Klartext mittels eines Schlüssels verschlüsselt und das dadurch entstandene Chiffrat (oder Geheimtext) an den Empfänger geschickt. Die so entstandene Verbindung wird als 'sicher' bezeichnet, was bedeutet dass niemand unbefugtes die Nachricht lesen kann. Mittels desselben Schlüssels kann der Empfänger das Chiffrat wieder in Klartext umwandeln (entschlüsseln).

Kryptographie Schema

Wichtige Begriffe

  • Klartext: Der lesbare, ursprüngliche Text
  • Chiffrat oder Geheimtext: Der verschlüsselte Text
  • Schlüssel: Die Information, die zum Ver- und Entschlüsseln nötig ist
  • Verschlüsseln: Klartext → Geheimtext
  • Entschlüsseln: Geheimtext → Klartext

Zu diesem Zweck gibt es viele verschiedene Methoden. Wir betrachten zuerst symmetrische Verschlüsselungen. »Symmetrisch« bedeutet in diesem Zusammenhang, dass der Empfänger denselben Schlüssel verwendet wie der Sender.

Rotationschiffre (Caesar-Chiffre)

Nach der Überlieferung des römischen Schriftstellers Sueton verwendete Julius Cäsar ein Verschlüsselungsverfahren, um seinen Feldherrn im Krieg Nachrichten zu schicken. Er verschob dazu alle Buchstaben im Alphabet um drei Zeichen.

  • Aus A wurde D
  • Aus B wurde E
  • Aus C wurde F
  • ...

Am Ende des Alphabets fing er wieder vorne an: - Aus X wurde A - Aus Y wurde B - Aus Z wurde C

Beispiel: Caesar-Verschlüsselung

Wenn wir das Wort HALLO mit Caesars Methode (Verschiebung um 3) verschlüsseln:

Klartext:    H  A  L  L  O
             ↓  ↓  ↓  ↓  ↓
Geheimtext:  K  D  O  O  R

Aufgaben: Von Hand verschlüsseln

Aufgabe 1: Erste Entschlüsselung

Eine Nachricht von Julius Cäsar an seine Truppen könnte gelautet haben:

DQJULII

Entschlüssle diese Nachricht von Hand. Bedenke, dass Caesar sein Alphabet um 3 Stellen verschoben hat.

Lösung
D → A (3 zurück)
Q → N
J → G
U → R
L → I
I → F
I → F

Lösung: ANGRIFF
Aufgabe 2: Allgemeine Caesar-Chiffre

Die Caesar-Chiffre kann man verallgemeinern, indem man nicht nur um 3, sondern um eine beliebige Anzahl Stellen verschiebt.

a) Wie viele verschiedene Schlüssel gibt es bei einer allgemeinen Caesar-Chiffre?

Hinweise:

  • Das Alphabet hat 26 Buchstaben
  • Ist eine Verschiebung um 27 sinnvoll? Oder gibt es eine kleinere Zahl, die dasselbe bewirkt?
  • Gibt es eine Verschiebung, die keine sinnvolle Verschlüsselung darstellt?

b) Hältst du das System für sicher? Wenn du weisst, dass ein Text mit der Caesar-Chiffre verschlüsselt ist, wie würdest du vorgehen um einen Geheimtext zu entschlüsseln, auch wenn du den Schlüssel nicht kennst?

Lösung

a) Es gibt 25 verschiedene Schlüssel (Verschiebung um 1 bis 25).

  • Verschiebung um 0 ist keine Verschlüsselung
  • Verschiebung um 26 ist gleich wie 0 (einmal rum)
  • Verschiebung um 27 ist gleich wie 1

b) Das System ist nicht sicher! Man kann einfach alle 25 Möglichkeiten durchprobieren (Brute-Force-Angriff). Das dauert nur wenige Minuten von Hand.

Aufgabe 3: Geheimtext knacken

Du hast folgenden Geheimtext abgefangen. Du vermutest stark, dass er mit der Caesar-Chiffre verschlüsselt wurde:

GRRK CKMK LAKNXKT TGIN XUS

Versuche den Klartext zu bestimmen, indem du verschiedene Verschiebungen ausprobierst. Welcher Schlüssel wurde verwendet?

Tipp: Beginne mit kleinen Verschiebungen (1, 2, 3...) und prüfe, ob ein sinnvoller deutscher Text entsteht.

Programmierung: Caesar-Chiffre

Nun wollen wir die Caesar-Chiffre in Python programmieren. Unser Ziel sind zwei Funktionen:

  • verschluesseln(klartext, schluessel)
  • entschluesseln(geheimtext, schluessel)

ASCII-Tabelle

Um Buchstaben zu verschieben, nutzen wir die ASCII-Codierung. In dieser Tabelle ist jedem Zeichen eine Zahl zugeordnet:

  • A hat den Code 65
  • B hat den Code 66
  • C hat den Code 67
  • ...
  • Z hat den Code 90

Du findest hier die vollständige ASCII-Tabelle als Referenz. In Python können wir mit zwei Funktionen auf diese Tabelle zugreifen:

  • ord(zeichen) → gibt die Zahl für ein Zeichen zurück
  • chr(zahl) → gibt das Zeichen für eine Zahl zurück

Beispiel: ord() und chr()

###(De-)Aktiviert den Code nach der Zeile # Tests (Groß-/Kleinschreibung wird nicht beachtet)
(Ctrl+I)
Ein- oder Ausstieg aus dem "Split-Screen"-Modus
(Alt+: ; Ctrl, um die Spalten zu vertauschen)
Ein- oder Ausstieg aus dem "Vollbildmodus"
(Esc)
Kürzen/nicht kürzen der Rückmeldungen im Terminal (Standardausgabe & Stacktrace / Starte das Programm erneut zum Anwenden)
Wenn aktiviert, wird der aus dem Terminal kopierte Text in eine Zeile umgewandelt, bevor er in die Zwischenablage kopiert wird.

Aufgaben: Verschlüsselungsfunktion

Einzelne Zeichen verschieben

Aufgabe 4: Einzelnes Zeichen verschieben

Schreibe ein Programm, welches ein einzelnes Zeichen um eine Stelle im Alphabet verschiebt.

Vorgehen:

  1. Hole die ASCII-Nummer vom Zeichen mit ord()
  2. Addiere 1 zur Nummer
  3. Wandle die neue Nummer zurück in ein Zeichen mit chr()
  4. Gib das verschobene Zeichen aus

Teste dein Programm mit dem Buchstaben 'A' → sollte 'B' ergeben.

###(De-)Aktiviert den Code nach der Zeile # Tests (Groß-/Kleinschreibung wird nicht beachtet)
(Ctrl+I)
Ein- oder Ausstieg aus dem "Split-Screen"-Modus
(Alt+: ; Ctrl, um die Spalten zu vertauschen)
Ein- oder Ausstieg aus dem "Vollbildmodus"
(Esc)
Kürzen/nicht kürzen der Rückmeldungen im Terminal (Standardausgabe & Stacktrace / Starte das Programm erneut zum Anwenden)
Wenn aktiviert, wird der aus dem Terminal kopierte Text in eine Zeile umgewandelt, bevor er in die Zwischenablage kopiert wird.

.128013.8594d/BnS52Lc8[Aysvf7.;w{kWUlö4 uE-tm1VTpCN6=(9ü}HIo0]rqe+3bi_g:Zz),Mah050c0$0H0?0*0A0p0D0k0A0?0p0p0Q010H0*0M010406050p0E0I0I0?0!0o040j0B1f0f0,050d1f1h1j1l1d0M04051z1s1C0d1z1d0c0*0q101214160@0*0,0@0A1Q0@0H1b050{0)0A0$1L1315011P1R1T1R0H1Z1#1X0H0!1A0H0@100X0~0M0?0f160i011%1N010r0}0$0f0?0I0$1X0p1~0f241)271#2a2c1b0a0D1n1p0,0p0q0X0!0p0k1S0?1r1t2g1A0d1_2F1?1^1@1Y0c2i161T0f290X0p1X1I1K111(2P0*2R0f0X2W1X0M0!0$1A2f1 2F2/0f2.2g2O012%0!1i0A1b0D0J1s2=1c1e2^2Y252{2}2 0i322E1d2=2_390?2~040D0(3d2:3f361M1)3i3k0D0C3o2?3q1 3h2w3a3l0h3y343g373t3D3j2 0P3H3A2h3K163u2 0s3Q353B3T2`3M3v0l3Y3J3s3U3%2 0S3*3r2Z3$2|3N040J0Y3;3!3,3@3E0J312D3p3Z3S3 3V3`3c443z463C3^3k0J3n4c3I3=383.3`3x4k3R4f413G4r4e3#490J3P4w3+3?4z3X4C4m3L4g1b0J3)4H3~4E4o0J3:4O474Q4K040i3|4U4t3_0i43334s4y4o0i4b4*4x484-4j331D2,2F2W2I0c1^2N3#0k2(2d1A4|1B4`462;2E05520_2@4P250k0J1b030D0n0E0r0,0?0)1$0C0-0D0F2#0/0$0A2R0 0.0$0*2z290D1g0D5F2R0D0g0H5A1#0D0q0$2x2z0*0$5s2h0G2q1o0E1q3Q4+481b5z5G0@293H0D4;3?0X1b0Q5?5^250p5j0402030(0S0u0n63650u5+5~1)5i5k300t5m0g0N0W0W0G0O1g2c0!0D0@1|5=4#4y1b130k0*0*0+0f6q5V5}4D255`045|4k5@6J3t0)1b2w0c3H6d161a040R6W6Q3U5.5F5H0f6$4I6Y1b0:3}4V386S042+2#0H6-5g1)6Z6#4k6X010p0?1b0r6}6?1)0p22620#0E0X0H676k6m6o6G6s2v2h6966792_0p0*1b0w7t6y045/6+7z3 7v1b0U7E3?7c1b7r0u5v7J5 7w047y726%2`6z2y6C6E7n7Q7b7S7I7V6.747d027f7h6b7+6~6/046;4r5,3?6f045l0i6i0z0I305L0!0@0B5;6,6x5-042R0E0$7#1h6H6O736L6N336P7,0f7Y6B6D6F8j0!6I7,6L0%8z7@010I7S4)3e730f6^6`0f6|7?7a7^714^7W75777%167L7e7g7i0O0$8g0D6p8x7P8Q7u7S7U8U8r1b8f8h8w6r8Y747)8}8!7/8$7=8?8E6Z7`4*7|5h615l0(6i0.0E0!0T0k0x0D2#0D5E5:5I1g0v1 0_5B6=3h1b5U5W6u5!0$0p0+7C8a8D8R018n9J3h6^2z8y8/3#708}8s8e8)8`7$9S3 979x4y8M0!6{8}9U9#7K7604789/5 7.7:7i0K5V2y9C299E9o6*8a5v7N908;9V9z9}2z0X9D9F9H6w959K7G047*ai7u7.6466927;9-6:6c7W8L1b8N8Pan9T1b8T5b8V9;9?aC7F9_939054098baK7K7d0F0!0,5Z0f0*0pa5aq94aG7,ak8=a)8E9WagaRa-aj8 9@7bap6a0D0b0Da6a^8Za8b07X049A9~ada0afa3aha=8:7H90a`ar9`a(2:739%7{737~5l0y5F5Q2,0D0L9E0H0p9(489*9,b39.aS9^7MbjaO1baQbg1b0GbQ0Dbs0*bu1$bx0pbz0DbQ0Gas7iau7_bB3?0x772w9N7A5QbY9Gbba;2:8q8E0X0v1b2#b:9$1b0m90617N0ea bH6 1b0;c17Kc6a%0Vc9bdaD04cd8l8Vcg6a0=cjbl7W6Z0Z0-3Q0DcAb{9K9Wb6ac5!ce6K5{cI6R1b9Qb)aFcu8r6^6UcPa904b=0Hb@9qb_2?bmavco8A1b8Cc*8E8G4Lb)983ecBcC9Oaz9+8OcVb38W9=bO8#7;ctc%8Vb2ca6(cXbyc!7Dc a@d97-7Ma%a|a~a%a77xcWcF9 c$5fa?bfc bh0ub%bkd67,bn4:0d5d2-4_dI0d562G4~1s2JdP5r1#4{1J34dL0`0|0~04.
Aufgabe 5: Variable Verschiebung

Erweitere dein Programm so, dass du ein Zeichen um eine variable Anzahl Stellen verschieben kannst.

Definiere dazu eine Variable schluessel und verwende sie für die Verschiebung.

Teste: - 'A' mit Schlüssel 3'D' - 'H' mit Schlüssel 3'K'

###(De-)Aktiviert den Code nach der Zeile # Tests (Groß-/Kleinschreibung wird nicht beachtet)
(Ctrl+I)
Ein- oder Ausstieg aus dem "Split-Screen"-Modus
(Alt+: ; Ctrl, um die Spalten zu vertauschen)
Ein- oder Ausstieg aus dem "Vollbildmodus"
(Esc)
Kürzen/nicht kürzen der Rückmeldungen im Terminal (Standardausgabe & Stacktrace / Starte das Programm erneut zum Anwenden)
Wenn aktiviert, wird der aus dem Terminal kopierte Text in eine Zeile umgewandelt, bevor er in die Zwischenablage kopiert wird.

.128013d/*n2Lcoysvfkrqelö4 u3tm1bipg):a=(h050b0q0x0G0B0r0k0u0h0r0G0k0k0H010x0B0C010406050k0v0y0y0G0o0j040g0s0+0e0D050c0+0-0/0;0)0C0405120{150c120)0b0B0l0S0U0W0Y0J0B0D0J0r1j0J0x0%050N0A0r0q1e0V0X011i1k1m1k0x1s1u1q0x0o130x0J0S0i0Q0C0G0e0Y0f011w1g010m0P0q0e0G0y0q1q0k1Q0e1W1y1Z1u1$1(0%0a0u0?0^0D0k0l0i0o0k0h1l0G0`0|1,130c1L281I1K1J1r0b1.0Y1m0e1#0i0k1q1b1d0T1x2i0B2k0e0i2p1q0C0o0q131+1R282E0e2D1,2h012w0o0.0r0%0z0{2H0(0*2K2r1X2N2P0%0f2T270)2H2L2!0G2Q040w2(2F162B282p2b0b1K2g2Y1y0h2x1)132`142^2W2?262?310L2J1R2L0n0%0L0m2=2I0u381-2 0Y0e0m0%0p0v0G0b0o0G0x0,0m1R252U3o2L0$040I3l3e3p1f1y0e0%0k0q0B0x0q3M3H3q013J0E0F3M060u3+3n2+3!3R043C3E3M3-2X3P0Y0i0%0H3@3Z3`010y0B0%0t3 3.413|040d473_2s2M3S3U3W3)3,3^3f3!3h042B3B0o0e4d4n413:3=0_3)0{3c2C2@4E0c35292|0{2c4L0G1t4G2`0)4H0M0O0Q04.
Aufgabe 6: Alphabet-Ende behandeln

Problem: Was passiert, wenn wir 'Z' um 3 Stellen verschieben?

ord('Z') = 90
90 + 3 = 93
chr(93) = ']'  ← Das ist kein Buchstabe!

Wir müssen am Alphabet-Ende wieder bei 'A' anfangen.

Lösung: Wir überprüfen, ob wir über das 'Z' hinausgehen und ziehen die Länge vom Alphabet ab:

neue_nummer = ascii_nummer + schluessel

# Falls wir über 'Z' (90) hinaus gehen:
if neue_nummer > ord('Z'):
    neue_nummer = neue_nummer - 26  # 26 Buchstaben zurück

Noch besser mit Modulo:

# Position im Alphabet (0-25)
position = ascii_nummer - ord('A')
# Verschieben mit Wrap-around
neue_position = (position + schluessel) % 26
# Zurück zu ASCII
neue_nummer = neue_position + ord('A')

Implementiere die Lösung und teste: - 'X' mit Schlüssel 3'A' - 'Z' mit Schlüssel 3'C'

###(De-)Aktiviert den Code nach der Zeile # Tests (Groß-/Kleinschreibung wird nicht beachtet)
(Ctrl+I)
Ein- oder Ausstieg aus dem "Split-Screen"-Modus
(Alt+: ; Ctrl, um die Spalten zu vertauschen)
Ein- oder Ausstieg aus dem "Vollbildmodus"
(Esc)
Kürzen/nicht kürzen der Rückmeldungen im Terminal (Standardausgabe & Stacktrace / Starte das Programm erneut zum Anwenden)
Wenn aktiviert, wird der aus dem Terminal kopierte Text in eine Zeile umgewandelt, bevor er in die Zwischenablage kopiert wird.
Verbleibende Versuche : 5/5

.128013d/n(Sü52ILc8Aoysvf70;rkWqXe+lö4 u-3tm1Vbi_p%g)ZzC:a6=9h050b0B0K0Z0P0D0q0G0l0D0Z0q0q0#010K0P0R010406050q0H0L0L0Z0w0p040k0E120d0T050c12141618100R04051m1f1p0c1m100b0P0r0:0=0@0_0%0P0T0%0D1D0%0K0~050+0O0D0B1y0?0^011C1E1G1E0K1M1O1K0K0w1n0K0%0:0o0.0R0Z0d0_0i011Q1A010s0-0B0d0Z0L0B1K0q1.0d1@1S1`1O1}1 0~0a0G1a1c0T0q0r0o0w0q0l1F0Z1e1g231n0c1)2s1$1(1%1L0b250_1G0d1|0o0q1K1v1x0;1R2C0P2E0d0o2J1K0R0w0B1n221/2s2Y0d2X232B012Q0w150D0~0G0M1f2#0 112(2L1^2+2-2/0i2=2r102#2)2|0Z2.040G0J302Z322_1z1S35370G0F3b2$3d1/342j2}380h3l2@332`3g3q362/0!3u3n243x0_3h2/0t3D2^3o3G2*3z3i0m3L3w3f3H3Q2/0$3T3e2M3P2,3A040M0u3!3N3V3%3r0M2;2q3c3M3F3/3I3*2 3@3m3_3p3(370M3a3 3v3#2{3X3*3k473E423;3t4e413O3|0M3C4j3U3$4m3K4p493y430~0M3S4u3.4r4b0M3Z4B3`4D4x040i3,4H4g3)0i3?2?4f4l4b0i3~2?1q2V2s2J2v0b1(2A3O0l2R201n4%1o4#3_2!2r054-0)2%4C2{0~0W0B0P2m1|3u0G4k3/0o0~0#56583$0q0M0~02030J0$0v0A5j5l0v3-4I4 042l1F0H0B0@0B0D5d4q1^5a045c47575E1S0L0P0~464T4U3{0~0R2G0P0{0o0d5D4v0_5G5I2?5K5$2*0O0~2j0b3u5e1^0}040e5=5L3H5052545!475?1S5^0U5#4~1S5G0I675t3g5.045:5{5,5^5`625|015g5i5k5m0n5p5m6i680_653D5S3$0l5h04030G0N0B2k2m0P0B0O1|0G5N0K0G0y0w0Z0R0I160o0H0d5;4O4l0~2E5y0Q5V0q5X0P5Z6c2)5(6?3O6k6w6d5}046.6:6=5J635%0~0C6_5T5v2m0D5y5A5C6m6j0~66736n5G0S783$5N0~0i4o5R74016D0~6G0V0H0w0g0l0x0G0W0H0G0n0f0X0j0j5s346*0B6,0d131 0w7o5F5b7Y3g7R6,705Y615*7v5G777k5,0d6f6h7g6x016{7^6}6o6E6u0v6t6r5r7|2)6z4e6B5u6+5z0Q51530%557:7_6^8i7}7=0~2m7X856`0~6l4Z6n0d7%0B0Q7U146J6|867i6A7v7x6F036G0n0D0K6J1}0{0r8H8w0~0?0l0P0P8A7V8D8l6@7!8(4l7?0w6%8v7h5_8E6)048e608?3/874T7v8x048b8#8C8q7,7l8*967;8W2l8Z937W7#75047/997_905w7c5z0q5B8U5,0x0~0P0s9g2*8y9e8%9k7}5G020T0K849D348-8/4_6n7{8:7_0q1=04020z0H0o9I0V9W9Y9I8{3$650Y3D0G9.5+9l9A8B9f8+590~0I5)2r9:7}7q4L7t31897$917S8c8_8g7+9}7-98ac8w6f8p9)5@8taja5929?9C9O8;7j8~0c4{2W4!ax0c4;2t4)1f2waE0Z1Naz4%10aA0*0,0.04.

Verschlüsselungsfunktion

Aufgabe 7: Verschlüsselungsfunktion

Jetzt haben wir alle Bausteine! Schreibe eine Funktion verschluesseln, die einen kompletten Text verschlüsselt.

Signatur:

def verschluesseln(klartext, schluessel):
    # ...
    return geheimtext

Vorgehen:

  1. Erstelle einen leeren String geheimtext = ""
  2. Durchlaufe jeden Buchstaben im klartext (mit for)
  3. Verschiebe jeden Buchstaben wie in Aufgabe 6
  4. Füge den verschobenen Buchstaben zu geheimtext hinzu
  5. Gib geheimtext zurück

Teste:

print(verschluesseln("HALLO", 3))  # → "KDOOR"
print(verschluesseln("ANGRIFF", 3))  # → "DQJULII"

###(De-)Aktiviert den Code nach der Zeile # Tests (Groß-/Kleinschreibung wird nicht beachtet)
(Ctrl+I)
Ein- oder Ausstieg aus dem "Split-Screen"-Modus
(Alt+: ; Ctrl, um die Spalten zu vertauschen)
Ein- oder Ausstieg aus dem "Vollbildmodus"
(Esc)
Kürzen/nicht kürzen der Rückmeldungen im Terminal (Standardausgabe & Stacktrace / Starte das Programm erneut zum Anwenden)
Wenn aktiviert, wird der aus dem Terminal kopierte Text in eine Zeile umgewandelt, bevor er in die Zwischenablage kopiert wird.
Verbleibende Versuche : 5/5

.128013d/n(x52Lc8oysvf70.;wrkqe+lö4 u-3tm1bGi_pg):z,Za6=9h050b0y0H0V0M0A0n0D0j0A0V0n0n0X010H0M0O010406050n0E0I0I0V0v0m040i0B0~0d0P050c0~1012140|0O04051i1b1l0c1i0|0b0M0o0,0.0:0=0Z0M0P0Z0A1z0Z0H0`050%0K0A0y1u0/0;011y1A1C1A0H1I1K1G0H0v1j0H0Z0,0l0*0O0V0d0=0h011M1w010p0)0y0d0V0I0y1G0n1*0d1:1O1?1K1_1{0`0a0D16180P0n0o0l0v0n0j1B0V1a1c1 1j0c1#2o1Y1!1Z1H0b210=1C0d1^0l0n1G1r1t0-1N2y0M2A0d0l2F1G0O0v0y1j1~1+2o2U0d2T1 2x012M0v110A0`0D0J1b2X0{0}2!2H1;2%2)2+0h2.2n0|2X2#2^0V2*040D0G2|2V2~2=1v1O31330D0C372Y391+302f2_340g3h2:2 2?3c3m322+0W3q3j203t0=3d2+0q3z2;3k3C2$3v3e0k3H3s3b3D3M2+0Y3P3a2I3L2(3w040J0r3W3J3R3Z3n0J2-2m383I3B3+3E3$2{3:3i3=3l3!330J363{3r3X2@3T3$3g433A3~3-3p4a3}3K3^0J3y4f3Q3Y4i3G431m2R2o2F2r0b1!2w3K0j2N1|1j4u1k4s3=2W2n054A0#2Z3*3Y0w0`0#0p3q0D4g3@0p0`0o0y2g2i0A0E0y0:0y0A0d3q4W3Y0_040e4/4m2@0`0w0.0v0H0y0f0H4^451O4=0T4U4:4`042h1B4)4+0A534O1;4=0Q0R3z0D5o4V4_3c4{4}4 51585r0=0l0`0X5x543D5t125v524q5y015A040s5h3?4n0`0E0O0O4#5Q2#4=0e0Q5D5i1O0j0J0`030D0d0E0v0D0L0v2C0n0K0E2i0n1I1^3z065p5q5E2$0`0P0y0Z0y0M0I5I5%5R1;5N5C43635(0=0n1.04020x0E0l0H0t6q6s6u6062591O4Q040p2f6e305G0v0S6a2i5 6j6B5z0u0`2K6H4h6J6d5K644=5m4a626A5L0d0`0/0j0M0M0N5/105X6P5L6h6V3@0K0`2f0b5Y3K5!713@6J6L0M6N4.6Z6l015k5n6(5o6Q65042A4)6;0 1{0v6{3Y6`6^646+046-6/7n6?7q7u7c5N0z7r5a5c4(4*0n4,6z7g6k6f6C6T4T7D7R5F7k0y7m6=7p7H1O5N020P6y7V306}046 744;0`4@7b7W016n0`6w6t0t0U7~7,2/7i5k6$2/617P6)7v0`7l0y7A7$7-3K5N0F6i2/7Q2#0I0M0`0h4k88897g7i7w4!4$0Z0l0K1^4*0N77797%5z5B8K2$7/2i7C845L737_6I7Y7!7o6@8S6!0`5$4a8w6(8y66686a6c505J8n7i7F8m2n8o6W048A5c8D8F0n8H6M697a8v8b7c6D2R0H5:968`8,0467696b6Y881b4L2S4r9p0c4E2p4w1b2s9w0V1J9r4u0|9s0$0(0*04.

Entschlüsselungsfunktion

Aufgabe 8: Entschlüsselungsfunktion

Schreibe nun eine Funktion entschluesseln, die einen Geheimtext zurück in Klartext verwandelt.

Hinweis: Entschlüsseln ist wie Verschlüsseln, nur rückwärts. Statt den Schlüssel zu addieren, musst du ihn...?

Teste:

print(entschluesseln("DQJULII", 3))  # → "ANGRIFF"
print(entschluesseln("KDOOR", 3))  # → "HALLO"

# Wichtiger Test:
text = "GEHEIM"
verschluesselt = verschluesseln(text, 5)
wieder_klar = entschluesseln(verschluesselt, 5)
print(text == wieder_klar)  # → True

###(De-)Aktiviert den Code nach der Zeile # Tests (Groß-/Kleinschreibung wird nicht beachtet)
(Ctrl+I)
Ein- oder Ausstieg aus dem "Split-Screen"-Modus
(Alt+: ; Ctrl, um die Spalten zu vertauschen)
Ein- oder Ausstieg aus dem "Vollbildmodus"
(Esc)
Kürzen/nicht kürzen der Rückmeldungen im Terminal (Standardausgabe & Stacktrace / Starte das Programm erneut zum Anwenden)
Wenn aktiviert, wird der aus dem Terminal kopierte Text in eine Zeile umgewandelt, bevor er in die Zwischenablage kopiert wird.
Verbleibende Versuche : 5/5

.128013d/n(x52Lc8Aoysvf70.;wrkqe+lö4 u-3tm1bGi_pg):z,a6=9h050b0z0I0V0N0B0o0E0j0B0V0o0o0X010I0N0P010406050o0F0J0J0V0w0n040i0C0~0d0Q050c0~1012140|0P04051i1b1l0c1i0|0b0N0p0,0.0:0=0Z0N0Q0Z0B1z0Z0I0`050%0L0B0z1u0/0;011y1A1C1A0I1I1K1G0I0w1j0I0Z0,0m0*0P0V0d0=0h011M1w010q0)0z0d0V0J0z1G0o1*0d1:1O1?1K1_1{0`0a0E16180Q0o0p0m0w0o0j1B0V1a1c1 1j0c1#2o1Y1!1Z1H0b210=1C0d1^0m0o1G1r1t0-1N2y0N2A0d0m2F1G0P0w0z1j1~1+2o2U0d2T1 2x012M0w110B0`0E0K1b2X0{0}2!2H1;2%2)2+0h2.2n0|2X2#2^0V2*040E0H2|2V2~2=1v1O31330E0D372Y391+302f2_340g3h2:2 2?3c3m322+0W3q3j203t0=3d2+0r3z2;3k3C2$3v3e0k3H3s3b3D3M2+0Y3P3a2I3L2(3w040K0s3W3J3R3Z3n0K2-2m383I3B3+3E3$2{3:3i3=3l3!330K363{3r3X2@3T3$3g433A3~3-3p4a3}3K3^0K3y4f3Q3Y4i3G431m2R2o2F2r0b1!2w3K0j2N1|1j4u1k4s3=2W2n054A0#2Z3*3Y0x0`0#0q3q0E4g3@0q0`1^0I2h1B0F0z0:0z0B0d3q4W3Y0_040e4.4m2@0`0Q0z0Z0z0N0J0I0z0f0I4@451O4;0U4U4/4_044$0B4(4*0B554O1;4;0R0S3z0E5q4V4^3c4`4|4~505254435s560=0m0`0X5a5t3D5v4}4 51535j3?3Y5F040t5Q300`0F0P0P0z0w5W3K4;0e0R5I5D010j0K0`030E0d0F0w0E0M0w2C0o0L0F2i0o1I1^3z065r5C5k5u040x0.0w5O5A2/695R1;5T5H5B5b1O0o1.04020y0F0m0I0u6u6w6y66686p0=4Q040q2f5-6a5K044{5M0J0T4~2i656o5J010m0v0`2K6L6k6b6P5x6g5(3+4;5o4a686E6X0d0`0/0j0N0N0O5^105$6%2#6m724h0L0`2f0b6-4:0`4?4q6@5L5x6S0N6U4-7f5.5m5p6=5q6F2$0`2A4(6~0 1{5%6W5.747C6M7u046`6|7y707B6i7t5T0G753@0`5e5g0o4+6D7r6j2#6H0N4T7F6(6N7w0z7L7A7S5S0`020B6C7*307704797b5l7d7 6q6s6A6x0u0l857_2/7t5m6:2/677!6?5.6^047-7/717`3K5T0A6n7O6X0J0N0`0h4k8f8g7r7t8k0p5$4$0m0L1^4)0O7j7l7;6l5G8Q3c7|2i7N4J6X5*827,0z7x6 7:7n7G7p4a8C6=8E0`6d126,8p3+8r8t2n7#4h0`8G2g2i8J8L0o8N6T4}7m8B8i7G6H2R0I5_9a8}8;6c6e8^8f1b4L2S4r9r0c4E2p4w1b2s9y0V1J9t4u0|9u0$0(0*04.

Substitutionschiffre

Angriff auf die Substitutionschiffre

Wir versetzen uns nun in die Schuhe eines Angreifers, welcher plant einen Geheimtext zu entschlüsseln, aber ohne Kenntnisse vom Schlüssel! Ist dies überhaupt möglich?

Dazu könnte der Angreifer doch einfach alle möglichen Schlüssel ausprobieren...

Entschlüsselungszeit

Können wir überhaupt schnell genug die Schlüssel durchprobieren, damit wir in akzeptabler Zeit ein Geheimtext ohne bekannten Schlüssel entschlüsseln können?

Dazu messen wir die Zeit, die der Rechner benötigt, um einen Schlüssel auszuprobieren. In der Bibliothek von Python finden wir dazu eine passende Funktion:

import time
time.perf_counter()
Diese Funktion ist eine Art "digitale Stoppuhr". Diese "Stoppuhr" startet zu irgendeinem Zeitpunkt (z.B. wenn der Rechner gestartet wird), und zählt ständig im Hintergrund weiter. Bei jedem Aufruf der Funktion erhalten wir eine Gleitkommazahl, mit ihrem aktuellen Wert.

Mit dieser Funktion können wir nun messen, wie lange unsere Entschlüsselungsfunktion braucht pro Schlüssel.

Aufgabe 9: Substitutionsverschlüsselung Dauer

Wie können wir mit der Zeitfunktion nun eine Zeitdauer messen? Messe, wie viel Zeit die Entschlüsselungsfunktion benötigt für den Geheimtext IRHHO.

###(De-)Aktiviert den Code nach der Zeile # Tests (Groß-/Kleinschreibung wird nicht beachtet)
(Ctrl+I)
Ein- oder Ausstieg aus dem "Split-Screen"-Modus
(Alt+: ; Ctrl, um die Spalten zu vertauschen)
Ein- oder Ausstieg aus dem "Vollbildmodus"
(Esc)
Kürzen/nicht kürzen der Rückmeldungen im Terminal (Standardausgabe & Stacktrace / Starte das Programm erneut zum Anwenden)
Wenn aktiviert, wird der aus dem Terminal kopierte Text in eine Zeile umgewandelt, bevor er in die Zwischenablage kopiert wird.
Verbleibende Versuche : 5/5

.128013d/n2Lcoysvfrelö utm1bipga=h050b0n0s0z0w0o0j0q0g0o0z0j0j0A010s0w0x010406050j0r0t0t0z0m0i040f0p0Z0d0y050c0Z0#0%0)0X0x04050`0:0}0c0`0X0b0w0k0K0M0O0Q0B0w0y0B0o1b0B0s0V050F0v0o0n160N0P011a1c1e1c0s1k1m1i0s0m0{0s0B0K0h0I0x0z0d0Q0e011o18010l0H0n0d0z0t0n1i0j1I0d1O1q1R1m1U1W0V0a0q0+0-0y0j0k0h0m0j0g1d0z0/0;1!0{0c1D201A1C1B1j0b1$0Q1e0d1T0h0j1i13150L1p2a0w2c0d0h2h1i0x0m0n0{1Z1J202w0d2v1!29012o0m0$0o0V0u0:2z202s2u0:2h230b1C282j1P0g2p1X0{2R0|2t2B2x2L1 052Y0D2)1#2W1q0g0u0V032`2+2x0X0c2.2P102(2Q142S2326210z1l312R2~0D0F0H0j04.
Brute-Force-Angriff auf die Substitutionschiffre

Unser Ziel ist es nun den folgenden Geheimtext zu entschlüsseln, ohne Kenntnis des Schlüssels! In diesem Text treten nur die Buchstaben EIKLNORST plus Leerzeichen auf. Wir nehmen nun an, dass die Leerzeichen nicht verschlüsselt worden sind.

ELOI RITLS KNOITK ELSKLI LOEKLL

Wir wollen versuchen diesen Geheimtext mit der Methode der "roher Gewalt" zu brechen. Dazu müssen wir alle Möglichkeiten durchprobieren.

Aufgabe: Substitutionsverschlüsselung Angriff

Schreibe ein Programm um alle möglichen Schlüssel zu probieren.

###(De-)Aktiviert den Code nach der Zeile # Tests (Groß-/Kleinschreibung wird nicht beachtet)
(Ctrl+I)
Ein- oder Ausstieg aus dem "Split-Screen"-Modus
(Alt+: ; Ctrl, um die Spalten zu vertauschen)
Ein- oder Ausstieg aus dem "Vollbildmodus"
(Esc)
Kürzen/nicht kürzen der Rückmeldungen im Terminal (Standardausgabe & Stacktrace / Starte das Programm erneut zum Anwenden)
Wenn aktiviert, wird der aus dem Terminal kopierte Text in eine Zeile umgewandelt, bevor er in die Zwischenablage kopiert wird.

.128013d/n2Lcoysvfrelö utm1bipga=h050b0n0s0z0w0o0j0q0g0o0z0j0j0A010s0w0x010406050j0r0t0t0z0m0i040f0p0Z0d0y050c0Z0#0%0)0X0x04050`0:0}0c0`0X0b0w0k0K0M0O0Q0B0w0y0B0o1b0B0s0V050F0v0o0n160N0P011a1c1e1c0s1k1m1i0s0m0{0s0B0K0h0I0x0z0d0Q0e011o18010l0H0n0d0z0t0n1i0j1I0d1O1q1R1m1U1W0V0a0q0+0-0y0j0k0h0m0j0g1d0z0/0;1!0{0c1D201A1C1B1j0b1$0Q1e0d1T0h0j1i13150L1p2a0w2c0d0h2h1i0x0m0n0{1Z1J202w0d2v1!29012o0m0$0o0V0u0:2z202s2u0:2h230b1C282j1P0g2p1X0{2R0|2t2B2x2L1 052Y0D2)1#2W1q0g0u0V032`2+2x0X0c2.2P102(2Q142S2326210z1l312R2~0D0F0H0j04.

Häufigkeitsanalyse

Wir wissen bereits, dass im allgemeinenen ein Brute-Force-Angriff auf die reguläre Substitutionsverschlüsselung nicht in nützlicher Zeit durchführbar ist. Wir können sie aber einfach angreifen, in dem wir zusätzliche (unversteckte) Informationen aus dem Geheimtext in den Angriff miteinbeziehen: die Buchstabenhäufigkeit. Dazu führt man eine Häufigkeitsanalyse durch. Um dies einfacher zu Programmieren, wollen wir zuerst eine weitere Datenstruktur kennenlernen: das "Wörterbuch" (dictionary) bzw. das assoziative Array.

assoziatives Array/Wörterbuch

Eine praktische neue Datenstruktur ist das assoziative Array. Darin können Elemente gespeichert werden, ähnlich wie bei einem normalen Array. Im normalen Array, wird über eine Ordnung auf ein Element zugegriffen, also über den Index, welcher z.B. auf das erste, zweite, dritte, i-te Element zugreift. Der Index ist dabei eine natürliche Zahl ≥ 0. Bei einem assoziativen Array wird nicht über einen Index auf ein Feld zugegriffen, sondern über einen Schlüssel, z.B. einen Buchstaben oder eine Zeichenkette. In Python können wir ein leeres assoziatives Array mit den geschweiften Klammern definieren.

wörterbuch = {}
Ein neues Element können wir hinzufügen in dem wir wie bei einem Array, über die eckigen Klammern [ ] den Schlüssel angeben und dem Element einen Wert zuweisen:

wörterbuch["meinSchlüssel"] = 15
Nun besitzt das assoziative Array ein Element mit Schlüssel meinSchlüssel und Wert 15.

Schlüssel Wert
meinSchlüssel 15

Ein weiteres Element kann in gleicher Weise hinzugefügt werden.

wörterbuch["andererSchlüssel"] = 99
Danach hat das assoziative Array den folgenden Inhalt:

Schlüssel Wert
meinSchlüssel 15
andererSchlüssel 99

Um auf ein Element zuzugreifen, können wir den Schlüssel analog zum Index bei einem normalen Array verwenden:

print(wörterbuch["meinSchlüssel"])

Um über ein assoziatives Array zu iterieren, d.h. mit einer Schleife auf alle Elemente zugreifen, können wir die for .. in ..-Schleife verwenden.

for schlüssel in wörterbuch:
    wert = wörterbuch[schlüssel]
    print(f"Schlüssel ist: {schlüssel} und Wert ist: {wert}")

Beispiel: assoziatives Array/ Wörterbuch

###(De-)Aktiviert den Code nach der Zeile # Tests (Groß-/Kleinschreibung wird nicht beachtet)
(Ctrl+I)
Ein- oder Ausstieg aus dem "Split-Screen"-Modus
(Alt+: ; Ctrl, um die Spalten zu vertauschen)
Ein- oder Ausstieg aus dem "Vollbildmodus"
(Esc)
Kürzen/nicht kürzen der Rückmeldungen im Terminal (Standardausgabe & Stacktrace / Starte das Programm erneut zum Anwenden)
Wenn aktiviert, wird der aus dem Terminal kopierte Text in eine Zeile umgewandelt, bevor er in die Zwischenablage kopiert wird.

Wörterbücher
Aufgabe: Wörterbücher

Erstelle ein neues und leeres assoziatives Array. Füge drei Elemente hinzu, mit den Schlüssel laenge, breite, kosten und frei gewählten Werten. Gib den Wert für den Schlüssel breite aus Gib alle Werte aus in dem du die for .. in ..-Schleife verwendest

###(De-)Aktiviert den Code nach der Zeile # Tests (Groß-/Kleinschreibung wird nicht beachtet)
(Ctrl+I)
Ein- oder Ausstieg aus dem "Split-Screen"-Modus
(Alt+: ; Ctrl, um die Spalten zu vertauschen)
Ein- oder Ausstieg aus dem "Vollbildmodus"
(Esc)
Kürzen/nicht kürzen der Rückmeldungen im Terminal (Standardausgabe & Stacktrace / Starte das Programm erneut zum Anwenden)
Wenn aktiviert, wird der aus dem Terminal kopierte Text in eine Zeile umgewandelt, bevor er in die Zwischenablage kopiert wird.

.128013d/n2Lcoysvfrelö utm1bipga=h050b0n0s0z0w0o0j0q0g0o0z0j0j0A010s0w0x010406050j0r0t0t0z0m0i040f0p0Z0d0y050c0Z0#0%0)0X0x04050`0:0}0c0`0X0b0w0k0K0M0O0Q0B0w0y0B0o1b0B0s0V050F0v0o0n160N0P011a1c1e1c0s1k1m1i0s0m0{0s0B0K0h0I0x0z0d0Q0e011o18010l0H0n0d0z0t0n1i0j1I0d1O1q1R1m1U1W0V0a0q0+0-0y0j0k0h0m0j0g1d0z0/0;1!0{0c1D201A1C1B1j0b1$0Q1e0d1T0h0j1i13150L1p2a0w2c0d0h2h1i0x0m0n0{1Z1J202w0d2v1!29012o0m0$0o0V0u0:2z202s2u0:2h230b1C282j1P0g2p1X0{2R0|2t2B2x2L1 052Y0D2)1#2W1q0g0u0V032`2+2x0X0c2.2P102(2Q142S2326210z1l312R2~0D0F0H0j04.
Häufigkeitsanalyse
Aufgabe: Häufigkeitsanalyse

Mithilfe von assoziativen Arrays kannst du nun eine Häufigkeitsanalyse durchführen. Analysiere den nachfolgenden Geheimtext.

Wenn man überprüfen möchte, ob ein bestimmter Eintrag in einem assoziativen Array schon vorhanden ist, können wir das in Schlüsselwort verwenden:

a = { }
a["land"] = "Schweiz"

if "land" in a:
    print("Wert zu Schlüssel land ist vorhanden")

if "ort" in a:
    print("Wert zu Schlüssel ort ist vorhanden")
else:
    print("Wert zu Schlüssel ort ist nicht vorhanden")

###(De-)Aktiviert den Code nach der Zeile # Tests (Groß-/Kleinschreibung wird nicht beachtet)
(Ctrl+I)
Ein- oder Ausstieg aus dem "Split-Screen"-Modus
(Alt+: ; Ctrl, um die Spalten zu vertauschen)
Ein- oder Ausstieg aus dem "Vollbildmodus"
(Esc)
Kürzen/nicht kürzen der Rückmeldungen im Terminal (Standardausgabe & Stacktrace / Starte das Programm erneut zum Anwenden)
Wenn aktiviert, wird der aus dem Terminal kopierte Text in eine Zeile umgewandelt, bevor er in die Zwischenablage kopiert wird.

.128013d/n(}x52Lc8[oysvf70äw]{rke+lö4 u3tm1bipg:)a6=9h050b0A0I0R0M0C0p0F0k0C0R0p0p0T010I0M0N010406050p0G0J0J0R0y0o040j0D0`0d0O050c0`0|0~100^0N04051e171h0c1e0^0b0M0q0(0*0,0.0V0M0O0V0C1v0V0I0?050Z0L0C0A1q0+0-011u1w1y1w0I1E1G1C0I0y1f0I0V0(0n0$0N0R0d0.0i011I1s010r0#0A0d0R0J0A1C0p1$0d1,1K1/1G1=1@0?0a0F12140O0p0q0n0y0p0k1x0R16181{1f0c1X2k1U1W1V1D0b1}0.1y0d1;0n0p1C1n1p0)1J2u0M2w0d0n2B1C0N0y0A1f1`1%2k2Q0d2P1{2t012I0y0}0C0?0F0K172T0@0_2W2D1-2Z2#2%0i2*2j0^2T2X2;0R2$040F0H2^2R2`2.1r1K2}2 0F0E332U351%2|2b2=300h3d2,2{2/383i2~2%0S3m3f1|3p0.392%0s3v2-3g3y2Y3r3a0l3D3o373z3I2%0U3L362E3H2!3s040K0t3m1i2N2k2B2n0b1W2s3G0k2J1^1f3)1g3%3E2U3#3/0X2V3F3N2Y0?0V0u0G1/0O0z0A0M0I1;3m0F3_2X0n0?0T4d4f3G0=040x0f3v3w2X0z0?0r2b4k3M3U0d0?0k4y3T1-0n0v0?2G4E3 4A0?0O0A0V490J4b0g0I3#4z1-4n0P4r0F4%4e4Y1K4u040M0r4L3x404B044D2i2R4)4F1K4H4J0d4:2|424446484a4c4_3`4*0.4!3v4(5f4{4M2:53451v564b50593~4;3U4n0m4X4|3z4C5w5i1K4n0w513G4h044j5q5h5s5j04435l47495o5A5M5C0?5v5q4l4=5z5Z5b015D5F405H0B5+3U0J0M0?2)5q065f5!3U4,0A0$0A5U2X5d5^5g4(5{5N5P555S582+675W045Y6d5(4?4^6i5x5)0?5E5K6e0.5H5J2+5L2X5;5?4r6s2Y0L0?2M2G4W5%6n4n0e613G4?695m6b5p6m5B5c0?0Q3D0c3|2O3$6$0c3?2l3+172o6-0R1F6(3)0^6)0Y0!0$04.
Aufgabe: Häufigkeitsanalyse Visualisieren

Kopiere dein Programm zur Häufigkeitsanalyse und stelle nun die Ergebnisse als Balkendiagramm dar.

Die Funktion für das Balkendiagramm plt.bar verlangt zwei Parameter: der erste für die x-Achse und der zweite für die y-Achse. Wir brauchen dazu vom assoziativen Array einmal alle Schlüssel als Array und einmal alle Werte als Array, das geht folgendermassen:

schlüssel = hf.keys()
werte = hf.values()
print(f"Alle SchlüsseL: {schlüssel}")
print(f"Alle Werte: {werte}")

Zusatz: Ignoriere die Sonderzeichen (Leerzeichen, Komma, etc.)

Deine Abbildung

Deine Abbildung wird hier erscheinen

###(De-)Aktiviert den Code nach der Zeile # Tests (Groß-/Kleinschreibung wird nicht beachtet)
(Ctrl+I)
Ein- oder Ausstieg aus dem "Split-Screen"-Modus
(Alt+: ; Ctrl, um die Spalten zu vertauschen)
Ein- oder Ausstieg aus dem "Vollbildmodus"
(Esc)
Kürzen/nicht kürzen der Rückmeldungen im Terminal (Standardausgabe & Stacktrace / Starte das Programm erneut zum Anwenden)
Wenn aktiviert, wird der aus dem Terminal kopierte Text in eine Zeile umgewandelt, bevor er in die Zwischenablage kopiert wird.

.128013d/n2Lcoysvfrelö utm1bipga=h050b0n0s0z0w0o0j0q0g0o0z0j0j0A010s0w0x010406050j0r0t0t0z0m0i040f0p0Z0d0y050c0Z0#0%0)0X0x04050`0:0}0c0`0X0b0w0k0K0M0O0Q0B0w0y0B0o1b0B0s0V050F0v0o0n160N0P011a1c1e1c0s1k1m1i0s0m0{0s0B0K0h0I0x0z0d0Q0e011o18010l0H0n0d0z0t0n1i0j1I0d1O1q1R1m1U1W0V0a0q0+0-0y0j0k0h0m0j0g1d0z0/0;1!0{0c1D201A1C1B1j0b1$0Q1e0d1T0h0j1i13150L1p2a0w2c0d0h2h1i0x0m0n0{1Z1J202w0d2v1!29012o0m0$0o0V0u0:2z202s2u0:2h230b1C282j1P0g2p1X0{2R0|2t2B2x2L1 052Y0D2)1#2W1q0g0u0V032`2+2x0X0c2.2P102(2Q142S2326210z1l312R2~0D0F0H0j04.