【问题标题】:How to verify integrity of files using digest in python (SHA256SUMS)如何在 python (SHA256SUMS) 中使用摘要验证文件的完整性
【发布时间】:2020-08-24 20:30:37
【问题描述】:

我有一组文件和一个 SHA256SUMS digest file,其中包含每个文件的 sha256() 哈希值。使用 python 验证文件完整性的最佳方法是什么?

例如,我将下载 Debian 10 网络安装程序 SHA256SUMS 摘要文件并在 BASH 中下载/验证其 MANIFEST 文件

user@host:~$ wget http://ftp.nl.debian.org/debian/dists/buster/main/installer-amd64/current/images/SHA256SUMS
--2020-08-25 02:11:20--  http://ftp.nl.debian.org/debian/dists/buster/main/installer-amd64/current/images/SHA256SUMS
Resolving ftp.nl.debian.org (ftp.nl.debian.org)... 130.89.149.21, 2001:67c:2564:a120::21
Connecting to ftp.nl.debian.org (ftp.nl.debian.org)|130.89.149.21|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 75295 (74K)
Saving to: ‘SHA256SUMS’

SHA256SUMS          100%[===================>]  73.53K  71.7KB/s    in 1.0s    

2020-08-25 02:11:22 (71.7 KB/s) - ‘SHA256SUMS’ saved [75295/75295]

user@host:~$ wget http://ftp.nl.debian.org/debian/dists/buster/main/installer-amd64/current/images/MANIFEST
--2020-08-25 02:11:27--  http://ftp.nl.debian.org/debian/dists/buster/main/installer-amd64/current/images/MANIFEST
Resolving ftp.nl.debian.org (ftp.nl.debian.org)... 130.89.149.21, 2001:67c:2564:a120::21
Connecting to ftp.nl.debian.org (ftp.nl.debian.org)|130.89.149.21|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1709 (1.7K)
Saving to: ‘MANIFEST’

MANIFEST            100%[===================>]   1.67K  --.-KB/s    in 0s      

2020-08-25 02:11:28 (128 MB/s) - ‘MANIFEST’ saved [1709/1709]

user@host:~$ sha256sum --check --ignore-missing SHA256SUMS 
./MANIFEST: OK
user@host:~$ 

在 python 中执行相同操作的最佳方法是什么(使用SHA256SUMS 文件下载并验证 Debian 10 MANIFEST 文件的完整性)?

【问题讨论】:

    标签: python python-3.x checksum sha256 data-integrity


    【解决方案1】:

    以下 python 脚本实现了一个名为 integrity_is_ok() 的函数,该函数获取 SHA256SUMS 文件的路径和要验证的文件列表,如果任何文件无法验证,则返回 False 并且True 否则。

    #!/usr/bin/env python3
    from hashlib import sha256
    import os
    
    # Takes the path (as a string) to a SHA256SUMS file and a list of paths to
    # local files. Returns true only if all files' checksums are present in the
    # SHA256SUMS file and their checksums match
    def integrity_is_ok( sha256sums_filepath, local_filepaths ):
    
        # first we parse the SHA256SUMS file and convert it into a dictionary
        sha256sums = dict()
        with open( sha256sums_filepath ) as fd:
            for line in fd:
                # sha256 hashes are exactly 64 characters long
                checksum = line[0:64]
    
                # there is one space followed by one metadata character between the
                # checksum and the filename in the `sha256sum` command output
                filename = os.path.split( line[66:] )[1].strip()
                sha256sums[filename] = checksum
    
        # now loop through each file that we were asked to check and confirm its
        # checksum matches what was listed in the SHA256SUMS file
        for local_file in local_filepaths:
    
            local_filename = os.path.split( local_file )[1]
    
            sha256sum = sha256()
            with open( local_file, 'rb' ) as fd:
                data_chunk = fd.read(1024)
                while data_chunk:
                    sha256sum.update(data_chunk)
                    data_chunk = fd.read(1024)
    
            checksum = sha256sum.hexdigest()
            if checksum != sha256sums[local_filename]:
                return False
    
        return True
    
    if __name__ == '__main__':
    
        script_dir = os.path.split( os.path.realpath(__file__) )[0]
        sha256sums_filepath = script_dir + '/SHA256SUMS'
        local_filepaths = [ script_dir + '/MANIFEST' ]
    
        if integrity_is_ok( sha256sums_filepath, local_filepaths ):
            print( "INFO: Checksum OK" )
        else:
            print( "ERROR: Checksum Invalid" )
    

    这是一个执行示例:

    user@host:~$ wget http://ftp.nl.debian.org/debian/dists/buster/main/installer-amd64/current/images/SHA256SUMS
    --2020-08-25 22:40:16--  http://ftp.nl.debian.org/debian/dists/buster/main/installer-amd64/current/images/SHA256SUMS
    Resolving ftp.nl.debian.org (ftp.nl.debian.org)... 130.89.149.21, 2001:67c:2564:a120::21
    Connecting to ftp.nl.debian.org (ftp.nl.debian.org)|130.89.149.21|:80... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 75295 (74K)
    Saving to: ‘SHA256SUMS’
    
    SHA256SUMS          100%[===================>]  73.53K   201KB/s    in 0.4s    
    
    2020-08-25 22:40:17 (201 KB/s) - ‘SHA256SUMS’ saved [75295/75295]
    
    user@host:~$ wget http://ftp.nl.debian.org/debian/dists/buster/main/installer-amd64/current/images/MANIFEST
    --2020-08-25 22:40:32--  http://ftp.nl.debian.org/debian/dists/buster/main/installer-amd64/current/images/MANIFEST
    Resolving ftp.nl.debian.org (ftp.nl.debian.org)... 130.89.149.21, 2001:67c:2564:a120::21
    Connecting to ftp.nl.debian.org (ftp.nl.debian.org)|130.89.149.21|:80... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 1709 (1.7K)
    Saving to: ‘MANIFEST’
    
    MANIFEST            100%[===================>]   1.67K  --.-KB/s    in 0s      
    
    2020-08-25 22:40:32 (13.0 MB/s) - ‘MANIFEST’ saved [1709/1709]
    
    user@host:~$ ./sha256sums_python.py 
    INFO: Checksum OK
    user@host:~$ 
    

    上述代码的部分内容改编自 Ask Ubuntu 上的以下答案:

    【讨论】:

      【解决方案2】:

      您可以按照本博文所述计算每个文件的 sha256sum:

      https://www.quickprogrammingtips.com/python/how-to-calculate-sha256-hash-of-a-file-in-python.html

      生成新清单文件的示例实现可能如下所示:

      import hashlib
      from pathlib import Path
      
      # Your output file
      output_file = "manifest-check"
      
      # Your target directory
      p = Path('.')
      
      sha256_hash = hashlib.sha256()
      
      with open(output_file, "w") as out:
        # Iterate over the files in the directory
        for f in p.glob("**/*"):
          # Process files only (no subdirs)
          if f.is_file():
            with open(filename,"rb") as f:
            # Read the file by chunks
            for byte_block in iter(lambda: f.read(4096),b""):
              sha256_hash.update(byte_block)
            out.write(f + "\t" + sha256_hash.hexdigest() + "\n")
      

      另外,这似乎是通过manifest-checker pip 包实现的。

      您可以在此处查看其来源 https://github.com/TonyFlury/manifest-checkerand 为 python 3 调整它

      【讨论】:

      • 这似乎根本没有使用SHA256SUMS 文件;它只计算哈希。没有比较步骤来检查哈希是否与摘要文件中列出的校验和匹配..
      • 嗯,使用这个 sn-p,您可以计算您下载的每个文件的 sha256 校验和。您仍然需要解析 MANIFEST 文件并将您的输出与文件提供的输出进行比较。您是否想实现不同的目标?
      • 您必须解析SHA256SUMS 文件,而不是MANIFEST。该解析是您的解决方案中缺少的内容,它是问题的重点(确保它可以正确解析使用sha256sum 命令生成的SHA256SUMS 文件的所有有效格式)
      • 您从外部网站逐字复制代码,上面写着“版权所有 © 快速编程技巧。保留所有权利。”我将编辑答案以摆脱它。
      • @mabe02 除非获得许可,否则“合理使用”短报价与复制大块报价之间存在差异。但是,您放置的那个是在 MIT 许可下的,所以我相信您被允许在这里复制那个,而不是您最初使用的那个。 (注意我不是律师 - 这是尽力而为的建议......)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-04
      • 1970-01-01
      • 2018-02-26
      相关资源
      最近更新 更多