Python通过哈希算法实现文件完整性校验-以及大型文件完整性校验

Tips:

下方代码使用了f-string格式化字符串使用Python3.6以下运行时,请修改字符串格式化方法!

文件完整性校验的作用

对于开发的程序,为了防止他人纂改,一般通过哈希算法(md5,sha1,sha256)进行文件的完整性校验

一般校验文件我们会对小型文件和大型文件进行区分

① 如果是小型文件,可以直接通过for循环读取字节流,对所有字节流进行hash加密获取哈希值即可

② 对于大型文件,我们一般会将文件分成多个块

例如: 一个1000字节的文件,分成10块,每次从100,200,300......字节分别读取50字节并连接起来进行哈希计算即可

1. 对于小型文件

本代码仅实现对文件md5值的获取,如果实现密码比较,直接通过布尔运算即可

### 小型文件校验
### 创建两个文本文件,其中第二个文件多了一个字符串8
import hashlib
import os.path


def check_small_file(file_path, enc_type=hashlib.md5()):
    """
        该方法会通过for循环以字节流读取文件
        并且通过updata方法添加到md5对象中进行校验
        如果用于大文件,则会校验很慢
         :param file_path 文件路径
         :param enc_type 加密方式,传入hashlib方法
    """
    enc_obj = enc_type
    with open(file_path, 'rb') as f:
        for line in f:
            enc_obj.update(line)
    return enc_obj.hexdigest()

2. 对于大型文件

大型文件我们需要先获取文件的字节数量,获取字节数量有两种方法进行获取

获取后按照我们需要进行分段的个数,进行整除,然后移动文件指针即可实现分段读取

# 大型文件校验
def check_big_file(file_path: str, check_frequency: int = 10, check_once_bytes=100, enc_type=hashlib.md5()):
    """
         该方法用于大文件校验
         通过seek方法移动文件指针
         保证对文件每10%的地方进行一次读取,并校验其完整性!
         :param file_path 文件路径
         :param check_frequency 校验次数默认10,填写几次则会分个区间去读取并校验
         :check_once_bytes 单次校验字节,默认100个字节
         :param enc_type 加密方式,传入hashlib方法
         :tips 如果文件过小,可能会出现校验出错的文件,所以该方法一般用于大型文件校验
    """
    # 获取文件的字节数(方法1)
    file_bytes = os.path.getsize(file_path)
    enc_obj = enc_type
    with open(file_path, 'rb') as f:
        # 获取文件的字节数(方法2)
        f.seek(0, 2)  # 将文件指针移动到末尾
        file_bytes = f.tell()  # 获取末尾的指针值 -> 字节总数
        check_bytes = file_bytes // check_frequency  # 每次移动的文件字节数
        for i in range(check_frequency):
            f.seek(check_bytes * i, 0)
            enc_obj.update(f.read(check_once_bytes))
    return enc_obj.hexdigest()

3.将上述代码进行整合就可以实现大小文件校验,并且支持多个哈希算法

完整实例如下:

这里就不再写布尔运算了,只要获得加密值就可以了

# coding: utf-8
# @Author: Ruan
# coding:utf-8

### 对于开发后的程序为了防止被人篡改
### 可以使用b模式将文件读取后
### 对文件进行hash处理
### 仅需要对照结果与我们开发时计算的结果是否相同即可
### 并且结果仅需要一串md5值即可


### 小型文件校验
### 创建两个文本文件,其中第二个文件多了一个字符串8
import hashlib
import os.path


def check_small_file(file_path, enc_type=hashlib.md5()):
    """
        该方法会通过for循环以字节流读取文件
        并且通过updata方法添加到md5对象中进行校验
        如果用于大文件,则会校验很慢
         :param file_path 文件路径
         :param enc_type 加密方式,传入hashlib方法
    """
    enc_obj = enc_type
    with open(file_path, 'rb') as f:
        for line in f:
            enc_obj.update(line)
    return enc_obj.hexdigest()


def check_big_file(file_path: str, check_frequency: int = 10, check_once_bytes=100, enc_type=hashlib.md5()):
    """
         该方法用于大文件校验
         通过seek方法移动文件指针
         保证对文件每10%的地方进行一次读取,并校验其完整性!
         :param file_path 文件路径
         :param check_frequency 校验次数默认10,填写几次则会分个区间去读取并校验
         :param enc_type 加密方式,传入hashlib方法
         :tips 如果文件过小,可能会出现校验出错的文件,所以该方法一般用于大型文件校验
    """
    # 获取文件的字节数(方法1)
    file_bytes = os.path.getsize(file_path)
    enc_obj = enc_type
    with open(file_path, 'rb') as f:
        # 获取文件的字节数(方法2)
        f.seek(0, 2)  # 将文件指针移动到末尾
        file_bytes = f.tell()  # 获取末尾的指针值 -> 字节总数
        check_bytes = file_bytes // check_frequency  # 每次移动的文件字节数
        for i in range(check_frequency):
            f.seek(check_bytes * i, 0)
            enc_obj.update(f.read(check_once_bytes))
    return enc_obj.hexdigest()


if __name__ == '__main__':
    initial_file = '.\\files\\原文件.txt'
    modify_file = '.\\files\\被修改的文件.txt'
    md5_init = check_small_file(initial_file)
    md5_modify = check_small_file(modify_file)
    print(f'初始文件md5:{md5_init}\n修改后文件md5:{md5_modify}')
    # 尽管只多了一个字符串8,但是结果却完全不相同
    print(f'使用md5进行节选(大型文件)完整性校验获取的md5值:{check_big_file(initial_file)}')
    print(f'使用sha256进行节选(大型文件)完整性校验获取的sha256值:{check_big_file(initial_file,enc_type=hashlib.sha256())}')

  • 11
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python 文件传输协议是一种用于在计算机网络中传输文件的协议。在计网课设中,可以使用 Python 编程语言开发一个简单的文件传输程序。 首先,我们需要实现服务端和客户端两个部分。服务端负责接收来自客户端的文件传输请求,并将文件保存到指定位置,而客户端负责将指定的文件发送给服务端。 对于服务端部分,我们可以使用 Python 的 socket 模块来建立服务器。通过 socket 模块可以创建一个 TCP/IP 套接字,在指定的端口上监听客户端的连接请求。一旦有客户端连接上来,服务端开始接收文件。 服务端可以定义一个函数,通过 socket 模块接收客户端发送的文件数据,并将数据保存到指定路径下的文件中。在这个函数中,可以使用 Python文件操作函数来写入数据到文件中。同时,为了保证文件完整性,可以使用校验和算法对接收的数据进行校验。 对于客户端部分,我们同样可以使用 socket 模块来建立一个 TCP/IP 的套接字。客户端需要连接到服务端指定的 IP 地址和端口。连接建立后,客户端通过读取文件内容,并调用 socket 模块的发送函数将文件数据发送给服务端。 客户端可以定义一个函数,通过读取指定路径下的文件内容,并将文件数据分块发送给服务端。在发送过程中,可以使用循环将文件数据读取并发送,直到文件全部发送完毕。为了保证文件传输的可靠性,可以使用确认应答机制来确保每一个数据块都被服务端正确接收。 总结起来,开发一个 Python 文件传输协议需要实现服务端和客户端两个部分。服务端通过 socket 模块建立服务器,接收来自客户端的文件传输请求,并将文件数据保存到指定位置。而客户端通过 socket 模块连接到服务端,并将指定的文件数据发送给服务端。通过这种方式,我们可以实现一个简单的文件传输程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值