Python,获取图像对象的 base64 编码 MD5 哈希

Python, get base64-encoded MD5 hash of an image object

我需要获取一个对象的 base64 编码的 MD5 散列值,其中该对象是存储为文件 fname 的图像。

我试过这个:

def get_md5(fname):
    hash = hashlib.md5()
    with open(fname) as f:
        for chunk in iter(lambda: f.read(4096), ""):
            hash.update(chunk)
    return hash.hexdigest().encode('base64').strip()

但是,我认为这是不对的,因为它 return 是一个包含太多字符的字符串。我的理解是它需要 24 个字符长。我得到

NjJiM2RlOWMzOTYxYmM3MDI5Y2Q1NzdjOTQ5YWRlYTQ=

我也尝试过其他一些类似的方法,例如,一种不执行块循环的方法。它们都是 return 相同的字符串。

(我后来需要 base64 编码的 MD5 哈希的操作失败了,我想这可能就是原因。)

首先,base64编码使字符串变长。 (使用 IPython 和 Python 3 的示例):

In [1]: s = '123456789012345678901234'

In [2]: len(s)
Out[2]: 24

In [3]: import base64

In [4]: e = base64.b64encode(s.encode('utf8'))

In [5]: len(e)
Out[5]: 32

In [6]: e
Out[6]: b'MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0'

使用 base64 编码,每 6 位输入得到 8 位输出。

In [7]: 32/24
Out[7]: 1.333

In [8]: 8/6
Out[8]: 1.333

base64 字母表使用 64(或 2**6)个不同的符号。 通常它们包括小写和大写字母,数字 0-9。这留下了两个额外的必需符号和一个填充字符。 通常 +/ 用作符号,但也有变化。特别是因为 / 在 UNIX 或 MS-Windows 文件名中是不允许的。

其次,使用十六进制表示将字节串的长度加倍;一个字节的十六进制表示可以在 00 和 FF 之间变化。示例(再次使用 IPython 和 Python 3):

In [1]: import hashlib

In [2]: s = b'this is a simple test'

In [3]: len(hashlib.md5(s).digest())
Out[3]: 16

In [4]: len(hashlib.md5(s).hexdigest())
Out[4]: 32

如果无论如何都要使用 base64 编码,那么使用 hexdigest().

是没有意义的

我能够通过使用 digest() 而不是 hexdigest() 使其工作。那么最后一行变成:

return hash.digest().encode('base64').strip()

结果是 24 个字符长,Google 云存储传输接受了它,这需要 base64 编码的 MD5 哈希。

对于Python 3(来自下面的评论):

import base64;  
return base64.b64encode(h.digest()).decode()

我正在为浏览器的 CSP 哈希生成一个带有 base64 编码的内联 javascript 哈希,所以上面接受的答案给出了以下错误。原因是所有类型的字符串都没有处理好

AttributeError: 'bytes' object has no attribute 'encode'

因为 Unicode 对象必须在散列之前进行编码。我在下面的代码中通过 inline.encode('utf-8') 对其进行编码。

要解决该问题,请使用以下方式。这很有魅力。

import hashlib
import base64

base64hash=base64.b64encode(hashlib.sha256(inline.encode('utf-8')).digest())
sha = "sha256-" + base64hash.decode("utf-8")
print(sha)

==> 这是为具有 base64 编码的字符串生成 sha256 哈希。