def test_self_sign_certificate(self): # Warning: proof of concept code only! pub, priv = self.session.generate_keypair(KeyType.RSA, 1024) tbs = TbsCertificate({ 'version': 'v1', 'serial_number': 1, 'issuer': Name.build({ 'common_name': 'Test Certificate', }), 'subject': Name.build({ 'common_name': 'Test Certificate', }), 'signature': { 'algorithm': 'sha1_rsa', 'parameters': None, }, 'validity': { 'not_before': Time({ 'utc_time': datetime.datetime(2017, 1, 1, 0, 0), }), 'not_after': Time({ 'utc_time': datetime.datetime(2038, 12, 31, 23, 59), }), }, 'subject_public_key_info': { 'algorithm': { 'algorithm': 'rsa', 'parameters': None, }, 'public_key': RSAPublicKey.load(encode_rsa_public_key(pub)), } }) # Sign the TBS Certificate value = priv.sign(tbs.dump(), mechanism=Mechanism.SHA1_RSA_PKCS) cert = Certificate({ 'tbs_certificate': tbs, 'signature_algorithm': { 'algorithm': 'sha1_rsa', 'parameters': None, }, 'signature_value': value, }) # Pipe our certificate to OpenSSL to verify it with subprocess.Popen((OPENSSL, 'verify'), stdin=subprocess.PIPE, stdout=subprocess.DEVNULL) as proc: proc.stdin.write(pem.armor('CERTIFICATE', cert.dump())) proc.stdin.close() self.assertEqual(proc.wait(), 0)
def apply_sig(filename: str, detach_path: str): """ Attach the signature for the bundle of the same name at the detach_path """ bundle, filepath = get_bundle_exec(filename) detach_bundle = os.path.join(detach_path, os.path.basename(bundle)) bin_code_signers: Dict[str, CodeSigner] = {} for file_path in glob.iglob(os.path.join(detach_bundle, "**"), recursive=True): if os.path.isdir(file_path): continue bundle_relpath = os.path.relpath(file_path, detach_bundle) bundle_path = os.path.join(bundle, bundle_relpath) if os.path.basename(os.path.dirname(file_path)) == "MacOS": # Signature files are only in the MacOS dir if file_path.endswith("sign"): bin_name, ext = os.path.splitext(file_path) bundle_relpath = os.path.relpath(bin_name, detach_bundle) bundle_path = os.path.join(bundle, bundle_relpath) if bin_name not in bin_code_signers: bin_code_signers[bin_name] = CodeSigner( bundle_path, Certificate(), PrivateKeyInfo()) bcs = bin_code_signers[bin_name] # Figure out which index this sig is for idx = 0 macho = bcs.macho if hasattr(bcs.macho, "Fhdr"): if ext == ".sign": raise Exception( "Cannot attach single architecture signature to universal binary" ) arch_type = CPU_NAME_TO_TYPE[ext[1:-4]] for i, h in enumerate(bcs.macho.fh): if h.cputype == arch_type: idx = i macho = bcs.macho.arch[i] break # Create a CodeSignatureAttacher csa = CodeSignatureAttacher(bundle_path, idx, macho, file_path) # Add it to the CodeSigner bcs.code_signers.append(csa) continue # Non-signature files are just copied over os.makedirs(os.path.dirname(bundle_path), exist_ok=True) shutil.copyfile(file_path, bundle_path) # Apply the signature for all CodeSigners for _, cs in bin_code_signers.items(): cs.apply_signature()
def __init__(self) -> None: self.Cert: Certificate = Certificate() self.IPDesc = IPDesc() self.Time = Uint64() self.Signature = Bytes()