Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen der Seite angezeigt.

Link zu der Vergleichsansicht

Beide Seiten, vorherige Überarbeitung Vorherige Überarbeitung
Nächste Überarbeitung
Vorherige Überarbeitung
gf_informatik:verschluesselung:symmetrisch [2025-03-31 20:39] – [Herausforderung: Verkettung] hofgf_informatik:verschluesselung:symmetrisch [2026-04-02 20:20] (aktuell) hof
Zeile 1: Zeile 1:
 ## Symmetrische Verschlüsselung ## Symmetrische Verschlüsselung
 +<html><script type="module" src="https://bottom.ch/editor/stable/bottom-editor.js"></script></html>
  
 Wir können nun beliebige Zeichenfolgen [[gf_informatik:verschluesselung:codierung|codieren]] und mit einer XOR-Operation verschlüsseln. Die Verschlüsselung erfolgt dabei blockweise, wobei jeder Block genau die Länge des Schlüssels hat. Die Verschlüsselung folgt diesem Schema: Wir können nun beliebige Zeichenfolgen [[gf_informatik:verschluesselung:codierung|codieren]] und mit einer XOR-Operation verschlüsseln. Die Verschlüsselung erfolgt dabei blockweise, wobei jeder Block genau die Länge des Schlüssels hat. Die Verschlüsselung folgt diesem Schema:
Zeile 27: Zeile 28:
   * Statistische Methoden könnten die Entschlüsselung ermöglichen, weil jeder Buchstabe an derselben Block-Position gleich verschlüsselt wird.   * Statistische Methoden könnten die Entschlüsselung ermöglichen, weil jeder Buchstabe an derselben Block-Position gleich verschlüsselt wird.
   * Wiederkehrende Wörter, insbesondere am Anfang der Nachricht, fallen schnell auf.   * Wiederkehrende Wörter, insbesondere am Anfang der Nachricht, fallen schnell auf.
-    * Die Enigma konnte im zweiten Weltkrieg auch deshalb geknackt werden, weil einige Wörter immer wieder auftauchten, z.B. `OBERKOMMANDODERWEHRMACHT`+    * Die [[wpde>Enigma_(Maschine)#Kryptographische_Schwächen|Enigma]] konnte im zweiten Weltkrieg auch deshalb geknackt werden, weil einige Wörter immer wieder auftauchten, z.B. `OBERKOMMANDODERWEHRMACHT`
   * Ein Angreifer könnte einen verschlüsselten Block in eine Nachricht einfügen, ohne den genauen Klartext zu kennen. Damit könnte er die Nachricht verfälschen.   * Ein Angreifer könnte einen verschlüsselten Block in eine Nachricht einfügen, ohne den genauen Klartext zu kennen. Damit könnte er die Nachricht verfälschen.
     * Fällt dir ein Beispiel ein, wie dies ausgenützt werden könnte?     * Fällt dir ein Beispiel ein, wie dies ausgenützt werden könnte?
Zeile 51: Zeile 52:
  
 {{ :gf_informatik:verschluesselung:illustrated_ecb_cbc.jpg?nolink&693 |}} {{ :gf_informatik:verschluesselung:illustrated_ecb_cbc.jpg?nolink&693 |}}
 +
 ### Herausforderung: Verkettung ### Herausforderung: Verkettung
  
Zeile 159: Zeile 161:
 ### Verkettung ausprobieren ### Verkettung ausprobieren
  
-Du benötigst ein Bild, z.B. {{:gf_informatik:verschluesselung:penguin.png&nolink|}}.+Wende eine einfache Block-Verschlüsselung im ECB bzw. CBC-Modus an, und dokumentieren den Effekt in einem Dokument (OneNote, Word, Latex...). 
 +  * Wie sieht das verschlüsselte Bild aus? 
 +  * Was passiert mit anderen (längeren) Schlüsseln? 
 +  * Warum ist ein Schlüssel nur aus Grossbuchstaben ungünstig? 
 + 
 + 
 +#### Vorgehen 
 + 
 +Du benötigst ein Bild, z.B. {{:gf_informatik:verschluesselung:penguin.png?linkonly|}}. 
 + 
 +Speichere den folgenden Code in VS Code. Der Code verwendet die OpenCV-Bibliothek zur Bildverarbeitung. Sie muss einmalig im Terminal mit `python -m pip install opencv-python` installiert werden. 
 + 
 +  * Führe den Code aus - was zeigt das Bild? 
 +  * Ändere den Code, um den Effekt von verschiedenen Schlüssellängen und von _Chaining_ auf das Chiffrat auszuprobieren! 
 +  * Dokumentiere die Resultate in OneNote / Word / Latex / Jupyter. 
 + 
 +<html><bottom-editor layout="split"> 
 +# In normal python: pip install opencv-python numpy 
 +import micropip 
 +await micropip.install(["numpy", "opencv-python"]);
  
-Zudem den folgenden Code: 
-<code python block_coder.py> 
 import cv2 as cv import cv2 as cv
 import numpy as np import numpy as np
 import math import math
 +import random
  
 def text_to_bytes(text): def text_to_bytes(text):
Zeile 184: Zeile 204:
  
 def binary_to_bytes(binstring): def binary_to_bytes(binstring):
 +    """Returns the list of bytes corresponding to the binary-interpreted sequences of 1s and 0s."""
     binstring *= 8  # ensure we are byte-aligned     binstring *= 8  # ensure we are byte-aligned
     result = []     result = []
Zeile 196: Zeile 217:
     return result     return result
  
-def block_coder(one, two):+def block_encrypt(one, two):
     # In reality, this would be a more complex operation, such as a sequence of     # In reality, this would be a more complex operation, such as a sequence of
     # [s-boxes](https://de.wikipedia.org/wiki/S-Box).     # [s-boxes](https://de.wikipedia.org/wiki/S-Box).
     return xor(one, two)     return xor(one, two)
  
-def block_encrypt(plain_byteskey_bytes, previous_block): +def block_decrypt(onetwo): 
-    # Chaining Block Cipher: Encrypt a single block but first  +    # In reality, this would be the inverse of block_encrypt
-    # xor the previous encrypted block with the plain text+    return xor(twoone)
-    return block_coder(xor(plain_bytes, previous_block)key_bytes)+
  
-def block_decrypt(cipher_bytes, key_bytes, previous_block): +def encrypt(plain_bytes, key_bytes, chaining=True, block_size=8): 
-    # Chaining Block Cipher: Encrypt single block but first  +    """Block-encrypt sequence of plaintext bytes with key
-    # xor the previous encrypted block with the plain text+      chaining=True: CBC mode 
-    return xor(block_coder(cipher_bytes, key_bytes), previous_block) +      * chaining=FalseECB mode 
- +      The returned ciphertext starts with the IV block. 
-def encrypt(plain_bytes, key_bytes, chaining=True, initialization_vector='12345678')+    """ 
-    block_size = len(initialization_vector) +    # random initialization vector 
-    iv = text_to_bytes(initialization_vector)+    iv = list(random.randbytes(block_size))
  
     # ensure our key material is divisible by block_size     # ensure our key material is divisible by block_size
     key_bytes = key_bytes * block_size     key_bytes = key_bytes * block_size
  
-    first_block text_to_bytes('a'*block_size) +    previous_block iv 
-    cipher_bytes = block_encrypt(first_block, key_bytes[0:block_size], iv+    cipher_bytes = iv
-    previous_block = cipher_bytes+
  
     for i in range(0, len(plain_bytes), block_size):     for i in range(0, len(plain_bytes), block_size):
         plain_block = plain_bytes[i:i+block_size]         plain_block = plain_bytes[i:i+block_size]
-        key_index = (i+block_size) % len(key_bytes)+        key_index = i % len(key_bytes)
         key_block = key_bytes[key_index:key_index+block_size]         key_block = key_bytes[key_index:key_index+block_size]
         if chaining:         if chaining:
             plain_block = xor(plain_block, previous_block)             plain_block = xor(plain_block, previous_block)
-        cipher_block = block_coder(plain_block, key_block)+        cipher_block = block_encrypt(plain_block, key_block)
         cipher_bytes += cipher_block         cipher_bytes += cipher_block
         previous_block = cipher_block         previous_block = cipher_block
Zeile 235: Zeile 254:
  
 def decrypt(cipher_bytes, key_bytes, chaining=True, block_size = 8): def decrypt(cipher_bytes, key_bytes, chaining=True, block_size = 8):
 +    """Block-decrypt a sequence of ciphertext bytes with key.
 +      * chaining=True: CBC mode
 +      * chaining=False: ECB mode
 +      The ciphertext is expected to start with the IV block, even in ECB mode.
 +    """
 +
     # ensure our key material is divisible by block_size     # ensure our key material is divisible by block_size
     key_bytes = key_bytes * block_size     key_bytes = key_bytes * block_size
  
 +    # recover the IV
     previous_block = cipher_bytes[0:block_size]     previous_block = cipher_bytes[0:block_size]
     plain_bytes = []     plain_bytes = []
Zeile 244: Zeile 270:
     for i in range(block_size, len(cipher_bytes), block_size):     for i in range(block_size, len(cipher_bytes), block_size):
         cipher_block = cipher_bytes[i:i+block_size]         cipher_block = cipher_bytes[i:i+block_size]
-        key_index = i % len(key_bytes)+        key_index = (i-block_size) % len(key_bytes)
         key_block = key_bytes[key_index:key_index+block_size]         key_block = key_bytes[key_index:key_index+block_size]
-        plain_block = block_coder(cipher_block, key_block)+        plain_block = block_decrypt(cipher_block, key_block)
         if chaining:         if chaining:
             plain_block = xor(plain_block, previous_block)             plain_block = xor(plain_block, previous_block)
Zeile 259: Zeile 285:
     return as_np     return as_np
  
-# Play with different keys +# Play with different keys: 
-key = "11110000011001101100010000110101110010111001100100010110000111110001100101000101101110111111000000000011000000111110010111101010111110001110101010101000001111001010110110100111000000000011111111010001111100110111101001111010000001011101010000101111110101001100010101001011011101110101011001110100100001101110110011000110100100111100010011001100100111000000000011011110000100010010001110101100111101010100111100010001010100101100111101101011100110110000000000101000000010100111110010000011101000111001100000101011110000000100110011000001000101001000011101000100100100100010100111110011101011010101010110001011010001001010000111000100100010111001111100011100001000011001100011100110101101111001000110001001111010111111100001111111111111011101100101111100000101000101100101011111111110001010111000101010110011011010111111101111110100000100100101001000100101100111100010101011111111001001101000011001101111000111111110101100001100110110000101100000000010111110001011011010010010000111010010011001101010010100000011101111110100101001111110011010000101001111001111000000010101111001000101100110010111101111001000010110111101000110110101000101110001001011100111110010111001011111111010000010011000011101100110111001001000110001110110011011000011001010001111000101100100001010110011000001011100001011010011010001110101010001111000000111111101110011000010010000111010111000111000110"+#key = "11110000011001101100010000110101110010111001100100010110000111110001100101000101101110111111000000000011000000111110010111101010111110001110101010101000001111001010110110100111000000000011111111010001111100110111101001111010000001011101010000101111110101001100010101001011011101110101011001110100100001101110110011000110100100111100010011001100100111000000000011011110000100010010001110101100111101010100111100010001010100101100111101101011100110110000000000101000000010100111110010000011101000111001100000101011110000000100110011000001000101001000011101000100100100100010100111110011101011010101010110001011010001001010000111000100100010111001111100011100001000011001100011100110101101111001000110001001111010111111100001111111111111011101100101111100000101000101100101011111111110001010111000101010110011011010111111101111110100000100100101001000100101100111100010101011111111001001101000011001101111000111111110101100001100110110000101100000000010111110001011011010010010000111010010011001101010010100000011101111110100101001111110011010000101001111001111000000010101111001000101100110010111101111001000010110111101000110110101000101110001001011100111110010111001011111111010000010011000011101100110111001001000110001110110011011000011001010001111000101100100001010110011000001011100001011010011010001110101010001111000000111111101110011000010010000111010111000111000110"
 key = "1111000001100110110001000011010111001011100110010001011000011111000110010100010110" key = "1111000001100110110001000011010111001011100110010001011000011111000110010100010110"
 key_bytes = binary_to_bytes(key) key_bytes = binary_to_bytes(key)
 +#key_bytes = text_to_bytes("rõménshÖRÑ")
 key_bytes = text_to_bytes("ROMANSHORN") key_bytes = text_to_bytes("ROMANSHORN")
  
-# Change between ECB and CBC modes+# Change between ECB and CBC modes:
 chaining = False  # False: ECB, True: CBC chaining = False  # False: ECB, True: CBC
  
-img cv.imread('encryption/penguin.png')+img_url = 'https://sca.ksr.ch/lib/exe/fetch.php?media=gf_informatik:verschluesselung:penguin.png' 
 +# In vanilla python, use urllib.request.urlopen(img_url) 
 +from pyodide.http import pyfetch 
 +response = await pyfetch(img_url) 
 +data = await response.bytes() 
 +arr = np.asarray(bytearray(data), dtype=np.uint8) 
 +img = cv.imdecode(arr, -1) # 'Load it as it is'
 img_bytes = img.tobytes() img_bytes = img.tobytes()
  
 img_encrypted = encrypt(img_bytes, key_bytes, chaining=chaining) img_encrypted = encrypt(img_bytes, key_bytes, chaining=chaining)
  
-# We drop the first block as it only used as initialization vector.+# We drop the first block as it'only used as initialization vector.
 cv.imshow("image", bytes_to_image(img_encrypted[8:], img.shape)) cv.imshow("image", bytes_to_image(img_encrypted[8:], img.shape))
-img_decrypted = decrypt(img_encrypted, key_bytes, chaining=chaining) 
 cv.waitKey() cv.waitKey()
  
 # Test if decryption works # Test if decryption works
 +# img_decrypted = decrypt(img_encrypted, key_bytes, chaining=chaining)
 # cv.imshow("image", bytes_to_image(img_decrypted, img.shape)) # cv.imshow("image", bytes_to_image(img_decrypted, img.shape))
 # cv.waitKey() # cv.waitKey()
-</code>+</bottom-editor></html>
  
  
  • gf_informatik/verschluesselung/symmetrisch.1743453594.txt.gz
  • Zuletzt geändert: 2025-03-31 20:39
  • von hof