summaryrefslogtreecommitdiff
path: root/matweb/utils.py
diff options
context:
space:
mode:
authorjfriedli2020-04-26 09:50:14 -0700
committerjfriedli2020-04-26 09:50:14 -0700
commitc301e472bd7fd79d675c5df089db0b16fd1e2cfe (patch)
treec3332e0f974edc09881b5534c35becc5b9fffa3b /matweb/utils.py
parente1bac8b6a7fd857f38b7bcb678398c82baaa8fd5 (diff)
Resolve "Use a HMAC instead of a hash"
Diffstat (limited to '')
-rw-r--r--matweb/utils.py35
1 files changed, 25 insertions, 10 deletions
diff --git a/matweb/utils.py b/matweb/utils.py
index 8dfff45..ec9b99c 100644
--- a/matweb/utils.py
+++ b/matweb/utils.py
@@ -12,15 +12,21 @@ def get_allow_origin_header_value():
12 return os.environ.get('MAT2_ALLOW_ORIGIN_WHITELIST', '*').split(" ") 12 return os.environ.get('MAT2_ALLOW_ORIGIN_WHITELIST', '*').split(" ")
13 13
14 14
15def hash_file(filepath: str) -> str: 15def hash_file(filepath: str, secret: str) -> str:
16 sha256 = hashlib.sha256() 16 """
17 The goal of the hmac is to ONLY make the hashes unpredictable
18 :param filepath: Path of the file
19 :param secret: a server side generated secret
20 :return: digest, secret
21 """
22 mac = hmac.new(secret.encode(), None, hashlib.sha256)
17 with open(filepath, 'rb') as f: 23 with open(filepath, 'rb') as f:
18 while True: 24 while True:
19 data = f.read(65536) # read the file by chunk of 64k 25 data = f.read(65536) # read the file by chunk of 64k
20 if not data: 26 if not data:
21 break 27 break
22 sha256.update(data) 28 mac.update(data)
23 return sha256.hexdigest() 29 return mac.hexdigest()
24 30
25 31
26def check_upload_folder(upload_folder): 32def check_upload_folder(upload_folder):
@@ -28,11 +34,20 @@ def check_upload_folder(upload_folder):
28 os.mkdir(upload_folder) 34 os.mkdir(upload_folder)
29 35
30 36
31def return_file_created_response(output_filename, mime, key, meta, meta_after, download_link): 37def return_file_created_response(
38 output_filename: str,
39 mime: str,
40 key: str,
41 secret: str,
42 meta: list,
43 meta_after: list,
44 download_link: str
45) -> dict:
32 return { 46 return {
33 'output_filename': output_filename, 47 'output_filename': output_filename,
34 'mime': mime, 48 'mime': mime,
35 'key': key, 49 'key': key,
50 'secret': secret,
36 'meta': meta, 51 'meta': meta,
37 'meta_after': meta_after, 52 'meta_after': meta_after,
38 'download_link': download_link 53 'download_link': download_link
@@ -65,9 +80,9 @@ def cleanup(parser, filepath, upload_folder):
65 parser, _ = parser_factory.get_parser(parser.output_filename) 80 parser, _ = parser_factory.get_parser(parser.output_filename)
66 meta_after = parser.get_meta() 81 meta_after = parser.get_meta()
67 os.remove(filepath) 82 os.remove(filepath)
68 83 secret = os.urandom(32).hex()
69 key = hash_file(os.path.join(upload_folder, output_filename)) 84 key = hash_file(os.path.join(upload_folder, output_filename), secret)
70 return key, meta_after, output_filename 85 return key, secret, meta_after, output_filename
71 86
72 87
73def get_file_paths(filename, upload_folder): 88def get_file_paths(filename, upload_folder):
@@ -77,7 +92,7 @@ def get_file_paths(filename, upload_folder):
77 return complete_path, filepath 92 return complete_path, filepath
78 93
79 94
80def is_valid_api_download_file(filename, key, upload_folder): 95def is_valid_api_download_file(filename: str, key: str, secret: str, upload_folder: str) -> [str, str]:
81 if filename != secure_filename(filename): 96 if filename != secure_filename(filename):
82 abort(400, message='Insecure filename') 97 abort(400, message='Insecure filename')
83 98
@@ -86,6 +101,6 @@ def is_valid_api_download_file(filename, key, upload_folder):
86 if not os.path.exists(complete_path): 101 if not os.path.exists(complete_path):
87 abort(404, message='File not found') 102 abort(404, message='File not found')
88 103
89 if hmac.compare_digest(hash_file(complete_path), key) is False: 104 if hmac.compare_digest(hash_file(complete_path, secret), key) is False:
90 abort(400, message='The file hash does not match') 105 abort(400, message='The file hash does not match')
91 return complete_path, filepath 106 return complete_path, filepath