Python:当base64解码时忽略'不正确的填充'错误

我有一些base64编码的数据,我想要转换回二进制,即使有一个填充错误。 如果我使用

base64.decodestring(b64_string) 

它会引发“不正确的填充”错误。 有另一种方法吗?

更新:感谢所有的反馈。 说实话,所有提到的方法听起来有点打击和思念,所以我决定尝试openssl。 以下命令工作:

 openssl enc -d -base64 -in b64string -out binary_data 

正如其他答复中所述,Base64数据可能有多种方式被破坏。

但是,正如维基百科所说的那样,删除填充(base64编码数据末尾的“=”字符)是“无损”的:

从理论的angular度来看,填充字符是不需要的,因为丢失字节的数量可以从Base64数字的个数计算出来。

所以,如果这真的是你的base64数据的唯一“错误”,填充可以加回来。 我想出了这个能够parsingWeasyPrint中的“数据”URL,其中一些是没有填充的base64:

 def decode_base64(data): """Decode base64, padding being optional. :param data: Base64 data as an ASCII byte string :returns: The decoded byte string. """ missing_padding = len(data) % 4 if missing_padding != 0: data += b'='* (4 - missing_padding) return base64.decodestring(data) 

testing这个函数: weasyprint / tests / test_css.py#L68

如果有填充错误,可能意味着你的string被破坏; base64编码的string应该有四个长度的倍数。 你可以尝试自己添加填充字符( = )来使string成为四的倍数,但它应该已经有了,除非出现错误

“不正确的填充”可能不仅意味着“缺less填充”,而且(不pipe信不信)“不正确的填充”。

如果build议“添加填充”方法不起作用,请尝试删除一些尾随字节:

 lens = len(strg) lenx = lens - (lens % 4 if lens % 4 else 4) try: result = base64.decodestring(strg[:lenx]) except etc 

更新:添加填充或从最后删除可能的坏字节的任何摆弄都应该在删除任何空格之后完成,否则长度计算将会失败。

如果您向我们展示了您需要恢复的(短)样本数据,那将是一个好主意。 编辑你的问题,并复制/粘贴 print repr(sample) 的结果

更新2:编码可能以url安全的方式完成。 如果是这种情况,你将能够在你的数据中看到减号和下划线字符,你应该能够使用base64.b64decode(strg, '-_')来解码它。

如果在数据中看不到减号和下划线字符,但可以看到加号和斜杠字符,则还有其他一些问题,可能需要添加填充或移除垃圾邮件的技巧。

如果您的数据中不能看到减号,下划线,加号​​和斜杠,则需要确定两个替代字符; 他们将是不是在[A-ZA-Z0-9]。 然后你需要试验一下在base64.b64decode()的第二个参数中需要使用哪个顺序。

更新3 :如果您的数据是“公司机密”:
(a)你应该这么说
(b)我们可以探索其他途径来理解问题,这很可能与使用什么字符而不是编码字母表中的+/或其他格式或无关字符有关。

一个这样的途径就是检查你的数据中的非标准字符,例如

 from collections import defaultdict d = defaultdict(int) import string s = set(string.ascii_letters + string.digits) for c in your_data: if c not in s: d[c] += 1 print d 

只要根据需要添加填充。 但是,请注意迈克尔的警告。

 b64_string += "=" * ((4 - len(b64_string) % 4) % 4) #ugh 

使用

 string += '=' * (-len(string) % 4) # restore stripped '='s 

信贷在这里的某处发表评论。

 >>> import base64 >>> enc = base64.b64encode('1') >>> enc >>> 'MQ==' >>> base64.b64decode(enc) >>> '1' >>> enc = enc.rstrip('=') >>> enc >>> 'MQ' >>> base64.b64decode(enc) ... TypeError: Incorrect padding >>> base64.b64decode(enc + '=' * (-len(enc) % 4)) >>> '1' >>> 

尝试任何其他的事情之前,尝试使用base64.urlsafe_b64decode(s)

使用URL安全字母表替代strings,而不是使用+和_代替标准Base64字母表中的/。

这个错误也可以通过在你想要解码的string末尾加一个换行符来提高。 如果您正在读取文件并无意中获取换行符,则可能发生这种情况。 例如。

 $ cat decode_strings.txt GA4TSNRSGE====== 

上面是一个文件的例子,所以Python:

 file = open('decode_strings.txt', 'r') for decode_str in file: print decode_str # try to decode it id = base64.b32decode(decode_str) print id 

将输出如下所示:

  raise TypeError('Incorrect padding') TypeError: Incorrect padding 

如果使用以下代码更新代码,则可以看到换行符:

 for decode_str in file: print decode_str print "Look at that newline above me :( " try: id = base64.b32decode(decode_str) except: pass 

这应该输出:

 GA4TSNRSGE====== Look at that newline above me :( 

要解决这个问题,只需在你的string上使用.rstrip():

  for decode_str in file: decode_str = decode_str.rstrip() id = base64.b32decode(decode_str) print decode_str, id 

在尝试解码目标string值之前,只需添加其他字符(如“=”或其他字符),并将其设置为4的倍数。 就像是;

 if len(value) % 4 != 0: #check if multiple of 4 while len(value) % 4 != 0: value = value + "=" req_str = base64.b64decode(value) else: req_str = base64.b64decode(value) 

添加填充是相当…很费劲。 下面是我在这个线程的注释帮助下写的函数,以及base64的维基页面(这非常有帮助) https://en.wikipedia.org/wiki/Base64#Padding

 import logging import base64 def base64_decode(s): """Add missing padding to string and return the decoded base64 string.""" log = logging.getLogger() s = str(s).strip() try: return base64.b64decode(s) except TypeError: padding = len(s) % 4 if padding == 1: log.error("Invalid base64 string: {}".format(s)) return '' elif padding == 2: s += b'==' elif padding == 3: s += b'=' return base64.b64decode(s)