J'ai des données encodées en base64 que je souhaite reconvertir en binaire même s'il y a une erreur de remplissage. Si j'utilise
base64.decodestring(b64_string)
il déclenche une erreur de «remplissage incorrect». Y a-t-il un autre moyen?
MISE À JOUR: Merci pour tous les commentaires. Pour être honnête, toutes les méthodes mentionnées sonnaient un peu hasardeuses, alors j'ai décidé d'essayer openssl. La commande suivante a fonctionné un régal:
openssl enc -d -base64 -in b64string -out binary_data
base64.b64decode(strg, '-_')
? C'est a priori, sans que vous vous souciez de fournir des exemples de données, la solution Python la plus probable à votre problème. Les «méthodes» proposées étaient des suggestions DEBUG, NÉCESSAIREMENT «aléatoires» étant donné la rareté des informations fournies.base64.urlsafe_b64decode(s)
sorted(list(set(b64_string)))
s'il vous plaît? Sans révéler quoi que ce soit de confidentiel à l'entreprise, cela devrait révéler quels caractères ont été utilisés pour encoder les données d'origine, qui à leur tour peuvent fournir suffisamment d'informations pour fournir une solution non aléatoire.Réponses:
Comme indiqué dans d'autres réponses, les données base64 peuvent être corrompues de différentes manières.
Cependant, comme le dit Wikipedia , la suppression du remplissage (les caractères '=' à la fin des données encodées en base64) est "sans perte":
Donc, si c'est vraiment la seule chose "qui ne va pas" avec vos données base64, le remplissage peut simplement être rajouté. Je suis venu avec ceci pour être en mesure d'analyser les URL de "données" dans WeasyPrint, dont certaines étaient en base64 sans remplissage:
Tests pour cette fonction: weasyprint / tests / test_css.py # L68
la source
str(data)
base64.decodestring
est obsolète pourbase64.decodebytes
Py3, mais pour la compatibilité des versions, il est préférable de l'utiliserbase64.b64decode
.base64
module ignore les caractères non base64 non valides dans l'entrée, vous devez d'abord normaliser les données. Supprimez tout ce qui n'est pas une lettre, un chiffre/
ou+
, puis ajoutez le remplissage.Ajoutez simplement un rembourrage au besoin. Tenez cependant compte de l'avertissement de Michael.
la source
===
fonctionne toujours. Tous les=
caractères supplémentaires sont apparemment supprimés en toute sécurité par Python.Il semble que vous ayez juste besoin d'ajouter un remplissage à vos octets avant le décodage. Il y a beaucoup d'autres réponses à cette question, mais je tiens à souligner que (au moins en Python 3.x)
base64.b64decode
tronquera tout rembourrage supplémentaire, à condition qu'il y en ait assez en premier lieu.Donc, quelque chose comme:
b'abc='
fonctionne aussi bien queb'abc=='
(comme le faitb'abc====='
).Cela signifie que vous pouvez simplement ajouter le nombre maximum de caractères de remplissage dont vous auriez besoin - qui est de trois (
b'==='
) - et base64 tronquera tous les caractères inutiles.Cela vous permet d'écrire:
ce qui est plus simple que:
la source
binascii.Error: Invalid base64-encoded string: number of data characters (5) cannot be 1 more than a multiple of 4
. Merci de l'avoir signalé!«Remplissage incorrect» peut signifier non seulement «remplissage manquant» mais aussi (croyez-le ou non) «remplissage incorrect».
Si les méthodes "d'ajout de remplissage" suggérées ne fonctionnent pas, essayez de supprimer quelques octets de fin:
Mise à jour: Tout tripotage autour de l'ajout de remplissage ou de la suppression des octets éventuellement incorrects de la fin doit être effectué APRÈS avoir supprimé les espaces, sinon les calculs de longueur seront perturbés.
Ce serait une bonne idée si vous nous montriez un (court) échantillon des données que vous devez récupérer. Modifiez votre question et copiez / collez le résultat de
print repr(sample)
.Mise à jour 2: il est possible que l'encodage ait été effectué de manière sécurisée pour les URL. Si tel est le cas, vous pourrez voir des caractères moins et des traits de soulignement dans vos données, et vous devriez pouvoir les décoder en utilisant
base64.b64decode(strg, '-_')
Si vous ne pouvez pas voir les caractères moins et les traits de soulignement dans vos données, mais que vous pouvez voir les caractères plus et les barres obliques, vous avez un autre problème et vous aurez peut-être besoin des astuces add-padding ou remove-cruft.
Si vous ne voyez aucun signe moins, trait de soulignement, plus et barre oblique dans vos données, vous devez déterminer les deux caractères alternatifs; ce seront ceux qui ne sont pas dans [A-Za-z0-9]. Ensuite, vous devrez expérimenter pour voir dans quel ordre ils doivent être utilisés dans le 2ème argument de
base64.b64decode()
Mise à jour 3 : Si vos données sont "confidentielles de l'entreprise":
(a) vous devriez le dire dès le départ
(b) nous pouvons explorer d'autres voies pour comprendre le problème, qui est très probablement lié aux caractères utilisés à la place
+
et/
dans l'alphabet de codage, ou par un autre formatage ou des caractères superflus.Une de ces possibilités serait d'examiner quels caractères non "standard" sont dans vos données, par exemple
la source
Utilisation
Le crédit va à un commentaire quelque part ici.
la source
S'il y a une erreur de remplissage, cela signifie probablement que votre chaîne est corrompue; Les chaînes codées en base64 doivent avoir un multiple de quatre longueurs. Vous pouvez essayer d'ajouter le caractère de remplissage (
=
) vous-même pour rendre la chaîne un multiple de quatre, mais il devrait déjà l'avoir à moins que quelque chose ne va pasla source
Consultez la documentation de la source de données que vous essayez de décoder. Est-il possible que vous vouliez utiliser à la
base64.urlsafe_b64decode(s)
place debase64.b64decode(s)
? C'est l'une des raisons pour lesquelles vous avez peut-être vu ce message d'erreur.C'est par exemple le cas pour diverses API de Google, comme la boîte à outils d'identité de Google et les charges utiles Gmail.
la source
urlsafe_b64decode
nécessite également un rembourrage.base64.urlsafe_b64decode
.L'ajout du rembourrage est plutôt ... délicat. Voici la fonction que j'ai écrite à l'aide des commentaires de ce fil ainsi que de la page wiki pour base64 (c'est étonnamment utile) https://en.wikipedia.org/wiki/Base64#Padding .
la source
Vous pouvez simplement utiliser
base64.urlsafe_b64decode(data)
si vous essayez de décoder une image Web. Il s'occupera automatiquement du rembourrage.la source
Il y a deux façons de corriger les données d'entrée décrites ici, ou, plus spécifiquement et en ligne avec l'OP, de rendre la méthode b64decode du module Python base64 capable de traiter les données d'entrée en quelque chose sans lever d'exception non interceptée:
Si cela soulève une exception, alors
je. Attrapez-le via try / except,
ii. (R?) Supprimez tous les caractères = des données d'entrée (NB cela peut ne pas être nécessaire),
iii. Ajoutez A == aux données d'entrée (A == à P == fonctionnera),
iv. Appelez base64.b64decode (...) avec ces A == - données d'entrée ajoutées
Le résultat de l'élément 1. ou de l'élément 2. ci-dessus donnera le résultat souhaité.
Mises en garde
Cela ne garantit pas que le résultat décodé sera ce qui a été encodé à l'origine, mais cela donnera (parfois?) À l'OP suffisamment pour travailler avec:
Voir ce que nous savons et hypothèses ci-dessous.
TL; DR
De quelques tests rapides de base64.b64decode (...)
il semble qu'il ignore les caractères non- [A-Za-z0-9 + /]; cela inclut ignorer = s à moins qu'il ne s'agisse du (des) dernier (s) caractère (s) d'un groupe analysé de quatre, auquel cas les = s terminent le décodage (a = b = c = d = donne le même résultat que abc =, et a = = b == c == donne le même résultat que ab ==).
Il apparaît également que tous les caractères ajoutés sont ignorés après le point où base64.b64decode (...) termine le décodage, par exemple à partir d'un = comme quatrième d'un groupe.
Comme indiqué dans plusieurs commentaires ci-dessus, il y a soit zéro, soit un, ou deux = s de remplissage requis à la fin des données d'entrée lorsque la valeur [nombre de caractères analysés jusqu'à ce point modulo 4] est 0, ou 3, ou 2, respectivement. Ainsi, à partir des éléments 3. et 4. ci-dessus, l'ajout de deux ou plusieurs = s aux données d'entrée corrigera tout problème de [remplissage incorrect] dans ces cas.
CEPENDANT, le décodage ne peut pas gérer le cas où le [nombre total de caractères analysés modulo 4] est 1, car il faut au moins deux caractères codés pour représenter le premier octet décodé dans un groupe de trois octets décodés. Dans les données d'entrée codées non corrompues, ce cas [N modulo 4] = 1 ne se produit jamais, mais comme l'OP a déclaré que des caractères peuvent être manquants, cela peut se produire ici. C'est pourquoi simplement ajouter = s ne fonctionnera pas toujours, et pourquoi ajouter A == fonctionnera lorsque l'ajout == ne fonctionnera pas. NB Utiliser [A] est tout sauf arbitraire: il n'ajoute que des bits effacés (zéro) au décodé, ce qui peut être correct ou pas, mais alors l'objet ici n'est pas l'exactitude mais la complétion par base64.b64decode (...) sans exceptions .
Ce que nous savons du PO et surtout des commentaires ultérieurs, c'est
openssl enc ...
fonctionne.Hypothèses
Github
Voici un wrapper pour implémenter cette solution:
https://github.com/drbitboy/missing_b64
la source
Une erreur de remplissage incorrecte est causée car parfois, des métadonnées sont également présentes dans la chaîne codée.Si votre chaîne ressemble à quelque chose comme: 'data: image / png; base64, ... base 64 stuff ....' alors vous devez supprimer le premier partie avant de le décoder.
Dites si vous avez une chaîne encodée en base64 d'image, puis essayez ci-dessous l'extrait de code.
la source
Ajoutez simplement des caractères supplémentaires comme "=" ou tout autre et faites-en un multiple de 4 avant d'essayer de décoder la valeur de la chaîne cible. Quelque chose comme;
la source
Dans le cas où cette erreur proviendrait d'un serveur Web: essayez de coder l'URL de votre valeur de publication. J'étais en train de POSTER via "curl" et j'ai découvert que je n'encodais pas ma valeur base64, donc les caractères comme "+" n'étaient pas échappés, de sorte que la logique de décodage d'url du serveur Web exécutait automatiquement le décodage d'url et convertissait + en espaces.
"+" est un caractère base64 valide et peut-être le seul caractère qui est mutilé par un décodage d'URL inattendu.
la source
Dans mon cas, j'ai rencontré cette erreur lors de l'analyse d'un e-mail. J'ai obtenu la pièce jointe sous forme de chaîne base64 et je l'ai extraite via re.search. Finalement, il y avait une étrange sous-chaîne supplémentaire à la fin.
Quand j'ai supprimé
--_=ic0008m4wtZ4TqBFd+sXC8--
et dépouillé la chaîne, l'analyse a été corrigée.Je vous conseille donc de vous assurer que vous décodez une chaîne base64 correcte.
la source
Tu devrais utiliser
Par défaut, les altchars sont
'+/'
.la source
J'ai également rencontré ce problème et rien n'a fonctionné. J'ai finalement réussi à trouver la solution qui me convient. J'avais compressé du contenu en base64 et cela est arrivé à 1 disque sur un million ...
Il s'agit d'une version de la solution proposée par Simon Sapin.
Dans le cas où le remplissage manque 3, je supprime les 3 derniers caractères.
Au lieu de "0gA1RD5L / 9AUGtH9MzAwAAA =="
Nous obtenons "0gA1RD5L / 9AUGtH9MzAwAA"
Selon cette réponse Trailing Comme dans base64, la raison est null. Mais je n'ai toujours aucune idée de la raison pour laquelle l'encodeur gâche tout ça ...
la source