检查文件是否已被修改的方法是计算并存储文件的哈希(或校验和)。然后,在任何时候都可以重新计算哈希并将其与存储的值进行比较。
我想知道是否有办法在文件中存储文件的哈希值?我在想文本文件。
计算哈希值的算法应该是迭代的,并且考虑将哈希值添加到正在计算哈希值的文件中......有意义吗?有什么可用吗?
谢谢!
编辑: https://security.stackexchange.com/questions/3851/can-a-file-contain-its-md5sum-inside-it
答案 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
使用这个改进的版本,坏人只有在他们首先找到你的超密钥时才会欺骗你。
答案 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)