在python

时间:2016-03-11 12:20:05

标签: python hash checksum

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

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

计算哈希值的算法应该是迭代的,并且考虑将哈希值添加到正在计算哈希值的文件中......有意义吗?有什么可用吗?

谢谢!

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

3 个答案:

答案 0 :(得分:2)

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!"

应该很清楚,单独并不能确保您的文件没有被更改;典型的用例是加密你的文件,但是采用明文的哈希值。这样,如果有人更改了哈希值(在文件的末尾)或者尝试更改邮件中的任何字符(加密部分),那么事情将会不匹配,您将知道某些内容已被更改。

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

答案 1 :(得分:1)

这是一个有趣的问题。如果采用适当的哈希约定并验证文件的完整性,则可以执行此操作。假设您有此文件,即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)的粗略实现。

答案 2 :(得分:0)

虽然它看起来像一个奇怪的想法,但它可能是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会产生以下错误:

  

&#34;文件名,目录名或卷标语法不正确。&#34;

这就是为什么我的示例使用MSDN上Using 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)