使用Python检查一个字符串是否是base64编码的

53

有没有一种好的方法可以使用Python检查一个字符串是否是用base64编码的?

11个回答

77

我曾经遇到和你一样的问题,后来一个非常简单的解决方法突然在我脑海中浮现。你所需要做的就是解码,然后重新编码。如果重新编码后的字符串与原来的编码字符串相等,那么它就是base64编码。
以下是代码:

import base64

def isBase64(s):
    try:
        return base64.b64encode(base64.b64decode(s)) == s
    except Exception:
        return False

就是这样!

编辑:这是该函数的版本,可适用于Python 3中的字符串和字节对象:

import base64

def isBase64(sb):
        try:
                if isinstance(sb, str):
                        # If there's any unicode here, an exception will be thrown and the function will return false
                        sb_bytes = bytes(sb, 'ascii')
                elif isinstance(sb, bytes):
                        sb_bytes = sb
                else:
                        raise ValueError("Argument must be string or bytes")
                return base64.b64encode(base64.b64decode(sb_bytes)) == sb_bytes
        except Exception:
                return False

如果您喜欢lambda:'isBase64 = lambda x:x.decode('base64').encode('base64').replace('\ n','')== x' 请注意,此代码有时会抛出不正确的填充异常。 - id01
3
附注:你可以直接使用return base64.b64encode(base64.b64decode(s)) == s,而不是使用if语句并返回一个常量布尔结果 :) - d0nut
6
isBase64('test') 返回True,意思是'test'是一个Base64编码的字符串。 - ahmed
2
@ahmed,这是因为“test”是一个有效的base64字符串。Base64包括a-z、A-Z、0-9、+、/和=用于填充。 - id01
5
因为Python3中strbytes无法自动隐式转换类型以进行比较,所以我不得不使用return base64.b64encode(base64.b64decode(s)).decode() == s来使其工作。因为我的s是Unicode字符串,而从base64.b64encode(base64.b64decode(s))返回的值是bytes类型。请参见:https://dev59.com/G10a5IYBdhLWcg3wNWbA。 - Vikas Prasad
显示剩余4条评论

39
import base64
import binascii

try:
    base64.decodestring("foo")
except binascii.Error:
    print "no correct base64"

1
我在文档中没有找到任何内容。 - user647772
3
"宁可在事后请求原谅,也不要在事前征得许可",尽管我更倾向于捕获可能会出现的实际异常(我认为将是binascii.Error)。 - LexyStardust
23
这是错误的,“base64.decodestring('čččč')”返回一个空字符串而没有异常,但我不认为字符串“čččč”是有效的base64字符串。 - Roman Plášil
2
base64.decodestring("dfdsfsdf ds fk") 不会引发 TypeError,因为该字符串似乎不是一个 base64 字符串。 - erny
7
如果s是有效的,base64.b64decode(s, validate=true)会解码它,否则会引发异常。而base64.decodestring非常宽容,会删除任何不是Base64字符的内容,这有潜在问题。 - Julian
显示剩余3条评论

21

这是不可能的。你最好的做法是验证一个字符串是否可能是有效的Base 64,尽管很多只包含ASCII文本的字符串在解码时可以像Base 64一样工作。


2
这真的是答案吗? - coler-j
3
是的,从技术上讲是正确的。可能这应该是一条评论,但在2012年Stack Overflow还不同吧。也许。 - Wooble

11
我使用的解决方案基于之前的答案之一,但使用了更现代的调用。
在我的代码中,my_image_string 可能是原始形式的图像数据或者它是一个 base64 字符串。如果解码失败,则我假定它是原始数据。
请注意,在 b64decode 中的 validate=True 关键字参数。这是必需的,以便解码器生成 assert。如果没有它,就不会有关于非法字符串的投诉。
import base64, binascii

try:
    image_data = base64.b64decode(my_image_string, validate=True)
except binascii.Error:
    image_data = my_image_string

4

使用Python正则表达式

import re

txt = "VGhpcyBpcyBlbmNvZGVkIHRleHQ="
x = re.search("^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$", txt)

if (x):
  print("Encoded")
else:
  print("Non encoded")

3
在尝试解码之前,我喜欢先进行格式检查,因为这是最轻量级的检查,不会返回错误的结果,从而遵循fail-fast编程原则。
以下是用于此任务的实用函数:
RE_BASE64 = "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$"
def likeBase64(s:str) -> bool:
    return False if s is None or not re.search(RE_BASE64, s) else True

2

@geoffspear是正确的,这不是100%可能的,但您可以通过检查字符串头部是否与base64编码字符串匹配(参见:如何检查字符串是否已经进行了base64编码)来接近实现。

# check if a string is base64 encoded.
def isBase64Encoded(s):
    pattern = re.compile("^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$")
    if not s or len(s) < 1:
        return False
    else:
        return pattern.match(s)

请注意,我的情况是如果字符串为空,则希望返回false,以避免解码,因为解码空字符串没有用处。


2
如果编码字符串的长度是4的倍数,它可以被解码。
base64.encodestring("whatever you say").strip().__len__() % 4 == 0

所以,你只需要检查字符串是否能够匹配上面的某些内容,那么它就不会抛出任何异常(我猜 =.=)

if len(the_base64string.strip()) % 4 == 0:
    # then you can just decode it anyway
    base64.decodestring(the_base64string)

这对于仍然是有效的带有 \n 的字符串不起作用。 - plaisthos

2

我知道我晚了近8年,但你可以使用正则表达式,这样你就可以验证给定的输入是否为BASE64。

import re

encoding_type = 'Encoding type: '
base64_encoding = 'Base64'


def is_base64():
    element = input("Enter encoded element: ")
    expression = "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$"

    matches = re.match(expression, element)

    if matches:
        print(f"{encoding_type + base64_encoding}")
    else:
        print("Unknown encoding type.")


is_base64()

1
def is_base64(s):
    s = ''.join([s.strip() for s in s.split("\n")])
    try:
        enc = base64.b64encode(base64.b64decode(s)).strip()
        return enc == s
    except TypeError:
        return False

在我的情况下,我的输入s包含换行符,我必须在比较之前将其去除。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接