1#!/usr/bin/python3 2 3# Copyright 2022 The Chromium Authors. All rights reserved. 4# Use of this source code is governed by a BSD-style license that can be 5# found in the LICENSE file. 6 7import hashlib 8import itertools 9import sys 10 11PAGE_SIZE = 0x1000 # System page size. 12HASH_SIZE = 8 # Size of the hash in bytes. 13 14 15def hash_pages(data): 16 out = bytearray() 17 18 offset = 0 19 while offset < len(data): 20 # Extract a page and pad it with zeroes in case it's not a full page. 21 # This is to emulate the behavior of mmap in Linux (and thus ChromeOS) 22 # environments. 23 # 24 # "POSIX specifies that the system shall always zero fill any 25 # partial page at the end of the object [...]". 26 # 27 # Reference: https://man7.org/linux/man-pages/man2/mmap.2.html 28 page = bytearray(data[offset : offset + PAGE_SIZE]) 29 page.extend(itertools.repeat(0x00, PAGE_SIZE - len(page))) 30 31 # Calculate the hash of the page. 32 digest = hashlib.blake2b(page, digest_size=HASH_SIZE).digest() 33 out.extend(digest) 34 35 offset += PAGE_SIZE 36 37 return out 38 39 40if __name__ == "__main__": 41 # Check arguments. 42 if len(sys.argv) != 3: 43 error_str = "icuhash: wrong number of arguments\n\n" 44 help_str = "usage: icuhash <infilename> <outfilename>\n\n" 45 sys.exit(error_str + help_str) 46 47 # Extract arguments. 48 in_filename = sys.argv[1] 49 out_filename = sys.argv[2] 50 51 # Read the input file. 52 with open(in_filename, "rb") as in_file: 53 data = in_file.read() 54 # Calculate hashes for each page of the file. 55 out_data = hash_pages(data) 56 # Write the output file. 57 with open(out_filename, "wb") as out_file: 58 out_file.write(out_data) 59