Week 3: 边下边播完整性校验作业

边下边播完整性校验

week 3最后的编程作业是解决体积较大的视频文件边下边播完整性校验问题, 原题如下:

Suppose a web site hosts large video file F F F that anyone can download. Browsers who download the file need to make sure the file is authentic before displaying the content to the user. One approach is to have the web site hash the contents of F F F using a collision resistant hash and then distribute the resulting short hash value h = H ( F ) h=H(F) h=H(F) to users via some authenticated channel (later on we will use digital signatures for this). Browsers would download the entire file FF, check that H ( F ) H(F) H(F) is equal to the authentic hash value h h h and if so, display the video to the user. Unfortunately, this means that the video will only begin playing after the entire file F F F has been downloaded.

Our goal in this project is to build a file authentication system that lets browsers authenticate and play video chunks as they are downloaded without having to wait for the entire file. Instead of computing a hash of the entire file, the web site breaks the file into 1KB blocks (1024 bytes). It computes the hash of the last block and appends the value to the second to last block. It then computes the hash of this augmented second to last block and appends the resulting hash to the third block from the end. This process continues from the last block to the first as in the following diagram:
在这里插入图片描述
The final hash value h 0 – a h_0 – a h0a hash of the first block with its appended hash – is distributed to users via the authenticated channel as above.

Now, a browser downloads the file F F F one block at a time, where each block includes the appended hash value from the diagram above. When the first block ( B 0 ∣ ∣ h 1 ) (B_0 || h_1) (B0h1) is received the browser checks that H ( B 0 ∣ ∣ h 1 ) H(B_0 || h_1) H(B0h1) is equal to h 0 h_0 h0 and if so it begins playing the first video block. When the second block
( B 1 ∣ ∣ h 2 ) (B_1 || h_2) (B1h2) is received the browser checks that H ( B 1 ∣ ∣ h 2 ) H(B_1 || h_2) H(B1h2) is equal to h 1 h_1 h1 and if so it plays this second block. This process continues until the very last block. This way each block is authenticated and played as it is received and there is no need to wait until the entire file is downloaded.

It is not difficult to argue that if the hash function H H H is collision resistant then an attacker cannot modify any of the video blocks without being detected by the browser. Indeed, since h 0 = H ( B 0 ∣ ∣ h 1 ) h_0=H(B_0 || h_1) h0=H(B0h1) an attacker cannot find a pair ( B 0 ′ , h 1 ′ ) ≠ ( B 0 , h 1 ) (B^{'}_0,h^{'}_1) \neq (B_0,h_1) (B0,h1)=(B0,h1) such that h 0 = H ( B 0 ′ , h 1 ′ ) h_0=H(B^{'}_0,h^{'}_1) h0=H(B0,h1) since this would break collision resistance of H H H. Therefore after the first hash check the browser is convinced that both B 0 B_0 B0 and h 1 h_1 h1 are authentic. Exactly the same argument proves that after the second hash check the browser is convinced that both B 1 B_1 B1 and h 2 h_2 h2 are authentic, and so on for the remaining blocks.

In this project we will be using SHA256 as the hash function. For an implementation of SHA256 use an existing crypto library such as PyCrypto (Python), Crypto++ (C++), or any other.

When appending the hash value to each block, please append it as binary data, that is, as 32 unencoded bytes (which is 256 bits). If the file size is not a multiple of 1KB then the very last block will be shorter than 1KB, but all other blocks will be exactly 1KB.
Your task is to write code to compute the hash h 0 h_0 h0 of a given file F F F and to verify blocks of F F F as they are received by the client.
In the box below please enter the (hex encoded) hash h 0 h_0 h0 for this video file.
You can check your code by using it to hash a different file. In particular, the hex encoded h 0 h_0 h0 for this video file is:
03c08f4ee0b576fe319338139c045c89c3e8e9409633bea29442e21425006ea8

解题思路

如题中所示,分为两部分:

  1. 将文件按1KB(1024B)大小进行分块
  2. 然后逆序从最后一块往前算sha256
  3. 直到算出第首块的hash值 h 0 h_0 h0

样例程序

代码

from Crypto.Hash import SHA256
from typing import Tuple, List


def split_file_into_chunks(path: str, chunk: int) -> List[bytes]:
    """
    将文件按大小切分成块
    :param path: 文件路径
    :param chunk: 大小
    :return:
    """
    with open(path, 'rb') as ivl:
        bytes_content = ivl.read()
        total_len = len(bytes_content)
        chunks = list()
        for i in range(0, total_len, chunk):
            chunks.append(bytes_content[i: i + chunk])
        return chunks

def compute_h0_hash(chunks: List[bytes]) -> (SHA256.SHA256Hash, List[Tuple[bytes, str]]):
    """
    计算hash
    :param chunks:
    :return:
    """
    result_list = list()
    last_chuck_hash = SHA256.new(chunks[-1])
    for i in range(len(chunks) - 2, -1, -1):
        result_list.append((chunks[i], last_chuck_hash))
        last_chuck_hash = SHA256.new(chunks[i] + last_chuck_hash.digest())
    result_list.reverse()  # 翻转,使得第一块在最前面
    return last_chuck_hash, result_list


if __name__ == "__main__":
    chunks = split_file_into_chunks("6.2.birthday.mp4_download", 1024)
    h0, _ = compute_h0_hash(chunks)
    print("test h0: {}".format(h0.hexdigest()))

    chunks = split_file_into_chunks("6.1.intro.mp4_download", 1024)
    h0, _ = compute_h0_hash(chunks)
    print("trail h0: {}".format(h0.hexdigest()))

结果

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值