AES kann mit OpenSSL nicht entschlüsselt werden

3834
robert

Ich arbeite an einem CTF-Spiel:

Im EZB-Modus mit AES verschlüsselt. Alle Werte base64 codiert

ciphertext = 8LBUVZfDfI6wnggG1uUYuQsRoGd08pGwHCN++R5rabMW9PJmWHWcSrjy5Tfffj6L key = 3q1FxGhuZ5fQYbjzDxgQ35== 

Ich habe versucht, es in meinem Terminal zu entschlüsseln, den Basiscode in base64 zu verlassen und die -base64Flagge zu verwenden, ohne Glück. Dann ging ich zu http://extranet.cryptomathic.com/aescalc, wo ich, nachdem ich die Werte in Hex konvertiert hatte, entschlüsseln konnte:

key: DEAD45C4686E6797D061B8F30F1810DF  text: F0B0545597C37C8EB09E0806D6E518B90B11A06774F291B01C237EF91E6B69B316F4F26658759C4AB8F2E537DF7E3E8B out: 7B796F755F73686F756C645F6E6F745F706F73745F7468655F61637475616C5F6374665F76616C75657D5F5F5F5F5F5F 

Dann kehrte ich zu meinem Terminal zurück und versuchte:

echo -n F0B0545597C37C8EB09E0806D6E518B90B11A06774F291B01C237EF91E6B69B316F4F26658759C4AB8F2E537DF7E3E8B | openssl enc -d -K DEAD45C4686E6797D061B8F30F1810DF -aes-128-ecb -nosalt 

aber ich habe den gleichen fehler bekommen:

bad decrypt 140735124906848:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:531: 

Ich habe dies auf Ubuntu 17.04 und jetzt auf meinem MacOSX mit OpenSSL 1.0.2l ausprobiert. Warum kann ich nicht in meinem eigenen Terminal entschlüsseln?

3
Da es sich um eine CTF handelt, habe ich die tatsächlichen Werte durch Platzhalter ersetzt. ;) Lery vor 6 Jahren 0

3 Antworten auf die Frage

5
Maarten Bodewes

Da openssldie PKCS # 7-Auffüllung standardmäßig verwendet wird und Ihr Klartext keine PKCS # 7-Auffüllung enthält. Wenn Ihr Klartext aufgefüllt wurde, wurde er mit Wertebytes aufgefüllt 5F. Verwenden Sie -nopadstattdessen die Option . Auffüllen mit Wert 5Fist kein mir bekanntes Auffüllschema. Wenn es entfernt werden muss, müssen Sie es selbst entfernen.

Sie zeigen derzeit die Eingabe in Hexadezimalzahlen an. Hexadezimal ist die Darstellung der Bytes, nicht die Bytewerte selbst. Sie müssen entweder das Quellmaterial direkt aus einer Datei eingeben, indem Sie <für Ihre Datei verwenden, oder indem Sie die Eingabe hexadezimal dekodieren.

Die Ausgabe ist auch binär. es wird keinen lesbaren Klartext darstellen. Daher müssen Sie die Ausgabe möglicherweise in Hexadezimale konvertieren, bevor Sie sie mit den Werten in Ihrer Frage vergleichen.

Googled und bekam eine meiner eigenen Antworten :) Maarten Bodewes vor 6 Jahren 1
Die 5Fs erscheinen in der entschlüsselten Nachricht. robert vor 6 Jahren 1
Ja, das Auffüllen erfolgt vor der Verschlüsselung mit der Blockverschlüsselung / Betriebsart und somit nach der Entschlüsselung. Maarten Bodewes vor 6 Jahren 1
Okay, ich verstehe jetzt. Bei Verwendung von "-nopad" werden keine Fehlermeldungen mehr angezeigt, die Ausgabe ist jedoch falsch, etwas Müll. robert vor 6 Jahren 1
AES ist eine 128-Bit / 16-Byte-Blockverschlüsselung. Daher ist es nicht möglich, PKCS # 5-kompatible Auffüllung zu verwenden, da sie nur für 64-Bit / 8-Byte-Blockverschlüsselungen definiert ist.] (Https://crypto.stackexchange.com/ q / 9043/1172). Wenn die Ausgabe wie ein Müll aussieht, liegt dies wahrscheinlich daran, dass die Ausgabe als US-ASCII / UTF-8 (oder ein beliebiger anderer Zeichensatz Ihres Systems) interpretiert wird. Leiten Sie die Ausgabe mithilfe von `>` in die Datei und öffnen Sie sie in einem Hex-Editor. * Vergleichen Sie dann * die Ergebnisse, nicht vorher. Maarten Bodewes vor 6 Jahren 1
@robert Tatsächlich erhältst du Müll, weil Openssl Bytes als Eingabe erwartet, keine hexadezimale Zeichenfolge, wie du sie füttert. Sie können `echo -n DEADC0DE | verwenden xxd -r -p | openssl ... `, um die tatsächlichen Daten abzurufen. Lery vor 6 Jahren 1
@Lery hat dies in meine Antwort integriert, die Eingabe vergessen. D'oh Maarten Bodewes vor 6 Jahren 0
3
Lery

Nun, Sie sollten vielleicht Python oder eine andere Skript- / Programmiersprache verwenden, um solche Dinge zu tun.

Die Vorteile des Programmierens sind:

  • Wann immer Sie etwas Ähnliches wiederholen müssen, haben Sie Ihren Code bereit.
  • Sie können Kommentare schreiben, um zu erklären, was los ist. Wenn Sie also einmal verstehen müssen, was Sie zuvor getan haben, können Sie dies dank des Codes und der Kommentare hoffentlich tun.
  • Viele Dinge wie Codierung, Byte-Handling usw. sind einfacher als in der Konsole
  • Die meisten Sprachen sind plattformübergreifend, so dass es unter Windows, Linux und Android problemlos funktioniert, wenn Sie Ihr Gerät einmal umschalten.

In Bezug auf Ihr aktuelles Problem kann es mit Python gelöst werden, alles zu tun:

# we import the function we need from common librairies from base64 import b64decode from Crypto.Cipher import AES from binascii import hexlify, unhexlify   # First we decode the message and the key from base64 into bytes: msg = b64decode("8LBUVZfDfI6wnggG1uUYuQsRoGd08pGwHCN++R5rabMW9PJmWHWcSrjy5Tfffj6L") key = b64decode("3q1FxGhuZ5fQYbjzDxgQ35==")  # We then instantiate a cipher_suite using AES with the provided key, in ECB mode cipher_suite = AES.new(key, AES.MODE_ECB)  # We can decrypt the message using our cipher_suite: recovered = cipher_suite.decrypt(msg)  # We can print it: print ("plaintext: ", recovered)  # There is some garbage at the end, but if we display it in hexadecimal form: print ("in hex:", hexlify(recovered)) # We can see it's just padding using '5f', so let's create a function to remove such padding: def unpad(padded): # we declare the value of our padding: paddingByte = unhexlify('5f') # we do a loop, while the last byte is padding while padded[-1:]==paddingByte: # we remove the last byte padded = padded[:-1] # once it's done, we return return padded  # We can now use our function to remove padding: print ("unpadded: ", unpad(recovered)) 

Wenn Sie jetzt nicht Python oder eine andere Sprache lernen möchten und / oder wenn Sie wirklich alles in Ihrem Terminal tun möchten, ist dies auch möglich: Dann können Sie alles direkt mit Pipes tun, um die Daten von einem zu übergeben Befehl an den anderen, Befehlssubstitutions den richtigen Schlüssel zu Openssl einzuspeisen, und die Befehle base64Base64 zu handhaben und xxdBinärdaten hex zu konvertieren (für den Schlüssel in Openssl) und schließlich verwenden seddie entfernen 5fpadding:

echo "8LBUVZfDfI6wnggG1uUYuQsRoGd08pGwHCN++R5rabMW9PJmWHWcSrjy5Tfffj6L" | base64 --decode | openssl enc -d -K $(echo "3q1FxGhuZ5fQYbjzDxgQ35==" | base64 --decode | xxd -c 16 -ps) -aes-128-ecb -nosalt -nopad | sed 's/_*$//g' 

Ich weiß nicht warum, aber ich persönlich finde den Python-Ansatz sauberer.


Sie haben auch erwähnt, dass Sie Müll mit der von Maarten Bodewes angegebenen Art und Weise erhalten haben, da Sie hexadezimale Werte an OpenSSL übergeben, während Sie die binären Daten (nicht den hexadezimalen Wert) der Nachricht direkt angeben sollten sollte den Schlüssel hexadezimal angeben:

echo -n f0b0545597c37c8eb09e0806d6e518b90b11a06774f291b01c237ef91e6b69b316f4f26658759c4ab8f2e537df7e3e8b | xxd -r -p | openssl ... 

PS: Sie sollten es wahrscheinlich vermeiden, die tatsächlichen Werte, auf die Sie in CTFs stoßen, zu veröffentlichen, da dies das Spiel für Personen beeinträchtigen könnte, deren erster Reflex darin besteht, die Werte zu googeln.

2
Henno

decodieren base64 durch

echo 8LBUVZfDfI6wnggG1uUYuQsRoGd08pGwHCN++R5rabMW9PJmWHWcSrjy5Tfffj6L | base64 -D > aesdata.dat

(Das -Dist eine Mac OS-Variante. Linux verwendet -doder --decodestattdessen).

Ähnlich:

echo 3q1FxGhuZ5fQYbjzDxgQ35== | base64 -D > aeskey.dat

openssl erwartet jedoch hexadezimale Werte in Parametern (aber binär in Verschlüsselungsdateien):

xxd -p < aeskey.datgibt dead45c4686e6797d061b8f30f1810df. Oder vom vorherigen Befehl weitergeleitet, wenn Sie Unordnung vermeiden möchten.

Endlich:

openssl enc -d -nopad -aes-128-ecb -K dead45c4686e6797d061b8f30f1810df -in aesdata.dat -out plain

wird es entschlüsseln. Das -nopad vermeidet den Entschlüsselungsfehler, da nicht standardmäßige Auffüllung verwendet wird.

Nun hd plain, um das Ergebnis zu überprüfen, was Sie tatsächlich gesucht haben.