2 # Copyright (c) 2013 Intel Corporation. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 # pylint: disable=C0301
7 """The script is used to parse an XPK file.
10 1. Check the magic file header;
11 2. Verify the signature of the XPK file;
12 3. Extract the content of the XPK file to some folder.
14 The format of XPK file can be found at
15 https://github.com/crosswalk-project/crosswalk-website/wiki/Crosswalk-package-management
17 This file is used by make_apk.py.
26 EXIT_CODE_CRYPTO_NOT_FOUND = 1
27 EXIT_CODE_NO_XPK_FILE = 2
28 EXIT_CODE_XPK_FILE_NOT_EXIST = 3
29 EXIT_CODE_MAGIC_FAILED = 4
30 EXIT_CODE_VERIFICATION_FAILED = 5
31 EXIT_CODE_XPK_FILE_IO_ERROR = 6
33 XPK_MAGIC_HEAD = 'CrWk'
36 EXIT_CODE_CRYPTO_NOT_FOUND: 'Python module Crypto('\
37 'https://www.dlitz.net/software/pycrypto/) is needed',
38 EXIT_CODE_NO_XPK_FILE: 'Please specify XPK file by --file',
39 EXIT_CODE_XPK_FILE_NOT_EXIST: 'The XPK file you specified does not exist',
40 EXIT_CODE_MAGIC_FAILED: 'The file you specified is not in XPK format',
41 EXIT_CODE_VERIFICATION_FAILED:
42 'Signature verification failed for the XPK file',
43 EXIT_CODE_XPK_FILE_IO_ERROR: 'Error happened when reading the XPK file',
47 def HandleError(err_code):
48 print('Error: %s' % errorMessageMap[err_code])
53 from Crypto.PublicKey import RSA
54 from Crypto.Signature import PKCS1_v1_5
55 from Crypto.Hash import SHA
57 HandleError(EXIT_CODE_CRYPTO_NOT_FOUND)
60 def CheckMagic(input_file):
61 magic = input_file.read(4)
62 if magic != XPK_MAGIC_HEAD:
63 HandleError(EXIT_CODE_MAGIC_FAILED)
66 def GetPubkeySignature(input_file):
67 """Return (pubkey, signature) pair"""
68 pubkey_size, signature_size = struct.unpack('II', input_file.read(8))
69 return (input_file.read(pubkey_size), input_file.read(signature_size))
72 def ExtractXPKContent(input_file, zip_path):
73 zip_file = open(zip_path, 'wb')
74 zip_file.write(input_file.read())
78 def VerifySignature(pubkey, signature, zip_path):
79 zip_file = open(zip_path, 'rb')
80 key = RSA.importKey(pubkey)
81 content = SHA.new(zip_file.read())
83 verifier = PKCS1_v1_5.new(key)
84 if not verifier.verify(content, signature):
85 HandleError(EXIT_CODE_VERIFICATION_FAILED)
89 option_parser = optparse.OptionParser()
90 option_parser.add_option('--file', '-f', help='Path to the xpk file')
91 option_parser.add_option('--out', '-o', help='Path to extract the xpk to')
93 opts, _ = option_parser.parse_args()
96 HandleError(EXIT_CODE_NO_XPK_FILE)
98 app_name = os.path.splitext(os.path.basename(opts.file))[0]
103 if os.path.isfile(opts.file):
106 xpk_file = open(opts.file, 'rb')
108 pubkey, signature = GetPubkeySignature(xpk_file)
109 zip_path = '%s.zip' % app_name
110 ExtractXPKContent(xpk_file, zip_path)
111 VerifySignature(pubkey, signature, zip_path)
112 zipfile.ZipFile(zip_path).extractall(opts.out)
113 except SystemExit as ec:
116 HandleError(EXIT_CODE_XPK_FILE_IO_ERROR)
119 if zip_path and os.path.isfile(zip_path):
122 HandleError(EXIT_CODE_XPK_FILE_NOT_EXIST)
125 if __name__ == '__main__':