Zack Williams | 7af92fe | 2021-08-15 15:37:50 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | """ |
| 3 | cpisign.py |
| 4 | |
| 5 | Utility for signing CPI data |
| 6 | """ |
| 7 | |
| 8 | # SPDX-FileCopyrightText: © 2021 Open Networking Foundation <support@opennetworking.org> |
| 9 | # SPDX-License-Identifier: Apache-2.0 |
| 10 | |
Wei-Yu Chen | 27f14ef | 2021-09-23 12:23:13 +0800 | [diff] [blame^] | 11 | import os |
| 12 | import json |
Zack Williams | 7af92fe | 2021-08-15 15:37:50 -0700 | [diff] [blame] | 13 | import getpass |
Wei-Yu Chen | 27f14ef | 2021-09-23 12:23:13 +0800 | [diff] [blame^] | 14 | import argparse |
Zack Williams | 7af92fe | 2021-08-15 15:37:50 -0700 | [diff] [blame] | 15 | from jose import jws |
| 16 | |
| 17 | from cryptography.hazmat.primitives.serialization import pkcs12 |
| 18 | from cryptography.hazmat.primitives import serialization |
| 19 | |
Wei-Yu Chen | 27f14ef | 2021-09-23 12:23:13 +0800 | [diff] [blame^] | 20 | parser = argparse.ArgumentParser(description="CBSD CPI signature data generator") |
| 21 | parser.add_argument("-k", "--key", help="The file name of CPI key") |
| 22 | parser.add_argument( |
| 23 | "signFiles", |
| 24 | type=str, |
| 25 | nargs="+", |
| 26 | help="The file name of sigature data, can accept multiple files in a time.", |
| 27 | ) |
| 28 | args = parser.parse_args() |
Zack Williams | 7af92fe | 2021-08-15 15:37:50 -0700 | [diff] [blame] | 29 | |
Wei-Yu Chen | 27f14ef | 2021-09-23 12:23:13 +0800 | [diff] [blame^] | 30 | if __name__ == "__main__": |
| 31 | # get password |
| 32 | cpi_password = bytes(getpass.getpass(), "ascii") |
Zack Williams | 7af92fe | 2021-08-15 15:37:50 -0700 | [diff] [blame] | 33 | |
Wei-Yu Chen | 27f14ef | 2021-09-23 12:23:13 +0800 | [diff] [blame^] | 34 | with open(args.key, "rb") as key_file: |
| 35 | (pkey, cert, addl_cert) = pkcs12.load_key_and_certificates( |
| 36 | key_file.read(), cpi_password |
| 37 | ) |
Zack Williams | 7af92fe | 2021-08-15 15:37:50 -0700 | [diff] [blame] | 38 | |
Wei-Yu Chen | 27f14ef | 2021-09-23 12:23:13 +0800 | [diff] [blame^] | 39 | pkey_raw = pkey.private_bytes( |
| 40 | encoding=serialization.Encoding.PEM, |
| 41 | format=serialization.PrivateFormat.TraditionalOpenSSL, |
| 42 | encryption_algorithm=serialization.NoEncryption(), |
Zack Williams | 7af92fe | 2021-08-15 15:37:50 -0700 | [diff] [blame] | 43 | ) |
| 44 | |
Wei-Yu Chen | 27f14ef | 2021-09-23 12:23:13 +0800 | [diff] [blame^] | 45 | if not os.path.exists("output"): |
| 46 | os.makedirs("output") |
Zack Williams | 7af92fe | 2021-08-15 15:37:50 -0700 | [diff] [blame] | 47 | |
Wei-Yu Chen | 27f14ef | 2021-09-23 12:23:13 +0800 | [diff] [blame^] | 48 | for signFile in args.signFiles: |
| 49 | with open(signFile, "r") as inFile: |
| 50 | inFileJson = json.loads(inFile.read()) |
| 51 | # The output is 3 parameters concat with dot to a string |
| 52 | # 3 params are: protectedHeader, encodedCpiSignedData, digitalSignature |
| 53 | SIGNED = jws.sign(inFileJson, pkey_raw, algorithm="RS256") |
Zack Williams | 7af92fe | 2021-08-15 15:37:50 -0700 | [diff] [blame] | 54 | |
Wei-Yu Chen | 27f14ef | 2021-09-23 12:23:13 +0800 | [diff] [blame^] | 55 | print(f"* {inFileJson['cbsdSerialNumber']} data was signed") |
| 56 | with open(f"output/{signFile}.signed", "w") as out_file: |
| 57 | out_file.write(SIGNED) |