Ich habe einige Base64-codierte Daten, die ich wieder in Binärdaten konvertieren möchte, auch wenn ein Auffüllfehler vorliegt. Wenn ich benutze
base64.decodestring(b64_string)
Es wird ein Fehler "Falsches Auffüllen" ausgelöst. Gibt es eine andere Art und Weise?
UPDATE: Danke für all das Feedback. Um ehrlich zu sein, klangen alle genannten Methoden ein bisschen schlecht und so entschied ich mich, openssl auszuprobieren. Der folgende Befehl war ein Vergnügen:
openssl enc -d -base64 -in b64string -out binary_data
base64.b64decode(strg, '-_')
? Dies ist a priori, ohne dass Sie sich die Mühe machen, Beispieldaten bereitzustellen, die wahrscheinlichste Python-Lösung für Ihr Problem. Die vorgeschlagenen "Methoden" waren DEBUG-Vorschläge, die angesichts des Mangels an gelieferten Informationen unbedingt "Hit and Miss" waren.base64.urlsafe_b64decode(s)
sorted(list(set(b64_string)))
bitte? Ohne irgendetwas unternehmensvertrauliches preiszugeben, sollte dies Aufschluss darüber geben, welche Zeichen zum Codieren der Originaldaten verwendet wurden, was wiederum genügend Informationen liefern kann, um eine Non-Hit-or-Miss-Lösung bereitzustellen.Antworten:
Wie in anderen Antworten erwähnt, gibt es verschiedene Möglichkeiten, wie base64-Daten beschädigt werden können.
Wie Wikipedia jedoch sagt, ist das Entfernen der Auffüllung (die '=' Zeichen am Ende der Base64-codierten Daten) "verlustfrei":
Wenn dies also wirklich das einzige ist, was mit Ihren base64-Daten "falsch" ist, kann das Auffüllen einfach wieder hinzugefügt werden. Ich habe mir das ausgedacht, um "Daten" -URLs in WeasyPrint analysieren zu können, von denen einige base64 ohne Auffüllen waren:
Tests für diese Funktion: weasyprint / tests / test_css.py # L68
quelle
str(data)
base64.decodestring
veraltet, aber ausbase64.decodebytes
Gründen der Versionskompatibilität besser zu verwendenbase64.b64decode
.base64
Modul ungültige Nicht-Base64-Zeichen in der Eingabe ignoriert, müssen Sie zuerst die Daten normalisieren . Entfernen Sie alles, was kein Buchstabe, keine Ziffer/
oder ist+
, und fügen Sie dann die Polsterung hinzu.Fügen Sie einfach nach Bedarf Polster hinzu. Beachten Sie jedoch Michaels Warnung.
quelle
===
funktioniert immer. Alle zusätzlichen=
Zeichen werden von Python scheinbar sicher verworfen.Es scheint, dass Sie Ihren Bytes vor dem Dekodieren nur eine Auffüllung hinzufügen müssen. Es gibt viele andere Antworten auf diese Frage, aber ich möchte darauf hinweisen (zumindest in Python 3.x).
base64.b64decode
jede zusätzliche Auffüllung abgeschnitten wird, vorausgesetzt, es gibt überhaupt genug.Also so etwas wie:
b'abc='
funktioniert genauso gut wieb'abc=='
(wie auchb'abc====='
).Dies bedeutet, dass Sie einfach die maximale Anzahl von Füllzeichen hinzufügen können, die Sie jemals benötigen würden
b'==='
- nämlich drei ( ) - und base64 alle unnötigen Zeichen abschneidet.So können Sie schreiben:
Das ist einfacher als:
quelle
binascii.Error: Invalid base64-encoded string: number of data characters (5) cannot be 1 more than a multiple of 4
. Vielen Dank für den Hinweis!"Falsche Polsterung" kann nicht nur "fehlende Polsterung" bedeuten, sondern auch (ob Sie es glauben oder nicht) "falsche Polsterung".
Wenn die vorgeschlagenen Methoden zum Hinzufügen von Auffüllungen nicht funktionieren, entfernen Sie einige nachfolgende Bytes:
Update: Jegliches Herumspielen am Auffüllen oder Entfernen möglicherweise fehlerhafter Bytes am Ende sollte NACH dem Entfernen von Leerzeichen erfolgen, da sonst die Längenberechnungen gestört werden.
Es wäre eine gute Idee, wenn Sie uns eine (kurze) Stichprobe der Daten zeigen würden, die Sie wiederherstellen müssen. Bearbeiten Sie Ihre Frage und kopieren Sie das Ergebnis von
print repr(sample)
.Update 2: Möglicherweise wurde die Codierung auf URL-sichere Weise durchgeführt. In diesem Fall können Sie Minus- und Unterstrichzeichen in Ihren Daten sehen und diese mit dekodieren
base64.b64decode(strg, '-_')
Wenn Sie in Ihren Daten keine Minus- und Unterstrichzeichen sehen können, aber Plus- und Schrägstriche sehen können, haben Sie ein anderes Problem und benötigen möglicherweise die Tricks zum Hinzufügen oder Auffüllen von Cruft.
Wenn Sie in Ihren Daten kein Minus, keinen Unterstrich, kein Plus und keinen Schrägstrich sehen können, müssen Sie die beiden alternativen Zeichen bestimmen. Sie sind diejenigen, die nicht in [A-Za-z0-9] enthalten sind. Dann müssen Sie experimentieren, um zu sehen, in welcher Reihenfolge sie im 2. Argument von verwendet werden müssen
base64.b64decode()
Update 3 : Wenn Ihre Daten "vertraulich" sind:
(a) Sie sollten dies im Voraus sagen.
(B) Wir können andere Wege zum Verständnis des Problems untersuchen, die höchstwahrscheinlich damit zusammenhängen, welche Zeichen anstelle von
+
und/
in verwendet werden das Kodierungsalphabet oder durch andere Formatierungen oder fremde Zeichen.Eine solche Möglichkeit wäre, zu untersuchen, welche nicht "Standard" -Zeichen in Ihren Daten enthalten sind, z
quelle
Verwenden
Kredit geht zu einem Kommentar irgendwo hier.
quelle
Wenn ein Auffüllfehler auftritt, bedeutet dies wahrscheinlich, dass Ihre Zeichenfolge beschädigt ist. Base64-codierte Zeichenfolgen sollten ein Vielfaches von vier Längen haben. Sie können versuchen, das Auffüllzeichen (
=
) selbst hinzuzufügen , um die Zeichenfolge zu einem Vielfachen von vier zu machen. Dies sollte jedoch bereits vorhanden sein, es sei denn, etwas stimmt nichtquelle
Überprüfen Sie die Dokumentation der Datenquelle, die Sie dekodieren möchten. Ist es möglich, dass Sie
base64.urlsafe_b64decode(s)
statt verwenden wolltenbase64.b64decode(s)
? Dies ist einer der Gründe, warum Sie diese Fehlermeldung möglicherweise gesehen haben.Dies ist beispielsweise bei verschiedenen Google-APIs wie dem Google Identity Toolkit und den Google Mail-Nutzdaten der Fall.
quelle
urlsafe_b64decode
erfordert auch Polsterung.base64.urlsafe_b64decode
.Das Hinzufügen der Polsterung ist ziemlich ... umständlich. Hier ist die Funktion, die ich mithilfe der Kommentare in diesem Thread geschrieben habe, sowie die Wiki-Seite für base64 (überraschend hilfreich) https://en.wikipedia.org/wiki/Base64#Padding .
quelle
Sie können es einfach verwenden,
base64.urlsafe_b64decode(data)
wenn Sie versuchen, ein Webbild zu dekodieren. Es kümmert sich automatisch um die Polsterung.quelle
Es gibt zwei Möglichkeiten, die hier beschriebenen Eingabedaten zu korrigieren oder, genauer gesagt und im Einklang mit dem OP, die b64decode-Methode des Python-Moduls base64 in die Lage zu versetzen, die Eingabedaten zu etwas zu verarbeiten, ohne eine nicht abgefangene Ausnahme auszulösen :
Wenn dies eine Ausnahme auslöst, dann
ich. Fangen Sie es über versuchen / außer,
ii. (R?) Entfernen Sie beliebige = Zeichen aus den Eingabedaten (Hinweis: Dies ist möglicherweise nicht erforderlich).
iii. Fügen Sie A == an die Eingabedaten an (A == bis P == funktionieren),
iv. Rufen Sie base64.b64decode (...) mit den A == - angehängten Eingabedaten auf
Das Ergebnis aus Punkt 1. oder Punkt 2. oben ergibt das gewünschte Ergebnis.
Vorsichtsmaßnahmen
Dies garantiert nicht, dass das decodierte Ergebnis das ist, was ursprünglich codiert wurde, aber es gibt (manchmal?) Dem OP genug, um damit zu arbeiten:
Siehe Was wir wissen und Annahmen unten.
TL; DR
Aus einigen Schnelltests von base64.b64decode (...)
es scheint, dass es Nicht- [A-Za-z0-9 + /] Zeichen ignoriert; das schließt das Ignorieren von = s ein, es sei denn sie sind die letzten Zeichen in einer analysierten Vierergruppe. In diesem Fall beenden die = s die Decodierung (a = b = c = d = ergibt das gleiche Ergebnis wie abc = und a = = b == c == ergibt das gleiche Ergebnis wie ab ==).
Es scheint auch, dass alle angehängten Zeichen nach dem Punkt ignoriert werden, an dem base64.b64decode (...) die Dekodierung beendet, z. B. von an = als viertes in einer Gruppe.
Wie in mehreren Kommentaren oben erwähnt, sind am Ende der Eingabedaten entweder null oder eins oder zwei = s Auffüllung erforderlich, wenn der Wert [Anzahl der analysierten Zeichen bis zu diesem Punkt Modulo 4] 0 oder 3 ist. bzw. 2. Ab den obigen Punkten 3. und 4. werden durch Anhängen von zwei oder mehr = s an die Eingabedaten alle Probleme mit [falscher Auffüllung] in diesen Fällen behoben.
Die Decodierung kann jedoch nicht den Fall behandeln, in dem die [Gesamtzahl der analysierten Zeichen Modulo 4] 1 ist, da mindestens zwei codierte Zeichen erforderlich sind, um das erste decodierte Byte in einer Gruppe von drei decodierten Bytes darzustellen. In nicht beschädigten codierten Eingabedaten tritt dieser Fall [N modulo 4] = 1 nie auf, aber da das OP feststellte, dass möglicherweise Zeichen fehlen, kann dies hier passieren. Aus diesem Grund funktioniert das Anhängen von = s nicht immer, und das Anhängen von A == funktioniert, wenn das Anhängen von == nicht funktioniert. NB Die Verwendung von [A] ist alles andere als willkürlich: Es werden nur gelöschte (Null-) Bits zu den decodierten hinzugefügt, was möglicherweise korrekt ist oder nicht, aber dann ist das Objekt hier nicht die Richtigkeit, sondern die Vervollständigung durch base64.b64decode (...) ohne Ausnahmen .
Was wir aus dem OP und insbesondere aus nachfolgenden Kommentaren wissen, ist
openssl enc ...
funktioniert, bestätigt oder zumindest nahegelegt .Annahmen
Github
Hier ist ein Wrapper zum Implementieren dieser Lösung:
https://github.com/drbitboy/missing_b64
quelle
Ein falscher Auffüllfehler wird verursacht, weil manchmal auch Metadaten in der codierten Zeichenfolge vorhanden sind. Wenn Ihre Zeichenfolge ungefähr so aussieht: 'data: image / png; base64, ... base 64 stuff ....', müssen Sie die erste entfernen Teil vor dem Dekodieren.
Sagen Sie, wenn Sie eine Image Base64-codierte Zeichenfolge haben, versuchen Sie es unter dem folgenden Snippet.
quelle
Fügen Sie einfach zusätzliche Zeichen wie "=" oder ein anderes hinzu und machen Sie ein Vielfaches von 4, bevor Sie versuchen, den Zielzeichenfolgenwert zu dekodieren. Etwas wie;
quelle
Falls dieser Fehler von einem Webserver kam: Versuchen Sie, Ihren Beitragswert mit einer URL zu codieren. Ich habe über "curl" gepostet und festgestellt, dass ich meinen base64-Wert nicht url-codiert habe, sodass Zeichen wie "+" nicht maskiert wurden, sodass die URL-Decodierungslogik des Webservers automatisch url-decodierte und + in Leerzeichen konvertierte.
"+" ist ein gültiges base64-Zeichen und möglicherweise das einzige Zeichen, das durch eine unerwartete URL-Dekodierung entstellt wird.
quelle
In meinem Fall trat dieser Fehler beim Parsen einer E-Mail auf. Ich habe den Anhang als base64-String erhalten und ihn über re.search extrahiert. Schließlich gab es am Ende einen seltsamen zusätzlichen Teilstring.
Als ich
--_=ic0008m4wtZ4TqBFd+sXC8--
die Zeichenfolge löschte und entfernte, wurde das Parsen korrigiert.Mein Rat ist also, sicherzustellen, dass Sie eine korrekte base64-Zeichenfolge dekodieren.
quelle
Du solltest benutzen
Standardmäßig sind die Altchars
'+/'
.quelle
Ich bin auch auf dieses Problem gestoßen und nichts hat funktioniert. Ich habe es endlich geschafft, die Lösung zu finden, die für mich funktioniert. Ich hatte Inhalte in base64 gezippt und dies geschah mit 1 von einer Million Datensätzen ...
Dies ist eine Version der von Simon Sapin vorgeschlagenen Lösung.
Falls der Abstand 3 fehlt, entferne ich die letzten 3 Zeichen.
Anstelle von "0gA1RD5L / 9AUGtH9MzAwAAA =="
Wir erhalten "0gA1RD5L / 9AUGtH9MzAwAA"
Nach dieser Antwort Trailing Wie in base64 ist der Grund Nullen. Aber ich habe immer noch keine Ahnung, warum der Encoder das durcheinander bringt ...
quelle