def __init__(self, cmdname, args): BaseAction.__init__(self, cmdname, args) crts = self._read_certificates(self._args.crtfile) self._hd = HexDump() local_vars = { "x509sak": x509sak, "derdec": lambda data: pyasn1.codec.der.decoder.decode(data)[0], "derenc": pyasn1.codec.der.encoder.encode, "berenc": pyasn1.codec.ber.encoder.encode, "crts": crts, "c": crts[0] if (len(crts) > 0) else None, "a": crts[0].asn1 if (len(crts) > 0) else None, "unpkcs1": PaddingTools.unpad_pkcs1, "decrsa": self._decrypt_selfsigned_rsa_signature, "md5": lambda payload: hashlib.md5(payload).digest(), "sha1": lambda payload: hashlib.sha1(payload).digest(), "sha256": lambda payload: hashlib.sha256(payload).digest(), "sha384": lambda payload: hashlib.sha384(payload).digest(), "sha512": lambda payload: hashlib.sha512(payload).digest(), "hd": self._hd.dump, "ap": self._asn1parse, "write_py": self._write_py, "safedec": ASN1Tools.safe_decode, } console = DebugConsole(local_vars = local_vars) for command in self._args.execute: print(">>> %s" % (command)) console.runcode(command) if len(self._args.execute) > 0: print() if not self._args.no_interact: console.interact()
def __init__(self, cmdname, args): BaseAction.__init__(self, cmdname, args) camgr = CAManager(self._args.capath) camgr.create_crl(self._args.crl_filename, validity_days=self._args.validity_days, signing_hash=self._args.hashfnc)
def __init__(self, cmdname, args): BaseAction.__init__(self, cmdname, args) self._pool = CertificatePool() self._pool.load_sources(self._args.crtsource) self._log.debug("Loaded a total of %d unique certificates in trust store.", self._pool.certificate_count) if self._args.format is not None: file_format = self._args.format else: file_format = os.path.splitext(self._args.outfile)[1].lstrip(".") self._active_substitutions = { name: getattr(self, "_substitute_" + name) for name in self.get_supported_substitutions() } self._get_cert_attributes = getattr(self, "_get_cert_attributes_" + self._args.color_scheme, None) if self._get_cert_attributes is None: raise LazyDeveloperException("Color scheme '%s' is unsupported. This is a bug." % (self._args.color_scheme)) # Load color palettes self._palette_traffic = AdvancedColorPalette(JSONTools.load_internal("x509sak.data", "palettes.json")["traffic"]) self._palette_flatui = AdvancedColorPalette(JSONTools.load_internal("x509sak.data", "palettes.json")["flatui"]) if file_format == "dot": with open(self._args.outfile, "w") as dotfile: self._write_dotfile(dotfile) elif file_format in [ "ps", "png", "pdf" ]: with tempfile.NamedTemporaryFile("w", prefix = "graph_", suffix = ".dot") as dotfile, open(self._args.outfile, "wb") as outfile: self._write_dotfile(dotfile) cmd = [ "dot", "-T%s" % (file_format), dotfile.name ] subprocess.check_call(cmd, stdout = outfile) else: raise UnknownFormatException("Unknown file format: \"%s\"" % (file_format))
def __init__(self, cmdname, args): BaseAction.__init__(self, cmdname, args) self._pool = CertificatePool() self._pool.load_sources(self._args.crtsource) self._log.debug( "Loaded a total of %d unique certificates in trust store.", self._pool.certificate_count) for cert in sorted(self._pool): if self._cert_matches(cert): cert.dump_pem()
def __init__(self, cmdname, args): BaseAction.__init__(self, cmdname, args) certs = X509Certificate.read_pemfile(self._args.crt_filename) if not certs[0].is_selfsigned: raise InvalidInputException("First certificate in chain (%s) is not self-signed." % (certs[0])) for (cert_id, (issuer, subject)) in enumerate(zip(certs, certs[1:]), 1): if not subject.signed_by(issuer): raise InvalidInputException("Certificate %d in file (%s) is not issuer for certificate %d (%s)." % (cert_id, issuer, cert_id + 1, subject)) self._log.debug("Chain of %d certificates to forge.", len(certs)) self._forge_cert(0, certs[0], 0, certs[0]) for (cert_subject_id, (issuer, subject)) in enumerate(zip(certs, certs[1:]), 1): self._forge_cert(cert_subject_id - 1, issuer, cert_subject_id, subject)
def __init__(self, cmdname, args): BaseAction.__init__(self, cmdname, args) if (not self._args.force) and os.path.exists(self._args.outfile): raise UnfulfilledPrerequisitesException( "File/directory %s already exists. Remove it first or use --force." % (self._args.outfile)) self._prime_db = PrimeDB(self._args.prime_db, generator_program=self._args.generator) q = self._prime_db.get(args.N_bits) if self._args.verbose >= 1: print("Chosen q = 0x%x" % (q)) bit_diff = args.L_bits - q.bit_length() while True: r = NumberTheory.randint_bits(bit_diff, two_msb_set=True) p = (r * q) + 1 if NumberTheory.is_probable_prime(p): break if self._args.verbose >= 1: print("Chosen p = 0x%x" % (p)) assert (q.bit_length() == args.N_bits) assert (p.bit_length() == args.L_bits) assert ((p - 1) % q == 0) # Non-verifiable method of generating g, see A.2.1 of FIPS 186-4, pg. 41 e = (p - 1) // q while True: h = random.randint(2, p - 2) g = pow(h, e, p) if g == 1: continue break if self._args.verbose >= 1: print("Chosen g = 0x%x" % (g)) dsa_parameters = DSAParameters.create(p=p, q=q, g=g) dsa_parameters.write_pemfile(self._args.outfile)
def __init__(self, cmdname, args): BaseAction.__init__(self, cmdname, args) # Plausibilize input parameters kwargs_checker = KwargsChecker(optional_arguments = set(self._DER_CLASSES.keys())) kwargs_checker.check(self._args.include_dertype, hint = "DER classes to be included") kwargs_checker.check(self._args.exclude_dertype, hint = "DER classes to be excluded") # Plausibilize output directory if os.path.exists(self._args.outdir) and (not self._args.force): raise Exception("Directory %s already exists. Remove it first or use --force." % (self._args.outdir)) try: os.makedirs(self._args.outdir) except FileExistsError: pass # Determine active DERHandler classes if len(self._args.include_dertype) == 0: active_der_types = set(self._DER_CLASSES.keys()) else: active_der_types = set(self._args.include_dertype) active_der_types -= set(self._args.exclude_dertype) self._active_der_types = [ self._DER_CLASSES[class_name] for class_name in active_der_types ] self._active_der_types.sort(key = lambda handler: (handler.precedence, handler.data_type)) self._stats = ActionScrapeStats(self._args) self._stats.set_active_der_types([ handler_class.data_type for handler_class in self._active_der_types ]) self._matches = Intervals() self._hashes = set() engine = ScrapeEngine(self._args.filename) if not self._args.no_pem: engine.search(self._find_pem, b"-----BEGIN ", min_length = 52, max_length = 32 * 1024) if (not self._args.no_der) and (len(self._active_der_types) > 0): self._log.debug("Looking for %d DER type(s): %s", len(self._active_der_types), ", ".join(handler.data_type for handler in self._active_der_types)) engine.search(self._find_der, bytes.fromhex("30"), min_length = 2, max_length = 32 * 1024) end_offset = engine.commence(start_offset = self._args.seek_offset, length = self._args.analysis_length, progress_callback = self._progress_callback) self._stats.finish(end_offset) self._stats.dump() if self._args.write_json is not None: JSONTools.write_to_file(self._stats.as_dict(), self._args.write_json)
def __init__(self, cmdname, args): BaseAction.__init__(self, cmdname, args) if args.encoding == "hex": with open(args.filename) as f: data = bytes.fromhex(f.read().replace("\n", "")) elif args.encoding == "bin": with open(args.filename, "rb") as f: data = f.read() else: raise NotImplementedError(args.encoding) if self._args.verbose >= 1: hd = HexDump() hd.dump(data) self._pp = pprint.PrettyPrinter(width=180) decoder = TLSMessageDecoder(side=args.side) decoder.add_hook("alert", self._msg_alert) decoder.add_hook("handshake", self._msg_handshake) decoder.put(data)
def __init__(self, cmdname, args): BaseAction.__init__(self, cmdname, args) structure = x509sak.estimate.JudgementStructure.create_judgement_structure( verbose=self._args.verbose >= 1) extended_enum_class = structure.create_extended_enum_class() if self._args.action == "list": codes = [enum_code.value for enum_code in extended_enum_class] for jc in sorted(codes): print(jc.name) elif self._args.action == "dump": structure.root.dump() elif self._args.action == "inherit": for (target_attribute, inherited_codes) in sorted( extended_enum_class.inheritance.items()): print("%s:" % (target_attribute)) for (base_name, codepoint) in sorted(inherited_codes.items()): print(" %-60s %s" % (base_name, codepoint.name)) print() else: raise NotImplementedError(self._args.action)
def __init__(self, cmdname, args): BaseAction.__init__(self, cmdname, args) if len(args.hash_alg) == 0: hash_fncs = self.get_default_hash_fncs() elif ("all" in args.hash_alg): hash_fncs = self.get_supported_hash_fncs() else: hash_fncs = set(args.hash_alg) with open(args.filename, "rb") as f: f.seek(args.seek_offset) self._data = f.read(args.analysis_length) if len(self._args.variable_hash_length) == 0: hash_lengths = self.get_default_variable_hash_lengths_bits() else: hash_lengths = self._args.variable_hash_length if any((value % 8) != 0 for value in hash_lengths): raise InvalidInputException("Not all hash lengths are evenly divisible by 8: %s" % (", ".join("%d" % (value) for value in hash_lengths))) if any((value < 8) for value in hash_lengths): raise InvalidInputException("Hash length must be at least 8 bit, not all are: %s" % (", ".join("%d" % (value) for value in hash_lengths))) valid_search_chars = set("abcdefABCDEF0123456789") if (self._args.search is not None) and (len(set(self._args.search) - valid_search_chars) > 0): raise InvalidInputException("Search pattern may only contain hexadecimal characters, but '%s' was given." % (self._args.search)) self._search = (self._args.search or "").lower() t0 = time.time() hash_fncs_by_name = { hashfnc.name: hashfnc for hashfnc in self.get_all_supported_hash_fncs() } for hash_fnc_name in sorted(hash_fncs): hash_fnc = hash_fncs_by_name[hash_fnc_name] if not hash_fnc.variable_output_length: self._run_hash_function(hash_fnc_name) else: for hash_len_bits in hash_lengths: self._run_hash_function(hash_fnc_name, output_length_bits = hash_len_bits) t1 = time.time() self._log.debug("Hash search took %.1f secs.", t1 - t0)
def __init__(self, cmdname, args): BaseAction.__init__(self, cmdname, args) if os.path.exists(self._args.crt_filename) and (not self._args.force): raise Exception( "File/directory %s already exists. Remove it first or use --force." % (self._args.crt_filename)) camgr = CAManager(self._args.capath) custom_x509_extensions = { custom_x509_extension.key: custom_x509_extension.value for custom_x509_extension in self._args.extension } camgr.sign_csr(self._args.csr_filename, self._args.crt_filename, extension_template=self._args.template, custom_x509_extensions=custom_x509_extensions, subject_dn=self._args.subject_dn, validity_days=self._args.validity_days, signing_hash=self._args.hashfnc, subject_alternative_dns_names=self._args.san_dns, subject_alternative_ip_addresses=self._args.san_ip)
def __init__(self, cmdname, args): BaseAction.__init__(self, cmdname, args) tls_version = TLSVersion.ProtocolTLSv1_2 self._conn = TLSClientConnection.tcp_connect( tls_version=tls_version, servername=args.servername, port=args.port) if self._args.starttls is None: pass elif self._args.starttls == "smtp": self._starttls_smtp(self._conn.transport) else: raise NotImplementedError(self._args.starttls) self._conn.decoder.add_hook("handshake", self._recv_handshake) self._conn.decoder.add_hook("record_layer", self._recv_record_layer) chh = ClientHelloHelper() client_hello = chh.create(server_name=args.servername) frame = ClientHelloPkt.pack(client_hello) self._conn.send_handshake(frame) self._conn.receive()
def __init__(self, cmdname, args): BaseAction.__init__(self, cmdname, args) sys.setrecursionlimit(10000) self._cg = CertGenerator.instantiate(self._args.tcname + ".ader") if self._args.list_parameters: for (name, values) in sorted(self._cg.parameters): print("%-30s %s" % (name, ", ".join(sorted(values)))) sys.exit(0) template_parameters = {} for parameter in self._args.parameter: (key, value) = parameter.split("=", maxsplit=1) if value == "*": template_parameters[key] = self._cg.get_choices(key) else: template_parameters[key] = [value] for (name, values) in self._cg.parameters: if name not in template_parameters: template_parameters[name] = values with contextlib.suppress(FileExistsError): os.makedirs(self._args.output_dir) template_parameters = list(template_parameters.items()) keys = [key for (key, values) in template_parameters] values = [values for (key, values) in template_parameters] self._tcs = [] for concrete_values in itertools.product(*values): concrete_values = dict(zip(keys, concrete_values)) try: self._render(concrete_values) except subprocess.CalledProcessError as e: print("Failed: %s (%s)" % (str(concrete_values), str(e))) self._tcs.sort() self._print_tcs()
def __init__(self, cmdname, args): BaseAction.__init__(self, cmdname, args) if self._args.parent_certificate is None: parent_ca_cert = None else: if self._args.in_format == "dercrt": # CA cert in DER form if host certificate is also in DER form crt = X509Certificate.read_derfile(self._args.parent_certificate) else: # CA cert in PEM form for all other cases crt = X509Certificate.read_pemfile(self._args.parent_certificate)[0] parent_ca_cert = CertificateAnalyzer.CertSource(source = self._args.parent_certificate, source_type = "pemcrt" if (self._args.in_format != "dercrt") else "dercrt", crts = [ crt ]) if self._args.in_format in [ "pemcrt", "dercrt", "host" ]: crt_sources = self._load_certificates() analysis_params = { "include_raw_data": self._args.include_raw_data, "fast_rsa": self._args.fast_rsa, "purposes": self._args.purpose, "entity_name": self._args.server_name, } if (len(analysis_params["purposes"]) == 0) and (self._args.in_format == "host") and (not self._args.no_automatic_host_check): analysis_params["purposes"].append("tls-server") if (analysis_params["entity_name"] is None) and (self._args.in_format == "host") and (not self._args.no_automatic_host_check): hostname = crt_sources[0].source.split(":")[0] analysis_params["entity_name"] = hostname crt_analyzer = CertificateAnalyzer(**analysis_params) analysis = crt_analyzer.analyze(crt_sources, parent_ca_cert) elif self._args.in_format == "json": analysis = self._read_json() else: raise NotImplementedError(self._args.in_format) output = self._args.output or "-" with FileWriter(output, "w") as f: self._show_analysis(f, analysis)
def __init__(self, cmdname, args): BaseAction.__init__(self, cmdname, args) if (not self._args.force) and os.path.exists(self._args.outfile): raise UnfulfilledPrerequisitesException( "File/directory %s already exists. Remove it first or use --force." % (self._args.outfile)) if not self._args.gcd_n_phi_n: self._primetype = "2msb" self._p_bitlen = self._args.bitlen // 2 self._q_bitlen = self._args.bitlen - self._p_bitlen else: self._primetype = "3msb" self._p_bitlen = self._args.bitlen // 3 self._q_bitlen = self._args.bitlen - (2 * self._p_bitlen) - 1 if (self._args.close_q) and (self._p_bitlen != self._q_bitlen): raise UnfulfilledPrerequisitesException( "Generating a close-q keypair with a %d modulus does't work, because p would have to be %d bit and q %d bit. Choose an even modulus bitlength." % (self._args.bitlen, self._p_bitlen, self._q_bitlen)) if self._args.q_stepping < 1: raise InvalidInputException( "q-stepping value must be greater or equal to 1, was %d." % (self._args.q_stepping)) self._log.debug("Selecting %s primes with p = %d bit and q = %d bit.", self._primetype, self._p_bitlen, self._q_bitlen) self._prime_db = PrimeDB(self._args.prime_db, generator_program=self._args.generator) p = None q = None while True: if p is None: p = self._prime_db.get(bitlen=self._p_bitlen, primetype=self._primetype) q_generator = self._select_q(p) if q is None: q = next(q_generator) if self._args.gcd_n_phi_n: # q = (2 * r * p) + 1 r = q q = 2 * r * p + 1 if not NumberTheory.is_probable_prime(q): q = None continue # Always make p the smaller factor if p > q: (p, q) = (q, p) n = p * q if self._args.public_exponent == -1: e = random.randint(2, n - 1) else: e = self._args.public_exponent if self._args.carmichael_totient: totient = NumberTheory.lcm(p - 1, q - 1) else: totient = (p - 1) * (q - 1) gcd = NumberTheory.gcd(totient, e) if self._args.accept_unusable_key or (gcd == 1): break else: # Pair (phi(n), e) wasn't acceptable. self._log.debug("gcd(totient, e) was %d, retrying.", gcd) if self._args.public_exponent != -1: # Public exponent e is fixed, need to choose another q. if p.bit_length() == q.bit_length(): # Can re-use q as next p (p, q) = (q, None) q_generator = self._select_q(p) else: # When they differ in length, need to re-choose both values (p, q) = (None, None) rsa_keypair = RSAPrivateKey.create( p=p, q=q, e=e, swap_e_d=self._args.switch_e_d, valid_only=not self._args.accept_unusable_key, carmichael_totient=self._args.carmichael_totient) rsa_keypair.write_pemfile(self._args.outfile) if self._args.verbose >= 1: diff = q - p print("Generated %d bit RSA key:" % (rsa_keypair.n.bit_length())) print("p = 0x%x" % (rsa_keypair.p)) if not self._args.gcd_n_phi_n: print("q = 0x%x" % (rsa_keypair.q)) else: print("q = 2 * r * p + 1 = 0x%x" % (rsa_keypair.q)) print("r = 0x%x" % (r)) print("phi(n) = 0x%x" % (rsa_keypair.phi_n)) print("lambda(n) = 0x%x" % (rsa_keypair.lambda_n)) print("phi(n) / lambda(n) = gcd(p - 1, q - 1) = %d" % (rsa_keypair.phi_n // rsa_keypair.lambda_n)) gcd_n_phin = NumberTheory.gcd(rsa_keypair.n, rsa_keypair.phi_n) if gcd_n_phin == rsa_keypair.p: print("gcd(n, phi(n)) = p") else: print("gcd(n, phi(n)) = 0x%x" % (gcd_n_phin)) if self._args.close_q: print("q - p = %d (%d bit)" % (diff, diff.bit_length())) print("n = 0x%x" % (rsa_keypair.n)) print("d = 0x%x" % (rsa_keypair.d)) print("e = 0x%x" % (rsa_keypair.e))
def __init__(self, cmdname, args): BaseAction.__init__(self, cmdname, args) if self._args.public_key: key = PublicKey.read_pemfile(self._args.key_filename)[0] if key.pk_alg.value.cryptosystem == Cryptosystems.RSA: print("# %d bit RSA public key (ID %s)" % (key.n.bit_length(), key.keyid().hex())) print("n = 0x%x" % (key.n)) print("e = 0x%x" % (key.e)) elif key.pk_alg.value.cryptosystem == Cryptosystems.ECC_ECDSA: print("# ECC public key on %s (key ID %s)" % (key.curve.name, key.keyid().hex())) print("curve_name = \"%s\"" % (key.curve.name)) print("(x, y) = (0x%x, 0x%x)" % (key.x, key.y)) elif key.pk_alg.value.cryptosystem == Cryptosystems.ECC_EdDSA: print( "# ECC public key on Twisted Edwards curve %s %s prehashing (key ID %s)" % (key.curve.name, "with" if key.prehash else "without", key.keyid().hex())) print("curve_name = \"%s\"" % (key.curve.name)) print("prehash = %s" % (key.prehash)) print("(x, y) = (0x%x, 0x%x)" % (key.x, key.y)) else: raise NotImplementedError(key.pk_alg.value.cryptosystem) else: if self._args.key_type == "rsa": key = RSAPrivateKey.read_pemfile(self._args.key_filename)[0] print("# %d bit RSA private key (ID %s)" % (key.n.bit_length(), key.pubkey.keyid().hex())) print("p = 0x%x" % (key.p)) print("q = 0x%x" % (key.q)) print("n = p * q") print("e = 0x%x" % (key.e)) print("d = 0x%x" % (key.d)) elif self._args.key_type == "ecc": key = ECPrivateKey.read_pemfile(self._args.key_filename)[0] print("# ECC private key on %s (key ID %s)" % (key.curve.name, key.pubkey.keyid().hex())) print("curve_name = \"%s\"" % (key.curve.name)) print("d = 0x%x" % (key.d)) print("(x, y) = (0x%x, 0x%x)" % (key.x, key.y)) elif self._args.key_type == "eddsa": key = EDPrivateKey.read_pemfile(self._args.key_filename)[0] pubkey = key.pubkey print( "# ECC private key on Twisted Edwards curve %s %s prehashing (key ID %s)" % (key.curve.name, "with" if key.prehash else "without", pubkey.keyid().hex())) print("curve_name = \"%s\"" % (key.curve.name)) print("prehash = %s" % (key.prehash)) print("priv = bytes.fromhex(\"%s\")" % (key.priv.hex())) print("hashfnc = hashlib.new(\"%s\")" % (key.curve.expand_hashfnc)) print( "(expand_bitwise_and, expand_bitwise_or) = (0x%x, 0x%x)" % (key.curve.expand_bitwise_and, key.curve.expand_bitwise_or)) print("a = 0x%x" % (key.scalar)) print("(x, y) = (0x%x, 0x%x)" % (pubkey.x, pubkey.y)) else: raise NotImplementedError(self._args.key_type)
def __init__(self, cmdname, args): BaseAction.__init__(self, cmdname, args) if (self._args.private_key is not None) and (self._args.outform != "pkcs12"): raise InvalidUsageException( "A private key will only be exported with a PKCS#12 output file." ) if self._args.outform != "pkcs12": if self._args.pkcs12_legacy_crypto: raise InvalidUsageException( "Specifying PKCS#12 legacy crypto while not using PKCS#12 output format has no effect." ) if self._args.pkcs12_no_passphrase: raise InvalidUsageException( "Specifying no PKCS#12 passphrase while not using PKCS#12 output format has no effect." ) if self._args.pkcs12_passphrase_file is not None: raise InvalidUsageException( "Specifying a PKCS#12 passphrase while not using PKCS#12 output format has no effect." ) else: if (self._args.pkcs12_legacy_crypto or self._args.pkcs12_no_passphrase or self._args.pkcs12_passphrase_file is not None) and (self._args.private_key is None): raise InvalidUsageException( "Specifying any PKCS#12 passphrase/crypto options when not including a private key makes no sense." ) self._pool = CertificatePool() self._load_truststore() if self._args.inform == "pem": certs = X509Certificate.read_pemfile(self._args.crtfile) if not self._args.dont_trust_crtfile: self._pool.add_certificates(certs) cert = certs[0] elif self._args.inform == "der": cert = X509Certificate.read_derfile(self._args.crtfile) else: raise NotImplementedError("inform", self._args.inform) chain = self._pool.find_chain(cert) if (chain.root is None) and (not self._args.allow_partial_chain): raise InvalidUsageException( "Could not build full chain for certificate %s and partial chain matches are disallowed." % (self._args.crtfile)) if self._args.outform == "rootonly": if chain.root is None: print("Root certificate output requested, but none found.", file=sys.stderr) sys.exit(1) certs = [chain.root] elif self._args.outform == "intermediates": certs = list(chain.chain) elif self._args.outform in ["fullchain", "multifile", "pkcs12"]: certs = list(chain.full_chain) elif self._args.outform == "all-except-root": certs = list(chain.full_chain) if chain.root is not None: certs = certs[:-1] else: raise NotImplementedError("outform", self._args.outform) if not self._args.order_leaf_to_root: certs = certs[::-1] for (cid, cert) in enumerate(certs): self._log.debug("Cert %d: %s", cid, cert) if self._args.outform == "multifile": for (cid, cert) in enumerate(certs): filename = self._args.outfile % (cid) with open(filename, "w") as f: print(cert.to_pem_data(), file=f) elif self._args.outform == "pkcs12": if self._args.private_key is not None: if self._args.pkcs12_no_passphrase: passphrase = None else: if self._args.pkcs12_passphrase_file is not None: with open(self._args.pkcs12_passphrase_file) as f: passphrase = f.readline() else: passphrase = PassphraseGenerator.non_ambiguous( ).gen_passphrase(80) print("Passphrase: %s" % (passphrase), file=sys.stderr) else: passphrase = None private_key_storage = PrivateKeyStorage( PrivateKeyStorageForm.PEM_FILE, filename=self._args.private_key) if (self._args.private_key is not None) else None pkcs12 = OpenSSLTools.create_pkcs12( certificates=certs, private_key_storage=private_key_storage, modern_crypto=not self._args.pkcs12_legacy_crypto, passphrase=passphrase) if self._args.outfile is None: # Write to stdout sys.stdout.buffer.write(pkcs12) else: # Write to file, binary with open(self._args.outfile, "wb") as f: f.write(pkcs12) else: if self._args.outfile is not None: with open(self._args.outfile, "w") as f: self._print_certs(f, certs) else: self._print_certs(sys.stdout, certs)
def __init__(self, cmdname, args): BaseAction.__init__(self, cmdname, args) if self._args.force: try: os.unlink(self._args.capath) except (IsADirectoryError, FileNotFoundError): pass try: shutil.rmtree(self._args.capath) except FileNotFoundError: pass else: if os.path.exists(self._args.capath): raise UnfulfilledPrerequisitesException( "File/directory %s already exists. Remove it first or use --force." % (self._args.capath)) os.makedirs(self._args.capath) os.chmod(self._args.capath, 0o700) camgr = CAManager(self._args.capath) custom_x509_extensions = { custom_x509_extension.key: custom_x509_extension.value for custom_x509_extension in self._args.extension } if (self._args.gen_keyspec is not None) or ((self._args.gen_keyspec is None) and (self._args.hardware_key is None)): # We need to generate a key. if self._args.gen_keyspec is not None: keyspec = self._args.gen_keyspec else: # Cannot default to this in argparse because it's part of a # mutually exclusive group with hardware_key keyspec = KeySpecification.from_cmdline_str("ecc:secp384r1") private_key_storage = PrivateKeyStorage( PrivateKeyStorageForm.PEM_FILE, filename="CA.key", search_path=camgr.capath) OpenSSLTools.create_private_key(private_key_storage, keyspec=keyspec) else: # The key is stored in hardware. private_key_storage = PrivateKeyStorage( PrivateKeyStorageForm.HARDWARE_TOKEN, pkcs11uri=self._args.hardware_key, so_search_path=self._args.pkcs11_so_search, module_so=self._args.pkcs11_module) signing_hash = self._args.hashfnc if private_key_storage.is_file_based: privkey = private_key_storage.load_private_key() if isinstance(privkey, EDPrivateKey): # We cannot specify a hash function for EdDSA because this # causes OpenSSL to fail with "elliptic curve # routines:pkey_ecd_ctrl:invalid digest type" -- for EdDSA, the # hash algorithms are implied signing_hash = None camgr.create_ca_structure( private_key_storage=private_key_storage, unique_subject=not self._args.allow_duplicate_subjects) if self._args.parent_ca is None: # Self-signed root CA camgr.create_selfsigned_ca_cert( subject_dn=self._args.subject_dn, validity_days=self._args.validity_days, custom_x509_extensions=custom_x509_extensions, signing_hash=signing_hash, serial=self._args.serial) # Create certificate chain file that only consists of our # self-signed certificate shutil.copy(self._args.capath + "/CA.crt", self._args.capath + "/chain.crt") else: # Intermediate CA if self._args.serial is not None: raise InvalidUsageException( "Can only specify certificate serial number when creating self-signed root CA certificate." ) with tempfile.NamedTemporaryFile("w", prefix="ca_", suffix=".csr") as csr: camgr.create_ca_csr(csr_filename=csr.name, subject_dn=self._args.subject_dn) parent_ca = CAManager(self._args.parent_ca) parent_ca.sign_csr( csr.name, camgr.root_crt_filename, subject_dn=self._args.subject_dn, validity_days=self._args.validity_days, custom_x509_extensions=custom_x509_extensions, extension_template="ca", signing_hash=signing_hash) # Create a certificate chain by appending the parent chain to our certificate if os.path.isfile(self._args.parent_ca + "/chain.crt"): with open(self._args.parent_ca + "/chain.crt") as parent_chainfile: parent_chain = parent_chainfile.read() with open(self._args.capath + "/CA.crt") as new_certificate_file: new_certificate = new_certificate_file.read() with open(self._args.capath + "/chain.crt", "w") as intermediate_chainfile: intermediate_chainfile.write(parent_chain) intermediate_chainfile.write(new_certificate)
def __init__(self, cmdname, args): BaseAction.__init__(self, cmdname, args) camgr = CAManager(self._args.capath) camgr.revoke_crt(self._args.crt_filename)