Skip to content

Commit 30a0efa

Browse files
authored
Merge pull request #2 from omaha-consulting/main
feat: add arg required_key_hashes to verify(...)
2 parents 6aa2436 + 2c06716 commit 30a0efa

File tree

2 files changed

+26
-6
lines changed

2 files changed

+26
-6
lines changed

src/crx3/verifier.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# -*- coding: utf-8 -*-
22

33
import base64
4+
import hashlib
45
import os.path
56
import os.path
67
import struct
@@ -53,10 +54,11 @@ def _verity_signature(crx_fp, file_size, public_key_bytes, signed_header_data, s
5354
return public_key.verify(signature, digest, padding.PKCS1v15(), Prehashed(sha256_algorithm))
5455

5556

56-
def verify(crx_file):
57+
def verify(crx_file, required_key_hashes=None):
5758
"""
5859
Verify the file as a valid Crx of CRX3 format.
5960
:param crx_file: crx file path.
61+
:param required_key_hashes: a list of hex strings of public key hashes.
6062
:return: (VerifierResult, CrxHeaderInfo or None)
6163
"""
6264
if not os.access(crx_file, os.F_OK | os.R_OK):
@@ -109,6 +111,7 @@ def return_error(verifier_error):
109111
return return_error(VerifierResult.ERROR_REQUIRED_PROOF_MISSING)
110112

111113
public_key_bytes = None
114+
required_key_set = set(required_key_hashes or [])
112115
for rsa_proof in rsa_proofs:
113116
# print(rsa_proof)
114117
if id_util.calc_crx_id_by_public_key(rsa_proof.public_key) == crx_id:
@@ -121,8 +124,10 @@ def return_error(verifier_error):
121124
except Exception as e:
122125
# print(e)
123126
return return_error(VerifierResult.ERROR_SIGNATURE_VERIFICATION_FAILED)
127+
public_key_hash = hashlib.sha256(rsa_proof.public_key).hexdigest()
128+
required_key_set.discard(public_key_hash)
124129

125-
if public_key_bytes is None:
130+
if public_key_bytes is None or required_key_set:
126131
return return_error(VerifierResult.ERROR_REQUIRED_PROOF_MISSING)
127132
# Convert public key bytes to base64 string.
128133
public_key_str = base64.b64encode(public_key_bytes).decode('utf-8')

tests/test_verifier.py

+19-4
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@
1111

1212
class VerifierTestCase(MyTest):
1313

14+
CRX_FILE = os.path.join(EXAMPLE_EXTENSION_DIR, EXAMPLE_EXTENSION_NAME + '.crx')
15+
PUBLIC_KEY_FILE = os.path.join(EXAMPLE_EXTENSION_DIR, EXAMPLE_EXTENSION_NAME + '-public-key.pem')
16+
PUBLIC_KEY_HASH = '99ec6d34093cd254def8c05e5fd5b25ebfef20f97d976eceba28b970da7d81b9'
17+
1418
def test_01_verify_ok_full(self):
15-
crx_file = os.path.join(EXAMPLE_EXTENSION_DIR, EXAMPLE_EXTENSION_NAME + '.crx')
16-
public_key_file = os.path.join(EXAMPLE_EXTENSION_DIR, EXAMPLE_EXTENSION_NAME + '-public-key.pem')
17-
verifier_result, header_info = verifier.verify(crx_file)
19+
verifier_result, header_info = verifier.verify(self.CRX_FILE)
1820
# print(verifier_result, header_info)
1921
self.assertEqual(verifier_result, verifier.VerifierResult.OK_FULL)
20-
public_key = read_public_key_str(public_key_file)
22+
public_key = read_public_key_str(self.PUBLIC_KEY_FILE)
2123
self.assertEqual(header_info, verifier.CrxHeaderInfo(EXAMPLE_EXTENSION_CRX_ID, public_key))
2224

2325
def test_02_verify_error_file_not_readable(self):
@@ -46,6 +48,19 @@ def test_04_verify_error_signature_verification_failed(self):
4648
self.assertEqual(verifier_result, verifier.VerifierResult.ERROR_SIGNATURE_VERIFICATION_FAILED)
4749
self.assertEqual(header_info, None)
4850

51+
def test_05_verify_ok_full_with_required_key_hashes(self):
52+
verifier_result, header_info = verifier.verify(self.CRX_FILE, [self.PUBLIC_KEY_HASH])
53+
# print(verifier_result, header_info)
54+
self.assertEqual(verifier_result, verifier.VerifierResult.OK_FULL)
55+
public_key = read_public_key_str(self.PUBLIC_KEY_FILE)
56+
self.assertEqual(header_info, verifier.CrxHeaderInfo(EXAMPLE_EXTENSION_CRX_ID, public_key))
57+
58+
def test_06_verify_fail_for_required_key_hashes(self):
59+
verifier_result, header_info = verifier.verify(self.CRX_FILE, ['0' * 64])
60+
# print(verifier_result, header_info)
61+
self.assertEqual(verifier_result, verifier.VerifierResult.ERROR_REQUIRED_PROOF_MISSING)
62+
self.assertEqual(header_info, None)
63+
4964

5065
if __name__ == '__main__':
5166
unittest.main()

0 commit comments

Comments
 (0)