Mendekripsi AES CBC dengan python dari OpenSSL AES
Saya perlu mendekripsi file yang dienkripsi pada OpenSSL dengan python tetapi saya tidak memahami opsi pycrypto.
Inilah yang saya lakukan di OpenSSL
openssl enc -aes-256-cbc -a -salt -pbkdf2 -iter 100000 -in "clear.txt" -out "crypt.txt" -pass pass: "mypassword"
openssl enc -d -aes-256-cbc -a -pbkdf2 -iter 100000 -in "crypt.txt" -out "out.txt" -pass pass: "mypassword"
Saya mencoba (yang jelas tidak akan berhasil)
obj2 = AES.new("mypassword", AES.MODE_CBC)
output = obj2.decrypt(text)
Saya hanya ingin melakukan langkah kedua dengan python, tetapi ketika melihat sampel:
https://pypi.org/project/pycrypto/
obj2 = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
obj2.decrypt(ciphertext)
Saya tidak perlu IV, Bagaimana cara menentukan garam? hash pbkdf2? Saya juga melihat utas ini
Bagaimana cara mendekripsi file yang dienkripsi OpenSSL AES dengan Python?
tapi tidak membantu.
Bisakah seseorang menunjukkan kepada saya bagaimana melakukan ini menggunakan python?
Terima kasih.
Jawaban
Pernyataan OpenSSL menggunakan PBKDF2 untuk membuat kunci 32 byte dan IV 16 byte. Untuk ini, salt 8 byte acak secara implisit dibuat dan sandi yang ditentukan, jumlah iterasi, dan intisari (default: SHA-256) diterapkan. Pasangan kunci / IV digunakan untuk mengenkripsi teks biasa dengan AES-256 dalam mode CBC dan padding PKCS7, s. disini . Hasilnya dikembalikan dalam format OpenSSL, yang dimulai dengan pengkodean ASCII 8 byte dari Salted__ , diikuti oleh garam 8 byte dan teks sandi yang sebenarnya, semua dikodekan Base64. Salt diperlukan untuk dekripsi, sehingga kunci dan IV dapat direkonstruksi.
Perhatikan bahwa kata sandi dalam pernyataan OpenSSL sebenarnya diteruskan tanpa tanda kutip, yaitu dalam pernyataan OpenSSL yang diposting, tanda kutip adalah bagian dari kata sandi.
Untuk dekripsi dengan Python, salt dan ciphertext yang sebenarnya harus ditentukan terlebih dahulu dari data yang dienkripsi. Dengan garam, pasangan kunci / IV dapat direkonstruksi. Akhirnya, pasangan kunci / IV dapat digunakan untuk dekripsi.
Contoh: Dengan pernyataan OpenSSL yang diposting, teks biasa
The quick brown fox jumps over the lazy dog
dienkripsi ke dalam ciphertext
U2FsdGVkX18A+AhjLZpfOq2HilY+8MyrXcz3lHMdUII2cud0DnnIcAtomToclwWOtUUnoyTY2qCQQXQfwDYotw==
Dekripsi dengan Python dimungkinkan sebagai berikut (menggunakan PyCryptodome ):
from Crypto.Protocol.KDF import PBKDF2
from Crypto.Hash import SHA256
from Crypto.Util.Padding import unpad
from Crypto.Cipher import AES
import base64
# Determine salt and ciphertext
encryptedDataB64 = 'U2FsdGVkX18A+AhjLZpfOq2HilY+8MyrXcz3lHMdUII2cud0DnnIcAtomToclwWOtUUnoyTY2qCQQXQfwDYotw=='
encryptedData = base64.b64decode(encryptedDataB64)
salt = encryptedData[8:16]
ciphertext = encryptedData[16:]
# Reconstruct Key/IV-pair
pbkdf2Hash = PBKDF2(b'"mypassword"', salt, 32 + 16, count=100000, hmac_hash_module=SHA256)
key = pbkdf2Hash[0:32]
iv = pbkdf2Hash[32:32 + 16]
# Decrypt with AES-256 / CBC / PKCS7 Padding
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted = unpad(cipher.decrypt(ciphertext), 16)
print(decrypted)
Sunting - Mengenai komentar Anda: 16 MB harus dimungkinkan, tetapi untuk data yang lebih besar, ciphertext umumnya akan dibaca dari file dan data yang didekripsi akan ditulis ke file, berbeda dengan contoh yang diposting di atas.
Apakah data dapat didekripsi dalam satu langkah pada akhirnya bergantung pada memori yang tersedia. Jika memori tidak mencukupi, data harus diproses dalam potongan-potongan.
Saat menggunakan potongan, akan lebih masuk akal jika Base64 tidak menyandikan data terenkripsi tetapi menyimpannya secara langsung dalam format biner. Ini dimungkinkan dengan menghilangkan opsi -a di pernyataan OpenSSL. Jika tidak, harus dipastikan bahwa selalu kelipatan bilangan bulat dari ukuran blok (relatif terhadap ciphertext yang tidak dikodekan) dimuat, di mana 3 byte dari ciphertext yang tidak dikodekan sesuai dengan 4 byte dari ciphertext yang dikodekan Base64.
Dalam kasus ciphertext yang disimpan biner: Selama dekripsi hanya blok pertama (16 byte) yang harus dibaca (biner) pada langkah pertama. Dari sini, garam dapat ditentukan (byte 8 hingga 16), kemudian kunci dan IV (analog dengan kode yang diposting di atas).
Sisa ciphertext lainnya dapat (biner) dibaca dalam potongan dengan ukuran yang sesuai (= kelipatan ukuran blok, misalnya 1024 byte). Setiap potongan dienkripsi / didekripsi secara terpisah, lihat beberapa panggilan enkripsi / dekripsi . Untuk membaca / menulis file dalam potongan dengan Python, lihat misalnya di sini .
Rincian lebih lanjut paling baik dijawab dalam lingkup pertanyaan terpisah.