计算哈希并将其添加到 python 中的文件

Calculate and add hash to a file in python

一种检查文件是否已被修改的方法是计算并存储文件的哈希值(或校验和)。然后在任何时候都可以重新计算哈希值并将其与存储的值进行比较。

我想知道是否有办法将文件的哈希值存储在文件本身中?我在考虑文本文件。

计算散列的算法应该是迭代的,并且考虑将散列添加到正在为其计算散列的文件中...有意义吗?有空吗?

谢谢!

编辑: https://security.stackexchange.com/questions/3851/can-a-file-contain-its-md5sum-inside-it

好吧,虽然它看起来像一个奇怪的想法,但它可能是 windows NTFS 文件系统的 属性 的一个应用程序:File Streams.

它允许在不更改默认流内容的情况下将许多 添加到文件中。例如:

echo foo > foo.text
echo bar > foo.text:alt
type foo.text
=>   foo
more < foo.text:alt
=>   bar

但是列出目录时,您只能看到一个文件:foo.txt

所以在你的用例中,你可以在名为 hash 的流中写入主流的哈希值,然后将 hash 流的内容与主流的哈希值进行比较。

请注意:由于我不知道的原因,type foo.text:alt 生成以下错误:

"The filename, directory name, or volume label syntax is incorrect."

这就是为什么我的示例按照 MSDNUsing streams page 中的建议使用 more <

所以假设你有一个 myhash 函数来给出文件的哈希值(你可以使用 hashlib 模块轻松构建一个):

def myhash(filename):
    # compute the hash of the file
    ...
    return hash_string

你可以这样做:

def store_hash(filename):
    hash_string = myhash(filename)
    with open(filename + ":hash") as fd:
        fd.write(hash_string)

def compare_hash(filename):
        hash_string = myhash(filename)
        with open(filename + ":hash") as fd:
            orig = fd.read()
        return (hash_string == orig)
from Crypto.Hash import HMAC
secret_key = "Don't tell anyone"
h = HMAC.new(secret_key)
text = "whatever you want in the file"
## or: text = open("your_file_without_hash_yet").read()
h.update(text)
with open("file_with_hash") as fh:
    fh.write(text)
    fh.write(h.hexdigest())

现在,正如某些人试图指出的那样,尽管他们看起来很困惑 - 您需要记住该文件的末尾有散列,并且散列本身不是散列的一部分。所以当你想 检查 文件时,你会按照以下行做一些事情:

end_len = len(h.hex_digest())
all_text = open("file_with_hash").read()
text, expected_hmac = all_text[:end_len], all_text[end_len:]
h = HMAC.new(secret_key)
h.update(text)
if h.hexdigest() != expected_hmac:
    raise "Somebody messed with your file!"

应该清楚的是,仅此 并不能确保您的文件未被更改;典型的用例是加密您的文件,但采用明文的哈希值。这样,如果有人更改了哈希值(在文件末尾)或尝试更改消息中的任何字符(加密部分),事情就会不匹配,你就会知道发生了什么变化。

恶意行为者将无法更改文件并修复哈希以匹配,因为他们需要更改一些数据,然后使用您的私钥重新哈希所有内容 .只要没有人知道您的私钥,他们就不知道如何重新创建正确的哈希值。

这是一个有趣的问题。如果您采用适当的约定来散列和验证文件的完整性,就可以做到这一点。假设你有这个文件,即 main.py:

#!/usr/bin/env python
# encoding: utf-8
print "hello world"

现在,您可以将 SHA-1 散列作为注释附加到 python 文件:

(printf '#'; cat main.py | sha1sum) >> main.py

已更新main.py

#!/usr/bin/env python
# encoding: utf-8
print "hello world"
#30e3b19d4815ff5b5eca3a754d438dceab9e8814  -

因此,要验证文件是否被修改,您可以在 Bash:

中执行此操作
if [ "$(printf '#';head -n-1 main.py | sha1sum)" == "$(tail -n1 main.py)" ]
then
    echo "Unmodified"
else 
    echo "Modified"
fi

当然,有人可能会通过手动更改哈希字符串来欺骗您。为了阻止这些坏人,您可以通过在将哈希添加到最后一行之前使用 秘密字符串 调整文件来改进系统。

改进版

在最后一行添加哈希值,包括您的秘密字符串:

(printf '#';cat main.py;echo 'MyUltraSecretTemperString12345') | sha1sum >> main.py

检查文件是否被修改:

if [ "$(printf '#';(head -n-1 main.py; echo 'MyUltraSecretTemperString12345') | sha1sum)" == "$(tail -n1 main.py)" ]
then
    echo "Unmodified"
else 
    echo "Modified"
fi

使用这个改进的版本,坏人只有先找到你的超级密钥才能愚弄你。

编辑: 这是 keyed-hash message authentication code (HMAC).

的粗略实现