私はctfゲームに取り組んでいます:
ECBモードのAESで暗号化されます。すべての値はbase64でエンコードされています
ciphertext = 8LBUVZfDfI6wnggG1uUYuQsRoGd08pGwHCN++R5rabMW9PJmWHWcSrjy5Tfffj6L
key = 3q1FxGhuZ5fQYbjzDxgQ35==
私は自分の端末でそれを復号化しようとしましたが、base64に暗号文を残し、-base64
フラグ、運がない。次に、 http://extranet.cryptomathic.com/aescalc に移動しました。ここで、値を16進数に変換した後、復号化できました。
key: DEAD45C4686E6797D061B8F30F1810DF
text: F0B0545597C37C8EB09E0806D6E518B90B11A06774F291B01C237EF91E6B69B316F4F26658759C4AB8F2E537DF7E3E8B
out: 7B796F755F73686F756C645F6E6F745F706F73745F7468655F61637475616C5F6374665F76616C75657D5F5F5F5F5F5F
次に、次のことを試みてターミナルに戻りました。
echo -n F0B0545597C37C8EB09E0806D6E518B90B11A06774F291B01C237EF91E6B69B316F4F26658759C4AB8F2E537DF7E3E8B | openssl enc -d -K DEAD45C4686E6797D061B8F30F1810DF -aes-128-ecb -nosalt
しかし、私は同じエラーを受け取りました:
bad decrypt
140735124906848:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:531:
これをUbuntu17.04で試しましたが、MacOSXでOpenSSL1.0.2lを使用して試しました。自分の端末で復号化できないのはなぜですか?
openssl
はデフォルトでPKCS#7パディングを使用し、プレーンテキストにはPKCS#7パディングが含まれていないためです。平文が埋め込まれている場合は、値5F
のバイトが埋め込まれています。代わりに、オプション-nopad
を使用してください。値5F
でパディングすることは、私が知っているパディングスキームではありません。削除する必要がある場合は、自分で削除する必要があります。
現在、入力は16進数で表示されています。 16進数はバイトの表現であり、バイト値自体ではありません。ファイルの<
を使用してファイルからソースマテリアルを直接入力するか、入力を16進デコードする必要があります。
出力もバイナリになります。読み取り可能な平文を表すものではありません。したがって、質問の値と比較する前に、出力を16進数に変換する必要がある場合があります。
まあ、あなたはpythonまたは他のスクリプト/プログラミング言語を使用してそのようなことをすることを検討したいかもしれません。
プログラムで行うことの利点は次のとおりです。
手元の問題に関しては、pythonを使用してすべてを実行することで解決できます:
# 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))
さて、あなたがPythonまたは他の言語を学びたくない場合、および/またはあなたが本当にしたい場合端末ですべてを行うには、それも可能です:次に、 pipes を使用してすべてを直接実行し、あるコマンドから別のコマンドにデータを渡し、 コマンド置換 をフィードすることができますopensslの右キー、およびコマンド base64
base64 plusを処理するには xxd
でバイナリデータを16進数に変換 (opensslのキーの場合)最後にsed
を使用して5f
パディング:
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'
理由はわかりませんが、個人的にはpythonアプローチの方がクリーンだと思います。
また、Maarten Bodewesが示した方法を使用してガベージを取得したとおっしゃいましたが、これは、OpenSSLに16進値をフィードしているという事実に起因していますが、バイナリデータを直接提供する必要があります (16進値ではなく)メッセージの場合、16進でキーを指定する必要があります。
echo -n f0b0545597c37c8eb09e0806d6e518b90b11a06774f291b01c237ef91e6b69b316f4f26658759c4ab8f2e537df7e3e8b | xxd -r -p | openssl ...
PS:CTFで遭遇する実際の値を投稿することはおそらく避けるべきです。なぜなら、最初の反射が値をグーグルすることである人々にとってゲームを台無しにする可能性があるからです。
base64をデコードする
echo 8LBUVZfDfI6wnggG1uUYuQsRoGd08pGwHCN++R5rabMW9PJmWHWcSrjy5Tfffj6L | base64 -D > aesdata.dat
(-D
はMacOSの癖です。Linuxは代わりに-d
または--decode
を使用する傾向があります)。
同様に:
echo 3q1FxGhuZ5fQYbjzDxgQ35== | base64 -D > aeskey.dat
ただし、opensslはパラメータに16進値を期待します(ただし、暗号ファイルではバイナリ)。
xxd -p < aeskey.dat
はdead45c4686e6797d061b8f30f1810df
を返します。または、混乱を避けたい場合は、前のコマンドからパイプします。
最後に:
openssl enc -d -nopad -aes-128-ecb -K dead45c4686e6797d061b8f30f1810df -in aesdata.dat -out plain
それを解読します。 -nopadは、非標準のパディングが使用されるため、復号化エラーを回避します。
hd plain
で結果を確認します。これは、まさにあなたが探していたものです。