def main() -> None: """Main function.""" # Set the folder for data (certificates, keys) data_dir = path.join(path.dirname(__file__), 'data') os.makedirs(data_dir, exist_ok=True) # load private key from data folder private_key_2048_ca = load_private_key(path.join(data_dir, "ca_privatekey_rsa2048.pem")) assert isinstance(private_key_2048_ca, RSAPrivateKey) # load associated public key public_key_2048_ca = load_public_key(path.join(data_dir, "ca_publickey_rsa2048.pem")) assert isinstance(public_key_2048_ca, RSAPublicKey) subject = issuer = generate_name_struct("first", "CZ") # generate CA certificate (self-signed certificate) ca_cert = generate_certificate(subject=subject, issuer=issuer, subject_public_key=public_key_2048_ca, issuer_private_key=private_key_2048_ca, serial_number=0x1, if_ca=True, duration=20 * 365, path_length=5) # Save certificates in two formats (pem and der) save_crypto_item(ca_cert, path.join(data_dir, "ca_cert_pem.crt")) save_crypto_item(ca_cert, path.join(data_dir, "ca_cert_der.crt"), encoding_type=Encoding.DER) print("The CA Certificate was created in der and pem format.") # Create first chain certificate signed by private key of the CA certificate subject_crt1 = generate_name_struct("second", "CZ") public_key_2048_subject = load_public_key(path.join(data_dir, "crt_publickey_rsa2048.pem")) assert isinstance(public_key_2048_subject, RSAPublicKey) crt1 = generate_certificate(subject=subject_crt1, issuer=issuer, subject_public_key=public_key_2048_subject, issuer_private_key=private_key_2048_ca, serial_number=0x3cc30000babadeda, if_ca=False, duration=20 * 365) # Save certificates in two formats (pem and der) save_crypto_item(crt1, path.join(data_dir, "crt_pem.crt")) save_crypto_item(crt1, path.join(data_dir, "crt_der.crt"), encoding_type=Encoding.DER) print("The first chain certificate (signed by CA certificate) was created in der and pem format.") # First chain certificate signed by private key of the CA certificate subject_crt2 = generate_name_struct("third", "CZ") private_key_2048_subject_1 = load_private_key(path.join(data_dir, "chain_privatekey_rsa2048.pem")) assert isinstance(private_key_2048_subject_1, RSAPrivateKey) public_key_2048_subject_1 = load_public_key(path.join(data_dir, "chain_publickey_rsa2048.pem")) assert isinstance(public_key_2048_subject_1, RSAPublicKey) crt1 = generate_certificate(subject=subject_crt2, issuer=issuer, subject_public_key=public_key_2048_subject_1, issuer_private_key=private_key_2048_ca, serial_number=0x2, if_ca=True, duration=20 * 365, path_length=3) # Save certificates in two formats (pem and der) save_crypto_item(crt1, path.join(data_dir, "chain_crt_pem.crt")) save_crypto_item(crt1, path.join(data_dir, "chain_crt_der.crt"), encoding_type=Encoding.DER) print("The first chain certificate (signed by CA certificate) was created in der and pem format.") # Create first chain certificate signed by private key of first certificate subject_crt3 = generate_name_struct("fourth", "CZ") issuer_crt3 = subject_crt2 public_key_2048_subject_2 = load_public_key(path.join(data_dir, "chain_crt2_publickey_rsa2048.pem")) assert isinstance(public_key_2048_subject_2, RSAPublicKey) crt1 = generate_certificate(subject=subject_crt3, issuer=issuer_crt3, subject_public_key=public_key_2048_subject_2, issuer_private_key=private_key_2048_subject_1, serial_number=0x3cc30000babadeda, if_ca=False, duration=20 * 365) # Save certificates in two formats (pem and der) save_crypto_item(crt1, path.join(data_dir, "chain_crt2_pem.crt")) save_crypto_item(crt1, path.join(data_dir, "chain_crt2_der.crt"), encoding_type=Encoding.DER) print("The second certificate in a chain was created in der and pem format.")
def generate(config: TextIO, output: BinaryIO, encoding: str, force: bool) -> None: """Generate certificate.""" logger.info("Generating Certificate...") logger.info("Loading configuration from yml file...") check_destination_dir(output.name, force) check_file_exists(output.name, force) config_data = load_configuration(config.name) cert_config = CertificateParametersConfig(config_data) priv_key = load_private_key(cert_config.issuer_private_key) pub_key = load_public_key(cert_config.subject_public_key) certificate = generate_certificate( subject=cert_config.subject_name, issuer=cert_config.issuer_name, subject_public_key=pub_key, issuer_private_key=priv_key, serial_number=cert_config.serial_number, duration=cert_config.duration, if_ca=cert_config.BasicConstrains_ca, path_length=cert_config.BasicConstrains_path_length, ) logger.info("Saving the generated certificate to the specified path...") encoding_type = Encoding.PEM if encoding.lower() == "pem" else Encoding.DER save_crypto_item(certificate, output.name, encoding_type=encoding_type) logger.info("Certificate generated successfully...") click.echo( f"The certificate file has been created: {os.path.abspath(output.name)}" )
def _get_signature(data: bytes, rotk_priv_path: str) -> bytes: """Creates a rsa signature over the data. :return: binary representing the signature """ priv_rotk = crypto.load_private_key(file_path=rotk_priv_path). \ private_bytes(encoding=crypto.Encoding.PEM, format=crypto.serialization.PrivateFormat.PKCS8, encryption_algorithm=crypto.serialization.NoEncryption()) return internal_backend.rsa_sign(priv_rotk, data)
def generate_master_boot_image(image_conf: click.File) -> None: """Generate MasterBootImage from json configuration file.""" config_data = json.load(image_conf) config = elftosb_helper.MasterBootImageConfig(config_data) app = load_binary(config.input_image_file) load_addr = config.output_image_exec_address trustzone = _get_trustzone(config) image_type = _get_master_boot_image_type(config) dual_boot_version = config.dual_boot_version firmware_version = config.firmware_version cert_block = None signature_provider = None if MasterBootImageType.is_signed(image_type): cert_config = elftosb_helper.CertificateBlockConfig(config_data) root_certs = [ load_binary(cert_file) for cert_file in cert_config.root_certs # type: ignore ] user_data = None if cert_config.isk_sign_data_path: user_data = load_binary(cert_config.isk_sign_data_path) isk_private_key = None if cert_config.isk_private_key_file: isk_private_key = load_private_key(cert_config.isk_private_key_file) assert isinstance(isk_private_key, EllipticCurvePrivateKeyWithSerialization) isk_cert = None if cert_config.isk_certificate: cert_data = load_binary(cert_config.isk_certificate) isk_cert = ECC.import_key(cert_data) ca_flag = not cert_config.use_isk cert_block = CertBlockV3( root_certs=root_certs, ca_flag=ca_flag, used_root_cert=cert_config.main_root_cert_id, constraints=cert_config.isk_constraint, isk_private_key=isk_private_key, isk_cert=isk_cert, # type: ignore user_data=user_data ) if cert_config.use_isk: signing_private_key_path = cert_config.isk_private_key_file else: signing_private_key_path = cert_config.main_root_private_key_file signature_provider = SignatureProvider.create(f'type=file;file_path={signing_private_key_path}') assert config.master_boot_output_file mbi = MasterBootImageN4Analog( app=app, load_addr=load_addr, image_type=image_type, trust_zone=trustzone, dual_boot_version=dual_boot_version, firmware_version=firmware_version, cert_block=cert_block, signature_provider=signature_provider ) mbi_data = mbi.export() write_file(mbi_data, config.master_boot_output_file, mode='wb')
def _extract_public_key(file_path: str, password: Optional[str]) -> crypto.RSAPublicKey: cert_candidate = crypto.load_certificate(file_path) if cert_candidate: return cert_candidate.public_key() private_candidate = crypto.load_private_key(file_path, password.encode() if password else None) if private_candidate: return private_candidate.public_key() public_candidate = crypto.load_public_key(file_path) if public_candidate: return public_candidate assert False, f"Unable to load secret file '{file_path}'."
def _get_signature(self) -> bytes: """Create signature for RSA. :return: signature in bytes format """ key = crypto.load_private_key(file_path=self.dck_priv) key_bytes = key.private_bytes( encoding=crypto.Encoding.PEM, format=crypto.serialization.PrivateFormat.PKCS8, encryption_algorithm=crypto.serialization.NoEncryption()) return internal_backend.rsa_sign(key_bytes, self._get_data_for_signature())
def _get_rotk(rotk_priv_key: str, _rot_pub_keys: List[str]) -> bytes: """Loads the vendor RoT private key. It corresponds to the (default) position zero RoT key in the rot_meta list of public keys. Derive public key from RoT private keys and converts it to the bytes. :return: binary representing the rotk public key """ priv_key_rotk = crypto.load_private_key(file_path=rotk_priv_key) pub_key_rotk = priv_key_rotk.public_key() assert isinstance(pub_key_rotk, crypto.RSAPublicKey) return rsa_key_to_bytes(key=pub_key_rotk, exp_length=4)
def _get_signature(data: bytes, rotk_priv_path: str) -> bytes: """Creates a cryptographic signature over the data. :return: binary representing the signature """ priv_rotk = crypto.load_private_key(file_path=rotk_priv_path) assert isinstance(priv_rotk, crypto.EllipticCurvePrivateKeyWithSerialization) signature = priv_rotk.sign(data, crypto.ec.ECDSA(crypto.hashes.SHA256())) r, s = utils_cryptography.decode_dss_signature(signature) public_numbers = crypto.EllipticCurvePublicNumbers( r, s, priv_rotk.curve) return ecc_public_numbers_to_bytes(public_numbers=public_numbers)
def signer(num: int) -> dict: """Route (API) that performing the signing. :param num: Index of the key to use (rot_id) :return: Signature wrapped in json, encoded in base64 """ private_key_file = os.path.join(THIS_DIR, f"k{num}_cert0_2048.pem") private_key = crypto.load_private_key(private_key_file) data_to_sign = base64.b64decode(request.args['data']) signature = private_key.sign(data=data_to_sign, padding=crypto.padding.PKCS1v15(), algorithm=crypto.hashes.SHA256()) data = base64.b64encode(signature) return jsonify({'signature': data.decode('utf-8')})
def __init__(self, file_path: str, password: str = '', encoding: str = 'PEM', hash_alg: str = None) -> None: """Initialize the plain file signature provider. :param file_path: Path to private file :param password: Password in case of encrypted private file, defaults to '' :param encoding: Private file encoding, defaults to 'PEM' :param hash_alg: Hash for the signature, defaults to 'sha256' """ self.file_path = file_path self.private_key = crypto.load_private_key(file_path) hash_size = self.private_key.key_size if isinstance(self.private_key, crypto.RSAPrivateKeyWithSerialization): hash_size = 256 # hash_size //= 8 hash_alg_name = hash_alg or f'sha{hash_size}' self.hash_alg = getattr(crypto.hashes, hash_alg_name.upper())()
def test_generate_rsa_key(tmpdir) -> None: """Test generate rsa key pair.""" cmd = f'genkey {os.path.join(tmpdir, "key_rsa.pem")}' runner = CliRunner() result = runner.invoke(main, cmd.split()) assert result.exit_code == 0 assert os.path.isfile(os.path.join(tmpdir, "key_rsa.pem")) assert os.path.isfile(os.path.join(tmpdir, "key_rsa.pub")) pub_key_from_file = load_public_key(os.path.join(tmpdir, "key_rsa.pub")) assert isinstance(pub_key_from_file, RSAPublicKey) assert pub_key_from_file.key_size == 2048 priv_key_from_file = load_private_key(os.path.join(tmpdir, "key_rsa.pem")) assert isinstance(priv_key_from_file, RSAPrivateKey) assert priv_key_from_file.key_size == 2048
def test_generate_ecc_key(tmpdir, protocol_version, curve_name) -> None: """Test generate ecc key pair.""" pem_path = os.path.join(tmpdir, f'{curve_name}_key_ecc.pem') pub_path = os.path.join(tmpdir, f'{curve_name}_key_ecc.pub') cmd = f'-p {protocol_version} genkey {pem_path}' runner = CliRunner() result = runner.invoke(main, cmd.split()) assert result.exit_code == 0 assert os.path.isfile(pem_path) assert os.path.isfile(pub_path) pub_key_from_file = load_public_key(pub_path) assert isinstance(pub_key_from_file, EllipticCurvePublicKey) assert pub_key_from_file.curve.name == curve_name priv_key_from_file = load_private_key(pem_path) assert isinstance(priv_key_from_file, EllipticCurvePrivateKey) assert pub_key_from_file.curve.name == curve_name
def signer(num: int) -> Response: """Route (API) that performing the signing. :param num: Index of the key to use (rot_id) :return: Signature wrapped in json, encoded in base64 """ private_key_file = os.path.join(THIS_DIR, f"k{num}_cert0_2048.pem") private_key = crypto.load_private_key(private_key_file) # in this example we assume RSA keys assert isinstance(private_key, crypto.RSAPrivateKey) data_to_sign = base64.b64decode(request.args["data"]) signature = private_key.sign( data=data_to_sign, padding=crypto.padding.PKCS1v15(), algorithm=crypto.hashes.SHA256(), ) data = base64.b64encode(signature) return jsonify({"signature": data.decode("utf-8")})
def _get_rotk(rotk_priv_key: str, rot_pub_keys: List[str]) -> bytes: """Creates RoTKey_Pub (2 element 16-bit array (little endian). CTRKtable index (RoT meta-data) of the public key used by the vendor to sign the DC. Curve identifier: - Secp256r1: 0x0001 - Secp384r1: 0x0002 - Secp521r1: 0x0003 :return: binary representation """ priv_loaded = crypto.load_private_key(rotk_priv_key) pub_from_priv = priv_loaded.public_key() pub_numbers = pub_from_priv.public_numbers() rot_pub_numbers = [ crypto.load_public_key(k).public_numbers() for k in rot_pub_keys ] key_index = rot_pub_numbers.index(pub_numbers) assert key_index is not None, "ROTK private key does not correspond to any of RotMeta public keys." curve_index = {256: 1, 384: 2, 521: 3}[pub_from_priv.key_size] return pack('<2H', key_index, curve_index)
def main(json_conf: click.File, cert_path: str) -> None: """Utility for certificate generation.""" logger.info("Generating Certificate...") logger.info("Loading configuration from json file...") json_content = json.load(json_conf) # type: ignore cert_config = CertificateParametersConfig(json_content) priv_key = load_private_key(cert_config.issuer_private_key) pub_key = load_public_key(cert_config.subject_public_key) certificate = generate_certificate( subject=cert_config.subject_name, issuer=cert_config.issuer_name, subject_public_key=pub_key, issuer_private_key=priv_key, serial_number=cert_config.serial_number, duration=cert_config.duration, if_ca=cert_config.BasicConstrains_ca, path_length=cert_config.BasicConstrains_path_length) logger.info("Saving the generated certificate to the specified path...") save_crypto_item(certificate, cert_path) logger.info("Certificate generated successfully...")
def test_is_key_priv(data_dir, file_name, password, expect_priv_key): key_path = path.join(data_dir, file_name) result = bool(load_private_key(key_path, password)) assert result is expect_priv_key