Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen der Seite angezeigt.
| Beide Seiten, vorherige Überarbeitung Vorherige Überarbeitung | |||
| gf_informatik:verschluesselung:symmetrisch [2026-04-02 20:18] – hof | gf_informatik:verschluesselung:symmetrisch [2026-04-02 20:20] (aktuell) – hof | ||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| ## Symmetrische Verschlüsselung | ## Symmetrische Verschlüsselung | ||
| + | < | ||
| Wir können nun beliebige Zeichenfolgen [[gf_informatik: | Wir können nun beliebige Zeichenfolgen [[gf_informatik: | ||
| Zeile 176: | Zeile 177: | ||
| * Dokumentiere die Resultate in OneNote / Word / Latex / Jupyter. | * Dokumentiere die Resultate in OneNote / Word / Latex / Jupyter. | ||
| - | < | + | < |
| + | # In normal python: pip install opencv-python numpy | ||
| + | import micropip | ||
| + | await micropip.install([" | ||
| + | |||
| + | import cv2 as cv | ||
| + | import numpy as np | ||
| + | import math | ||
| + | import random | ||
| + | |||
| + | def text_to_bytes(text): | ||
| + | """ | ||
| + | numbers = [] | ||
| + | for letter in text: | ||
| + | number = ord(letter) | ||
| + | numbers.append(number) | ||
| + | return numbers | ||
| + | |||
| + | def bytes_to_text(numbers): | ||
| + | """ | ||
| + | text = "" | ||
| + | for number in numbers: | ||
| + | letter = chr(number) | ||
| + | text += letter | ||
| + | return text | ||
| + | |||
| + | def binary_to_bytes(binstring): | ||
| + | """ | ||
| + | binstring *= 8 # ensure we are byte-aligned | ||
| + | result = [] | ||
| + | for eight in range(0, len(binstring), | ||
| + | result.append(int(binstring[eight: | ||
| + | return result | ||
| + | |||
| + | def xor(one, two): | ||
| + | result = [] | ||
| + | for i in range(len(one)): | ||
| + | result.append(one[i] ^ two[i]) | ||
| + | return result | ||
| + | |||
| + | def block_encrypt(one, | ||
| + | # In reality, this would be a more complex operation, such as a sequence of | ||
| + | # [s-boxes](https:// | ||
| + | return xor(one, two) | ||
| + | |||
| + | def block_decrypt(one, | ||
| + | # In reality, this would be the inverse of block_encrypt. | ||
| + | return xor(two, one) | ||
| + | |||
| + | def encrypt(plain_bytes, | ||
| + | """ | ||
| + | * chaining=True: | ||
| + | * chaining=False: | ||
| + | The returned ciphertext starts with the IV block. | ||
| + | """ | ||
| + | # random initialization vector | ||
| + | iv = list(random.randbytes(block_size)) | ||
| + | |||
| + | # ensure our key material is divisible by block_size | ||
| + | key_bytes = key_bytes * block_size | ||
| + | |||
| + | previous_block = iv | ||
| + | cipher_bytes = iv | ||
| + | |||
| + | for i in range(0, len(plain_bytes), | ||
| + | plain_block = plain_bytes[i: | ||
| + | key_index = i % len(key_bytes) | ||
| + | key_block = key_bytes[key_index: | ||
| + | if chaining: | ||
| + | plain_block = xor(plain_block, | ||
| + | cipher_block = block_encrypt(plain_block, | ||
| + | cipher_bytes += cipher_block | ||
| + | previous_block = cipher_block | ||
| + | |||
| + | return cipher_bytes | ||
| + | |||
| + | def decrypt(cipher_bytes, | ||
| + | """ | ||
| + | * chaining=True: | ||
| + | * chaining=False: | ||
| + | The ciphertext is expected to start with the IV block, even in ECB mode. | ||
| + | """ | ||
| + | |||
| + | # ensure our key material is divisible by block_size | ||
| + | key_bytes = key_bytes * block_size | ||
| + | |||
| + | # recover the IV | ||
| + | previous_block = cipher_bytes[0: | ||
| + | plain_bytes = [] | ||
| + | |||
| + | # The decrypted first block is ignored... | ||
| + | for i in range(block_size, | ||
| + | cipher_block = cipher_bytes[i: | ||
| + | key_index = (i-block_size) % len(key_bytes) | ||
| + | key_block = key_bytes[key_index: | ||
| + | plain_block = block_decrypt(cipher_block, | ||
| + | if chaining: | ||
| + | plain_block = xor(plain_block, | ||
| + | plain_bytes += plain_block | ||
| + | previous_block = cipher_block | ||
| + | return plain_bytes | ||
| + | |||
| + | |||
| + | def bytes_to_image(img_bytes, | ||
| + | as_np = np.asarray(img_bytes, | ||
| + | as_np = as_np.reshape(shape) | ||
| + | return as_np | ||
| + | |||
| + | # Play with different keys: | ||
| + | #key = " | ||
| + | key = " | ||
| + | key_bytes = binary_to_bytes(key) | ||
| + | #key_bytes = text_to_bytes(" | ||
| + | key_bytes = text_to_bytes(" | ||
| + | |||
| + | # Change between ECB and CBC modes: | ||
| + | chaining = False # False: ECB, True: CBC | ||
| + | |||
| + | img_url = ' | ||
| + | # 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), | ||
| + | img = cv.imdecode(arr, | ||
| + | img_bytes = img.tobytes() | ||
| + | |||
| + | img_encrypted = encrypt(img_bytes, | ||
| + | |||
| + | # We drop the first block as it's only used as initialization vector. | ||
| + | cv.imshow(" | ||
| + | cv.waitKey() | ||
| + | |||
| + | # Test if decryption works | ||
| + | # img_decrypted = decrypt(img_encrypted, | ||
| + | # cv.imshow(" | ||
| + | # cv.waitKey() | ||
| + | </ | ||