AES Decryption

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
cheekycrexy
User
Beiträge: 2
Registriert: Dienstag 27. Oktober 2020, 12:37

Moin,

ich habe von der Uni eine Aufgabe bekommen, an der ich etwas verzweifle.
Gegeben ist eine txt Datei mit einer AES 256 CBC verschlüsselten Nachricht. Gegeben ist auch der Schlüssel (11 Zeichen lang).
Aufgabe ist ein Python Skript zu schreiben, welches die Input Datei entschlüsselt und das Ergebnis in eine neue Datei schreibt.
Datei lesen, schreiben usw. ist kein Problem, allerdings meckert Python natürlich über den 11 Byte Key, dass dieser zu kurz ist.
Außerdem sind keine Infos über den IV gegeben.

Jemand eine Idee?
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

Da fehlt dann wohl was. Du mußt doch eine Beschreibung der verwendeten Verschlüsselung haben.
cheekycrexy
User
Beiträge: 2
Registriert: Dienstag 27. Oktober 2020, 12:37

Sirius3 hat geschrieben: Dienstag 27. Oktober 2020, 13:07 Da fehlt dann wohl was. Du mußt doch eine Beschreibung der verwendeten Verschlüsselung haben.
Nicht wirklich. Folgende Info habe ich:

Encrypted input file: input.txt
Decrypted output file: plain.txt
Cipher key: foundations

Bei den txt Dateien ist auf der Website entsprechend ein Link zu der txt Datei, bzw bei der Input Datei halt, aus der man den verschlüsselten Text entnehmen kann.
Außerdem haben wir diese Infos:
- Als Eingabe soll das Skript einen Schlüssel-String k und eine Datei mit beliebigem Namen f akzeptieren.
- Eingabe-Datei (UTF-8) [...] mit AES-256-CBC in base64 enkodiert wurde.

Mehr Infos haben wir nicht.
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

Mit diesen Angaben ist die Aufgabe nicht lösbar. Es fehlt die Angabe einer Key Derivation Function aus der man aus dem Passwort (hier Cipher key genannt) sowohl den Schlüssel (eigentlicher Cipher key) als auch den IV berechnen könnte.
Benutzeravatar
__blackjack__
User
Beiträge: 14054
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Alternativ könnte es auch sein, dass der IV mit bei den Daten gespeichert ist. Aber auch da gilt: das ist eine Information die man braucht um das entschlüsseln zu können.

Ist der Link zur verschlüsselten Datei öffentlich oder könntest Du die Datei zur Verfügung stellen?

Ansonsten wären praktische Ratschläge: Beim Aufgabensteller nachfragen und schauen ob es vielleicht etablierte Vorgehensweisen gibt um aus einem Passwort den Schlüssel und IV zu gewinnen und das dann einfach mal auszuprobieren.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
__blackjack__
User
Beiträge: 14054
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Mit ein bisschen mehr Info kann ich jetzt sagen, das im Grunde alle Informationen vorhanden sind. Wenn man nämlich den verschlüsselten Text kennt, lässt sich relativ einfach herausfinden womit das verschlüsselt wurde und kann mit diesen Informationen schon mal das gleiche Programm verwenden um zu entschlüsseln. Das Programm errechnet alles nötige aus dem Passwort und einem Teil der Eingabedatei.

Schritt 1 wäre also herausfinden welches Programm verwendet wurde. Dafür ist es hilfreich mal soweit zu ”dekodieren” wie man völlig ohne Kryptographie kommen kann und sich die rohe verschlüsselte Nachricht mal anzuschauen. Da sollte etwas auffallen mit dem man eine Suchmaschine füttern kann.

Wenn man herausgefunden hat, wie man das mit dem entsprechenden Programm entschlüsselt, braucht man das ”nur” noch in Python nachprogrammieren. Wobei da dann die Frage ist welche Bibliothek(en) man verwenden darf. Oder soll das tatsächlich komplett in reinem Python umgesetzt werden?
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
greetings1
User
Beiträge: 51
Registriert: Donnerstag 22. Oktober 2020, 18:19

Hier mal ein Anfang:

Code: Alles auswählen

in_file = "input.txt"

to_encrypt = ""
with open(in_file) as f:
    while True:
        c = f.read(1)
        if not c:
            break
        to_encrypt += c

while len(to_encrypt) % 16 != 0:
    to_encrypt += "0"

states = []
for i in range(0, len(to_encrypt), 16):
    state = []
    for j in range(4):
        row = []
        for k in range(4):
            row.append(to_encrypt[i + j * 4 + k])
        state.append(row)
    states.append(state)

print(states)
Da ich die S-Box aber nicht verstehe kann ich nicht weitermachen. :( Es fehlt "nur" noch die Schlüsselexpansion und Transformationen.
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

@greetings1: warum lädst Du die Datei Zeichen für Zeichen? Das ist doch ziemlich langsam und umständlich.
Einfach 0en anzuhängen ist kein sinnvolles Padding. Warum läuft die Schleife über i in 16er-Schritten, die über j aber nicht in 4er-Schritten?

Code: Alles auswählen

with open(in_file) as input:
    to_encrypt = input.read()
to_encrypt += "0" * (-len(to_encrypt) % 16)
states = []
for i in range(0, len(to_encrypt), 16):
    state = []
    for j in range(0, 16, 4):
        state.append(list(to_encrypt[i + j : i + j + 4]))
    states.append(state)
oder als Listcomprehension:

Code: Alles auswählen

states = [
    [list(to_encrypt[i + j: i + j + 4]) for j in range(0, 16, 4)]
    for i in range(0, len(to_encrypt), 16)
]
Was willst Du dann mit der Liste von Listen von Listen anfangen? Mit Zeichen an sich arbeiten die meisten Verschlüsselungsverfahren nicht, sondern sie benutzen Bytes.
AES verstanden, also warum gerade die Transformationen in der Reihenfolge gemacht werden, habe ich auch nicht. Wenn man das selbst implementieren will, muß man sich nur exakt an die Anleitung halten.
Benutzeravatar
__blackjack__
User
Beiträge: 14054
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Also ich habe das jetzt implementiert, aber AES habe ich mir fertig aus einem Package geholt. Genau wie das ”ent-padden”. :-)

Wer sich selbst mal an der Aufgabe versuchen möchte: Hier ist etwas das mit pythonrocks als Passwort verschlüsselt wurde:

Code: Alles auswählen

U2FsdGVkX19ItN5bqZMeP5KJUnPEpM/EcZFvt7WZMj9fmgahpxA1yf/bUxSk/Ybu
gpD77XRLFF+OWwwSssweRk6bE1qgu2vieD5rJPrRkrTn4jz12N5Q6XG4k4aBqpza
M0OH1TpdavUQIMbFi9QbsGdVFuNcJFUP8A1askvkkxAgeNVhKycK4antXmAu4jlR
ZjzmBTEXfCaBYznz0t5QxCd8ZPpd0XSMykZbbc+zi39Yt9hfxR06HX2I8x/IBkTm
kIcwUBIH9L2i9vpO5DXdA8xqAbXq204aAmAywZHUjjDTY95wlBquGJpuGReiPH/O
woLqsia4ZFTJEgCKHIy1C+UOjIFMB5xJrpZ37nrb5+FFOY7CaR3jdxk75TEsR9J0
FN9PyzPWuakmU3YhSu7kYRDocwvArbNBVn6Q28xJo3X5FndQungqDGsV9Kh09cN9
RInmjzX6YdGXpPyBisZIiNlrLVplW+sC+3FEJz3RI+8E/c+iE74/tjQ2FbJPjj7I
7s0tus7fmXsBXvcOsj3bpIujm2a03XFuyxxflbcQHsICWOet00+lyLmTjbVyo+aV
41CB4tLFF/Kop/CYzbUhy1DUVmasyfDkcM9FiYt3/IqSdNqP1KKv+gF8DUrCv50g
8Jn0TYMITQPDazMiivFqKd2Hgvj0ez/bVQJLNG0e8duZsF/bTZJ1f6nqtSv/0VWP
xVfRt/tUxq27hVmk1td0w594hFWZIsZeOa49elvBboS1qmyZWLWnx/2CN8uBT8HR
4r1lgEP0jvFLbiWluZf8o1ndXmJX7i63iZRpKDsRZUGYT/zvT6UqyLXXmazNHrFu
Wnb3WARtcDBuj0NReAnEMgsCrUAuyDTVfK88zGtnVX2RDM1t+yzPtasAmZSJiJfv
Xfx3saeHvZdfIoZpgBwUxlWSY0E4U1iBVQzgZa/xUzzsN5FAR2N7WrVWwZ7aHBVI
6CvAlN/AtfO5cGd53u0dZvyExkSHipLvoavaq/+QBC7h+/0D3O8acDkUGgXRd3YN
U3nMoPmqvIc1dmMd+KIfTSY+X9PePJ/7Gu7pUavu02QnzDjUjfVD22khsCD6xvyl
XkXsN8gmTgn6Rqpu60Auv/+VfgR3t5qUpKyJGCwWrHUmV9qiQGeYENTQ9Ht39yO/
NmUuIW72nrD+qSqyvuyl8Q==
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
__blackjack__
User
Beiträge: 14054
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Gar niemand neugierig was da geheimes verschlüsselt ist? 🙂
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
__blackjack__
User
Beiträge: 14054
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ui, ist das mittlerweile alt das Thema. 🙂 Habe hier noch ein Tab im Editor offen gehabt mit der Lösung:

Code: Alles auswählen

#!/usr/bin/env python3
import binascii
import hashlib
import sys

import click
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes

SALTED_PREFIX = b"Salted__"
SALT_LENGTH = 8  # in bytes.
KEY_SIZE = 256  # in bits.


def derive_key_and_iv(
    password, key_length, iv_length, hash_algorithm="sha256", salt=b""
):
    result = bytearray()
    digest = b""
    needed_length = key_length + iv_length
    while len(result) < needed_length:
        digest = hashlib.new(hash_algorithm, digest + password + salt).digest()
        result.extend(digest)
    return result[:key_length], result[key_length:needed_length]


@click.command()
@click.option(
    "-p",
    "--password",
    metavar="PASSWORD",
    prompt=True,
    hide_input=True,
    envvar="DECODE_PASSWORD",
    show_envvar=True,
    help="password used to decode. Default: prompt user.",
)
@click.option(
    "--message-digest",
    type=click.Choice(["md5", "sha256"]),
    default="sha256",
    show_default=True,
    help="hash function used to derive key and IV.",
)
@click.argument("file", type=click.File("rb"), default="-")
def decode(password, message_digest, file):
    """
    Decode given FILE with given password.  If no FILE is given, the input is
    read from standard input.

    The input data is expected to be Base64 encoded encrypted data. The expected
    encryption is AES 256 in CBC mode with a salt.

    Decrypted data is written to standard output.
    \f

    For data encrypted with::

      openssl enc -base64 -aes-256-cbc -salt -pass pass:pythonrocks -in plain.txt

    """
    try:
        encrypted_and_salted = binascii.a2b_base64(file.read())
    except binascii.Error as error:
        click.echo(f"can not decode base64 data: {error}", err=True)
        sys.exit(1)

    if not encrypted_and_salted.startswith(SALTED_PREFIX):
        click.echo("encrypted data isn't salted", err=True)
        sys.exit(2)

    prefix_length = len(SALTED_PREFIX)
    salt = encrypted_and_salted[prefix_length : prefix_length + SALT_LENGTH]
    encrypted = encrypted_and_salted[prefix_length + SALT_LENGTH :]
    key, iv = derive_key_and_iv(
        password.encode("utf-8"),
        KEY_SIZE // 8,
        algorithms.AES.block_size // 8,
        message_digest,
        salt,
    )
    decryptor = Cipher(algorithms.AES(key), modes.CBC(iv)).decryptor()
    try:
        decrypted = decryptor.update(encrypted) + decryptor.finalize()
    except ValueError as error:
        click.echo(f"can not decrypt data: {error}", err=True)
        sys.exit(3)
    unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
    try:
        unpadded = unpadder.update(decrypted) + unpadder.finalize()
    except ValueError as error:
        click.echo(f"can not unpad decrypted data: {error}", err=True)
        sys.exit(4)

    click.get_binary_stream("stdout").write(unpadded)


if __name__ == "__main__":
    decode()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten