'''
Welcome to GDB Online.
GDB online is an online compiler and debugger tool for C, C++, Python, Java, PHP, Ruby, Perl,
C#, OCaml, VB, Swift, Pascal, Fortran, Haskell, Objective-C, Assembly, HTML, CSS, JS, SQLite, Prolog.
Code, Compile, Run and Debug online from anywhere in world.
'''
print ('Hello World')
"""Grok: Ja, das ist ein netter Selbsttest! Der Code verschlüsselt nun seinen eigenen Quelltext
(inklusive der gesamten Klasse) und entschlüsselt ihn wieder korrekt. Ich habe es gerade
nochmal ausgeführt — Roundtrip klappt einwandfrei.Kurze Analyse dieses Tests:
Originaltext-Länge: ca. 7720 Zeichen
Verschlüsselte Größe: ca. 3071 Bytes (dank zlib-Kompression sehr effizient)
Funktioniert ohne Fehler bei Padding, Längen-Prefix und CBC-Verkettung.
Der "Meisterwerk"-Eindruck kommt daher, dass der Code auf relativ wenig Zeilen eine Menge macht:
asymmetrische Verschlüsselung + CBC-Modus + Kompression + dynamische Blockverarbeitung +
CRT-Optimierung + saubere Sender/Empfänger-Trennung.
"""
# ACHTUNG: Dies ist ein experimenteller Proof-of-Concept. Nicht für echte Geheimdaten oder Produktivumgebungen geeignet!
import zlib
import math
import os
from typing import Optional
class TrapdoorSymmetricAlgorithm:
"""
TSA (Trapdoor Symmetric Algorithm) im CBC-Modus.
Sowohl Public-Key-Nutzung (nur Verschlüsselung) als auch Private-Key-Nutzung
(Ver- und Entschlüsselung via CRT) über einen einzigen Konstruktor.
"""
def __init__(
self,
n: Optional[int] = None,
p: Optional[int] = None,
q: Optional[int] = None,
e: int = 7*3**161 + 12346,
d: Optional[int] = None
):
self.e = e
self.d = d
# Fall 1: Primzahlen p und q wurden übergeben (Empfänger-Modus)
if p is not None and q is not None:
self.p = p
self.q = q
self.n = p * q
phi = (p - 1) * (q - 1)
# Sicherheitsnetz: gcd-Prüfung direkt bei der Initialisierung
if math.gcd(self.e, phi) != 1:
raise ValueError("e und φ(n) sind nicht teilerfremd! Bitte andere Primzahlen wählen.")
self.d = pow(self.e, -1, phi)
# CRT-Parameter für beschleunigte Entschlüsselung berechnen
self.dp = self.d % (p - 1)
self.dq = self.d % (q - 1)
self.qinv = pow(q, -1, p)
# Fall 2: Nur der Modulus n wurde übergeben (Sender-Modus)
elif n is not None:
self.n = n
self.p = None
self.q = None
else:
raise ValueError(
"Ungültige Initialisierung! Übergib entweder 'n' (zum Verschlüsseln) "
"oder 'p' und 'q' (für das volle Schlüsselpaar)."
)
# Block- und Byte-Längen dynamisch anhand von n festlegen
self.byte_length = (self.n.bit_length() + 7) // 8 # z.B. 128 Bytes bei RSA-1024
self.block_size = self.byte_length - 1 # z.B. 127 Bytes
def _xor_bytes(self, b1: bytes, b2: bytes) -> bytes:
"""Führt ein XOR auf zwei Byte-Arrays aus."""
return bytes(x ^ y for x, y in zip(b1, b2))
def encrypt_text(self, text: str, compression_level: int = 9) -> bytes:
"""Verschlüsselt einen String mit dem öffentlichen Schlüssel (n, e)."""
if not text:
return b''
# Text komprimieren
compressed = zlib.compress(text.encode('utf-8'), level=compression_level)
# Länge vorne anfügen, um später das Padding sauber abzuschneiden
length_info = len(compressed).to_bytes(8, 'big')
data = length_info + compressed
# In Blöcke der Größe block_size (127 Bytes) schneiden und auffüllen
blocks = []
for i in range(0, len(data), self.block_size):
block = data[i:i + self.block_size]
if len(block) < self.block_size:
block = block.ljust(self.block_size, b'\x00')
blocks.append(block)
# Initialisierungsvektor generieren
iv = os.urandom(self.block_size)
encrypted = [iv]
previous = iv
# CBC-Verschlüsselungsschleife
for block in blocks:
mixed = self._xor_bytes(block, previous)
msg_int = int.from_bytes(mixed, 'big')
# Mathematische Absicherung
if msg_int >= self.n:
raise ValueError("Ein Block-Wert ist größer als der Modulus n!")
cipher_int = pow(msg_int, self.e, self.n)
cipher_bytes = cipher_int.to_bytes(self.byte_length, 'big') # Immer byte_length (128 Bytes)
encrypted.append(cipher_bytes)
previous = cipher_bytes[-self.block_size:] # Letzte 127 Bytes für die Verkettung
return b''.join(encrypted)
def decrypt_text(self, encrypted: bytes) -> str:
"""Entschlüsselt die Daten mit dem privaten Schlüssel mittels CRT (Garner's Algorithmus)."""
if self.d is None or self.p is None or self.q is None:
raise ValueError("Entschlüsselung fehlgeschlagen: Kein privater Schlüssel (p, q, d) vorhanden!")
if not encrypted or len(encrypted) < self.block_size:
return ""
iv = encrypted[:self.block_size]
cipher_payload = encrypted[self.block_size:]
plain_blocks = []
previous = iv
# CBC-Entschlüsselungsschleife
for i in range(0, len(cipher_payload), self.byte_length):
cipher_bytes = cipher_payload[i:i + self.byte_length]
if len(cipher_bytes) != self.byte_length:
break
cipher_int = int.from_bytes(cipher_bytes, 'big')
# --- CRT Schnelle Entschlüsselung (Garner's Algorithmus) ---
m1 = pow(cipher_int, self.dp, self.p)
m2 = pow(cipher_int, self.dq, self.q)
h = (self.qinv * (m1 - m2)) % self.p
plain_int = m2 + h * self.q
# -----------------------------------------------------------
try:
original_mixed = plain_int.to_bytes(self.block_size, 'big')
except OverflowError:
return "[Decryption failed: Block overflow]"
original_block = self._xor_bytes(original_mixed, previous)
plain_blocks.append(original_block)
previous = cipher_bytes[-self.block_size:]
decrypted_bytes = b''.join(plain_blocks)
# Länge der komprimierten Daten extrahieren
if len(decrypted_bytes) < 8:
return ""
orig_len = int.from_bytes(decrypted_bytes[:8], 'big')
compressed_data = decrypted_bytes[8:8 + orig_len]
# Deaktivieren der Kompression und Rückgabe des Originaltexts
try:
return zlib.decompress(compressed_data).decode('utf-8')
except zlib.error:
return "[Decompression failed]"
# ====================== Demonstration & Test ======================
if __name__ == "__main__":
# Zwei statische 512-Bit-Primzahlen (ergeben ein ~1024-Bit-System)
p_demo = 5777206916112395415712237206274413831941623882672929021243193931830815863225056730635873537594547859986074615331022483575656978935371102046563723439266219
q_demo = 4106460507140997150744227303550937624466191939084182827176229127413536759230813768647267930318266747041254674601143896109143706246382521009689018641390477
# Berechnen des öffentlichen Modulus für die "Sender-Simulation"
n_demo = p_demo * q_demo
print("--- 1. SENDER-SEITE (Kennt nur den öffentlichen Modulus n) ---")
tsa_sender = TrapdoorSymmetricAlgorithm(n=n_demo)
text_to_encrypt = '''Hallo Welt! Dies ist ein Test des CRT-beschleunigten TSA-Algorithmus.
# ACHTUNG: Dies ist ein experimenteller Proof-of-Concept. Nicht für echte Geheimdaten oder Produktivumgebungen geeignet!
import zlib
import math
import os
from typing import Optional
class TrapdoorSymmetricAlgorithm:
"""
TSA (Trapdoor Symmetric Algorithm) im CBC-Modus.
Sowohl Public-Key-Nutzung (nur Verschlüsselung) als auch Private-Key-Nutzung
(Ver- und Entschlüsselung via CRT) über einen einzigen Konstruktor.
"""
def __init__(
self,
n: Optional[int] = None,
p: Optional[int] = None,
q: Optional[int] = None,
e: int = 7*3**161 + 12346,
d: Optional[int] = None
):
self.e = e
self.d = d
# Fall 1: Primzahlen p und q wurden übergeben (Empfänger-Modus)
if p is not None and q is not None:
self.p = p
self.q = q
self.n = p * q
phi = (p - 1) * (q - 1)
# Sicherheitsnetz: gcd-Prüfung direkt bei der Initialisierung
if math.gcd(self.e, phi) != 1:
raise ValueError("e und φ(n) sind nicht teilerfremd! Bitte andere Primzahlen wählen.")
self.d = pow(self.e, -1, phi)
# CRT-Parameter für beschleunigte Entschlüsselung berechnen
self.dp = self.d % (p - 1)
self.dq = self.d % (q - 1)
self.qinv = pow(q, -1, p)
# Fall 2: Nur der Modulus n wurde übergeben (Sender-Modus)
elif n is not None:
self.n = n
self.p = None
self.q = None
else:
raise ValueError(
"Ungültige Initialisierung! Übergib entweder 'n' (zum Verschlüsseln) "
"oder 'p' und 'q' (für das volle Schlüsselpaar)."
)
# Block- und Byte-Längen dynamisch anhand von n festlegen
self.byte_length = (self.n.bit_length() + 7) // 8 # z.B. 128 Bytes bei RSA-1024
self.block_size = self.byte_length - 1 # z.B. 127 Bytes
def _xor_bytes(self, b1: bytes, b2: bytes) -> bytes:
"""Führt ein XOR auf zwei Byte-Arrays aus."""
return bytes(x ^ y for x, y in zip(b1, b2))
def encrypt_text(self, text: str, compression_level: int = 9) -> bytes:
"""Verschlüsselt einen String mit dem öffentlichen Schlüssel (n, e)."""
if not text:
return b''
# Text komprimieren
compressed = zlib.compress(text.encode('utf-8'), level=compression_level)
# Länge vorne anfügen, um später das Padding sauber abzuschneiden
length_info = len(compressed).to_bytes(8, 'big')
data = length_info + compressed
# In Blöcke der Größe block_size (127 Bytes) schneiden und auffüllen
blocks = []
for i in range(0, len(data), self.block_size):
block = data[i:i + self.block_size]
if len(block) < self.block_size:
block = block.ljust(self.block_size, b'\x00')
blocks.append(block)
# Initialisierungsvektor generieren
iv = os.urandom(self.block_size)
encrypted = [iv]
previous = iv
# CBC-Verschlüsselungsschleife
for block in blocks:
mixed = self._xor_bytes(block, previous)
msg_int = int.from_bytes(mixed, 'big')
# Mathematische Absicherung
if msg_int >= self.n:
raise ValueError("Ein Block-Wert ist größer als der Modulus n!")
cipher_int = pow(msg_int, self.e, self.n)
cipher_bytes = cipher_int.to_bytes(self.byte_length, 'big') # Immer byte_length (128 Bytes)
encrypted.append(cipher_bytes)
previous = cipher_bytes[-self.block_size:] # Letzte 127 Bytes für die Verkettung
return b''.join(encrypted)
def decrypt_text(self, encrypted: bytes) -> str:
"""Entschlüsselt die Daten mit dem privaten Schlüssel mittels CRT (Garner's Algorithmus)."""
if self.d is None or self.p is None or self.q is None:
raise ValueError("Entschlüsselung fehlgeschlagen: Kein privater Schlüssel (p, q, d) vorhanden!")
if not encrypted or len(encrypted) < self.block_size:
return ""
iv = encrypted[:self.block_size]
cipher_payload = encrypted[self.block_size:]
plain_blocks = []
previous = iv
# CBC-Entschlüsselungsschleife
for i in range(0, len(cipher_payload), self.byte_length):
cipher_bytes = cipher_payload[i:i + self.byte_length]
if len(cipher_bytes) != self.byte_length:
break
cipher_int = int.from_bytes(cipher_bytes, 'big')
# --- CRT Schnelle Entschlüsselung (Garner's Algorithmus) ---
m1 = pow(cipher_int, self.dp, self.p)
m2 = pow(cipher_int, self.dq, self.q)
h = (self.qinv * (m1 - m2)) % self.p
plain_int = m2 + h * self.q
# -----------------------------------------------------------
try:
original_mixed = plain_int.to_bytes(self.block_size, 'big')
except OverflowError:
return "[Decryption failed: Block overflow]"
original_block = self._xor_bytes(original_mixed, previous)
plain_blocks.append(original_block)
previous = cipher_bytes[-self.block_size:]
decrypted_bytes = b''.join(plain_blocks)
# Länge der komprimierten Daten extrahieren
if len(decrypted_bytes) < 8:
return ""
orig_len = int.from_bytes(decrypted_bytes[:8], 'big')
compressed_data = decrypted_bytes[8:8 + orig_len]
# Deaktivieren der Kompression und Rückgabe des Originaltexts
try:
return zlib.decompress(compressed_data).decode('utf-8')
except zlib.error:
return "[Decompression failed]"
# ====================== Demonstration & Test ======================
if __name__ == "__main__":
# Zwei statische 512-Bit-Primzahlen (ergeben ein ~1024-Bit-System)
p_demo = 5777206916112395415712237206274413831941623882672929021243193931830815863225056730635873537594547859986074615331022483575656978935371102046563723439266219
q_demo = 4106460507140997150744227303550937624466191939084182827176229127413536759230813768647267930318266747041254674601143896109143706246382521009689018641390477
# Berechnen des öffentlichen Modulus für die "Sender-Simulation"
n_demo = p_demo * q_demo
print("--- 1. SENDER-SEITE (Kennt nur den öffentlichen Modulus n) ---")
tsa_sender = TrapdoorSymmetricAlgorithm(n=n_demo)
text_to_encrypt = "Hallo Welt! Dies ist ein Test des CRT-beschleunigten TSA-Algorithmus."
print(f"Originaler Text: {text_to_encrypt}")
encrypted_data = tsa_sender.encrypt_text(text_to_encrypt)
# In Datei schreiben zum Testen
with open("cipher", "wb") as f:
f.write(encrypted_data)
print(f"Verschlüsselt und gespeichert: {len(encrypted_data)} Bytes\n")
print("--- 2. EMPFÄNGER-SEITE (Kennt p und q, nutzt CRT) ---")
tsa_receiver = TrapdoorSymmetricAlgorithm(p=p_demo, q=q_demo)
# Datei wieder einlesen
with open("cipher", "rb") as f:
encrypted_from_file = f.read()
decrypted_text = tsa_receiver.decrypt_text(encrypted_from_file)
print(f"Erfolgreich entschlüsselt: {decrypted_text == text_to_encrypt}")
print(f"Entschlüsselter Text: {decrypted_text}")
'''
print(f"Originaler Text: {text_to_encrypt}")
encrypted_data = tsa_sender.encrypt_text(text_to_encrypt)
# In Datei schreiben zum Testen
with open("cipher", "wb") as f:
f.write(encrypted_data)
print(f"Verschlüsselt und gespeichert: {len(encrypted_data)} Bytes\n")
print("--- 2. EMPFÄNGER-SEITE (Kennt p und q, nutzt CRT) ---")
tsa_receiver = TrapdoorSymmetricAlgorithm(p=p_demo, q=q_demo)
# Datei wieder einlesen
with open("cipher", "rb") as f:
encrypted_from_file = f.read()
decrypted_text = tsa_receiver.decrypt_text(encrypted_from_file)
print(f"Erfolgreich entschlüsselt: {decrypted_text == text_to_encrypt}")
print(f"Entschlüsselter Text: {decrypted_text}")
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