59 lines
1.7 KiB
Python
Executable File
59 lines
1.7 KiB
Python
Executable File
#!/usr/bin/python3
|
|
|
|
# Copyright 2022 The Chromium Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
import hashlib
|
|
import itertools
|
|
import sys
|
|
|
|
PAGE_SIZE = 0x1000 # System page size.
|
|
HASH_SIZE = 8 # Size of the hash in bytes.
|
|
|
|
|
|
def hash_pages(data):
|
|
out = bytearray()
|
|
|
|
offset = 0
|
|
while offset < len(data):
|
|
# Extract a page and pad it with zeroes in case it's not a full page.
|
|
# This is to emulate the behavior of mmap in Linux (and thus ChromeOS)
|
|
# environments.
|
|
#
|
|
# "POSIX specifies that the system shall always zero fill any
|
|
# partial page at the end of the object [...]".
|
|
#
|
|
# Reference: https://man7.org/linux/man-pages/man2/mmap.2.html
|
|
page = bytearray(data[offset : offset + PAGE_SIZE])
|
|
page.extend(itertools.repeat(0x00, PAGE_SIZE - len(page)))
|
|
|
|
# Calculate the hash of the page.
|
|
digest = hashlib.blake2b(page, digest_size=HASH_SIZE).digest()
|
|
out.extend(digest)
|
|
|
|
offset += PAGE_SIZE
|
|
|
|
return out
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# Check arguments.
|
|
if len(sys.argv) != 3:
|
|
error_str = "icuhash: wrong number of arguments\n\n"
|
|
help_str = "usage: icuhash <infilename> <outfilename>\n\n"
|
|
sys.exit(error_str + help_str)
|
|
|
|
# Extract arguments.
|
|
in_filename = sys.argv[1]
|
|
out_filename = sys.argv[2]
|
|
|
|
# Read the input file.
|
|
with open(in_filename, "rb") as in_file:
|
|
data = in_file.read()
|
|
# Calculate hashes for each page of the file.
|
|
out_data = hash_pages(data)
|
|
# Write the output file.
|
|
with open(out_filename, "wb") as out_file:
|
|
out_file.write(out_data)
|