Saya memiliki beberapa data yang dikodekan base64 yang ingin saya ubah kembali ke biner bahkan jika ada kesalahan padding di dalamnya. Jika saya menggunakan
base64.decodestring(b64_string)
itu memunculkan kesalahan 'Padding salah'. Apakah ada cara lain?
UPDATE: Terima kasih atas semua umpan baliknya. Sejujurnya, semua metode yang disebutkan terdengar sedikit untung-untungan jadi saya memutuskan untuk mencoba openssl. Perintah berikut bekerja dengan baik:
openssl enc -d -base64 -in b64string -out binary_data
base64.b64decode(strg, '-_')
? Itu apriori, tanpa Anda repot-repot menyediakan data sampel apa pun, solusi Python yang paling mungkin untuk masalah Anda. "Metode" yang diusulkan adalah saran DEBUG, SEHARUSNYA "untung-untungan" mengingat kurangnya informasi yang diberikan.base64.urlsafe_b64decode(s)
sorted(list(set(b64_string)))
tolong? Tanpa mengungkapkan rahasia perusahaan apa pun, yang harus mengungkapkan karakter mana yang digunakan untuk menyandikan data asli, yang pada gilirannya dapat memberikan informasi yang cukup untuk memberikan solusi non-hit-or-miss.Jawaban:
Seperti yang dikatakan dalam tanggapan lain, ada berbagai cara di mana data base64 dapat rusak.
Namun, seperti yang dikatakan Wikipedia , menghapus padding (karakter '=' di akhir data yang dikodekan base64) adalah "lossless":
Jadi jika ini benar-benar satu-satunya yang "salah" dengan data base64 Anda, padding dapat ditambahkan kembali. Saya datang dengan ini untuk dapat mengurai URL "data" di WeasyPrint, beberapa di antaranya adalah base64 tanpa padding:
Tes untuk fungsi ini: weasyprint / tests / test_css.py # L68
sumber
str(data)
base64.decodestring
sudah tidak digunakan lagibase64.decodebytes
di Py3 tetapi untuk kompatibilitas versi lebih baik digunakanbase64.b64decode
.base64
modul mengabaikan karakter non-base64 yang tidak valid dalam input, Anda harus menormalkan data terlebih dahulu. Hapus apa pun yang bukan huruf, angka/
atau+
, lalu tambahkan padding.Cukup tambahkan padding sesuai kebutuhan. Namun, perhatikan peringatan Michael.
sumber
===
selalu berhasil.=
Karakter tambahan apa pun tampaknya dibuang dengan aman oleh Python.Sepertinya Anda hanya perlu menambahkan padding ke byte Anda sebelum melakukan decoding. Ada banyak jawaban lain untuk pertanyaan ini, tetapi saya ingin menunjukkan bahwa (setidaknya dengan Python 3.x)
base64.b64decode
akan memotong padding tambahan, asalkan ada cukup di tempat pertama.Jadi, sesuatu seperti:
b'abc='
bekerja sebaikb'abc=='
(seperti halnyab'abc====='
).Artinya, Anda dapat menambahkan jumlah maksimum karakter pengisi yang Anda perlukan — yaitu tiga (
b'==='
) —dan base64 akan memotong karakter pengisi yang tidak diperlukan.Ini memungkinkan Anda menulis:
yang lebih sederhana dari:
sumber
binascii.Error: Invalid base64-encoded string: number of data characters (5) cannot be 1 more than a multiple of 4
. Terima kasih telah menunjukkan hal ini!"Padding yang salah" tidak hanya berarti "padding yang hilang" tetapi juga (percaya atau tidak) "padding yang salah".
Jika metode "menambahkan padding" yang disarankan tidak berhasil, coba hapus beberapa byte tambahan:
Pembaruan: Setiap mengutak-atik menambahkan padding atau menghapus byte yang mungkin buruk dari akhir harus dilakukan SETELAH menghapus spasi, jika tidak perhitungan panjang akan mengecewakan.
Ada baiknya jika Anda menunjukkan contoh (singkat) data yang perlu Anda pulihkan. Edit pertanyaan Anda dan salin / tempel hasil dari
print repr(sample)
.Pembaruan 2: Ada kemungkinan bahwa pengkodean telah dilakukan dengan cara yang aman untuk url. Jika demikian, Anda akan dapat melihat karakter minus dan garis bawah dalam data Anda, dan Anda harus dapat memecahkan kode dengan menggunakan
base64.b64decode(strg, '-_')
Jika Anda tidak dapat melihat karakter minus dan garis bawah dalam data Anda, tetapi dapat melihat karakter plus dan slash, maka Anda memiliki masalah lain, dan mungkin memerlukan trik add-padding atau remove-cruft.
Jika Anda tidak dapat melihat minus, garis bawah, plus dan garis miring di data Anda, maka Anda perlu menentukan dua karakter alternatif; mereka akan menjadi orang-orang yang tidak ada di [A-Za-z0-9]. Kemudian Anda harus bereksperimen untuk melihat urutan mana yang harus digunakan dalam argumen kedua
base64.b64decode()
Pembaruan 3 : Jika data Anda adalah "rahasia perusahaan":
(a) Anda harus mengatakannya di awal
(b) kami dapat mencari cara lain untuk memahami masalah, yang kemungkinan besar terkait dengan karakter apa yang digunakan sebagai pengganti
+
dan/
dalam alfabet pengkodean, atau dengan format lain atau karakter asing.Salah satu cara tersebut adalah dengan memeriksa apa karakter non- "standar" dalam data Anda, mis
sumber
Menggunakan
Penghargaan diberikan untuk komentar di suatu tempat di sini.
sumber
Jika ada kesalahan padding, itu mungkin berarti string Anda rusak; string berenkode base64 harus memiliki kelipatan empat panjang. Anda dapat mencoba menambahkan karakter pengisi (
=
) sendiri untuk membuat string menjadi kelipatan empat, tetapi seharusnya sudah memilikinya kecuali ada yang salahsumber
Periksa dokumentasi sumber data yang Anda coba dekode. Apakah mungkin bahwa Anda bermaksud menggunakannya
base64.urlsafe_b64decode(s)
bukanbase64.b64decode(s)
? Itulah salah satu alasan Anda mungkin melihat pesan kesalahan ini.Ini adalah contoh kasus untuk berbagai Google API, seperti Google Identity Toolkit dan payload Gmail.
sumber
urlsafe_b64decode
juga membutuhkan bantalan.base64.urlsafe_b64decode
.Menambahkan padding agak ... fiddly. Inilah fungsi yang saya tulis dengan bantuan komentar di utas ini serta halaman wiki untuk base64 (sangat membantu) https://en.wikipedia.org/wiki/Base64#Padding .
sumber
Anda cukup menggunakan
base64.urlsafe_b64decode(data)
jika Anda mencoba memecahkan kode gambar web. Ini secara otomatis akan mengurus bantalan.sumber
Ada dua cara untuk mengoreksi data input yang dijelaskan di sini, atau, lebih spesifik dan sejalan dengan OP, untuk membuat metode b64decode modul Python dapat memproses data input menjadi sesuatu tanpa memunculkan pengecualian yang tidak tertangkap:
Jika itu menimbulkan pengecualian, maka
saya. Tangkap melalui coba / kecuali,
ii. (R?) Hapus semua karakter = dari data input (NB ini mungkin tidak diperlukan),
aku aku aku. Tambahkan A == ke data masukan (A == melalui P == akan bekerja),
iv. Panggil base64.b64decode (...) dengan A == - data masukan yang ditambahkan
Hasil dari Item 1. atau Item 2. di atas akan memberikan hasil yang diinginkan.
Peringatan
Ini tidak menjamin hasil yang didekodekan akan seperti yang semula dikodekan, tetapi (terkadang?) Akan memberikan OP yang cukup untuk bekerja dengan:
Lihat Apa yang kami ketahui dan Asumsi di bawah ini.
TL; DR
Dari beberapa tes cepat base64.b64decode (...)
tampaknya ia mengabaikan karakter non- [A-Za-z0-9 + /]; itu termasuk mengabaikan = s kecuali mereka adalah karakter terakhir dalam kelompok yang diurai empat, dalam hal ini = s menghentikan decoding (a = b = c = d = memberikan hasil yang sama seperti abc =, dan a = = b == c == memberikan hasil yang sama seperti ab ==).
Tampaknya juga bahwa semua karakter yang ditambahkan diabaikan setelah titik di mana base64.b64decode (...) mengakhiri decoding misalnya dari an = sebagai yang keempat dalam grup.
Seperti dicatat dalam beberapa komentar di atas, ada baik nol, atau satu, atau dua, = s padding yang diperlukan di akhir input data ketika nilai [jumlah karakter yang diurai ke titik modulo 4] adalah 0, atau 3, atau 2, masing-masing. Jadi, dari item 3. dan 4. di atas, menambahkan dua atau lebih = s ke data masukan akan memperbaiki masalah [Padding yang salah] dalam kasus tersebut.
NAMUN, decoding tidak dapat menangani kasus di mana [jumlah total karakter yang diurai modulo 4] adalah 1, karena dibutuhkan setidaknya dua karakter yang disandikan untuk mewakili byte pertama yang didekodekan dalam grup yang terdiri dari tiga byte yang didekode. Dalam data input yang disandikan tidak rusak, kasus [N modulo 4] = 1 ini tidak pernah terjadi, tetapi karena OP menyatakan bahwa karakter mungkin hilang, hal itu dapat terjadi di sini. Itulah mengapa menambahkan = s tidak akan selalu berhasil, dan mengapa menambahkan A == akan berhasil ketika menambahkan == tidak. NB Menggunakan [A] hanyalah sembarang: ia hanya menambahkan bit yang dihapus (nol) ke yang didekodekan, yang mungkin benar atau tidak, tetapi kemudian objek di sini bukanlah kebenaran tetapi diselesaikan oleh base64.b64decode (...) tanpa pengecualian .
Apa yang kita ketahui dari OP dan terutama komentar selanjutnya adalah
openssl enc ...
berhasil.Asumsi
Github
Berikut ini pembungkus untuk mengimplementasikan solusi ini:
https://github.com/drbitboy/missing_b64
sumber
Kesalahan padding yang salah disebabkan karena terkadang, metadata juga ada dalam string yang disandikan. Jika string Anda terlihat seperti: 'data: image / png; base64, ... base 64 stuff ....' maka Anda perlu menghapus yang pertama bagian sebelum mendekodekannya.
Katakanlah jika Anda memiliki gambar string yang dienkode base64, lalu coba cuplikan di bawah ini ..
sumber
Cukup tambahkan karakter tambahan seperti "=" atau lainnya dan buat kelipatan 4 sebelum Anda mencoba mendekode nilai string target. Sesuatu seperti;
sumber
Jika kesalahan ini berasal dari server web: Coba enkode url nilai posting Anda. Saya sedang POSTING melalui "curl" dan menemukan bahwa saya tidak melakukan pengkodean url nilai base64 saya sehingga karakter seperti "+" tidak lolos sehingga logika dekode url server web secara otomatis menjalankan dekode url dan mengonversi + ke spasi.
"+" adalah karakter base64 yang valid dan mungkin satu-satunya karakter yang rusak oleh dekode url yang tidak terduga.
sumber
Dalam kasus saya, saya menghadapi kesalahan itu saat mengurai email. Saya mendapatkan lampiran sebagai string base64 dan mengekstraknya melalui re.search. Akhirnya ada substring tambahan yang aneh di bagian akhir.
Ketika saya menghapus
--_=ic0008m4wtZ4TqBFd+sXC8--
dan menghapus string maka penguraian diperbaiki.Jadi saran saya adalah memastikan bahwa Anda mendekode string base64 yang benar.
sumber
Kamu harus menggunakan
Secara default, altchar adalah
'+/'
.sumber
Saya mengalami masalah ini juga dan tidak ada yang berhasil. Saya akhirnya berhasil menemukan solusi yang sesuai untuk saya. Saya memiliki konten zip di base64 dan ini terjadi pada 1 dari satu juta catatan ...
Ini adalah versi solusi yang disarankan oleh Simon Sapin.
Jika padding hilang 3 maka saya menghapus 3 karakter terakhir.
Alih-alih "0gA1RD5L / 9AUGtH9MzAwAAA =="
Kami mendapatkan "0gA1RD5L / 9AUGtH9MzAwAA"
Menurut jawaban ini Trailing As di base64 alasannya adalah nulls. Tapi saya masih tidak tahu mengapa pembuat enkode mengacaukannya ...
sumber