def create_crlsets(): """ Create test CRLs """ print("creating crl set") revoked = crypto.Revoked() chainrev = crypto.Revoked() future_revoked = crypto.Revoked() revoked.set_rev_date(dates['OK_NOW'].encode('utf-8')) chainrev.set_rev_date(dates['OK_NOW'].encode('utf-8')) future_revoked.set_rev_date(dates['FUTURE'].encode('utf-8')) # the get_serial_number method results in a hex str like '0x17' # but set_serial needs a hex str like '17' ser = hex(end_certs['revoked'][0].get_serial_number())[2:] revoked.set_serial(ser.encode('utf-8')) ser = hex(end_certs['west_chain_revoked'][0].get_serial_number())[2:] chainrev.set_serial(ser.encode('utf-8')) ser = hex(end_certs['revoked'][0].get_serial_number())[2:] future_revoked.set_serial(ser.encode('utf-8')) needupdate = crypto.CRL() needupdate.add_revoked(revoked) needupdate.add_revoked(chainrev) with open(dirbase + "crls/needupdate.crl", "wb") as f: f.write(needupdate.export(ca_certs['mainca'][0], ca_certs['mainca'][1], type=crypto.FILETYPE_ASN1, days=0, digest='sha256'.encode('utf-8'))) print("sleeping for needupdate/valid crl time difference") time.sleep(5) validcrl = crypto.CRL() validcrl.add_revoked(revoked) validcrl.add_revoked(chainrev) with open(dirbase + "crls/cacrlvalid.crl", "wb") as f: f.write(validcrl.export(ca_certs['mainca'][0], ca_certs['mainca'][1], type=crypto.FILETYPE_ASN1, days=15, digest='sha256'.encode('utf-8'))) othercrl = crypto.CRL() othercrl.add_revoked(revoked) othercrl.add_revoked(chainrev) with open(dirbase + "crls/othercacrl.crl", "wb") as f: f.write(othercrl.export(ca_certs['otherca'][0], ca_certs['otherca'][1], type=crypto.FILETYPE_ASN1, days=15, digest='sha256'.encode('utf-8'))) notyet = crypto.CRL() notyet.add_revoked(future_revoked) with open(dirbase + "crls/futurerevoke.crl", "wb") as f: f.write(notyet.export(ca_certs['mainca'][0], ca_certs['mainca'][1], type=crypto.FILETYPE_ASN1, days=15, digest='sha256'.encode('utf-8')))
def create_leading_zero_crl(): """ Create our special crl with a signature that starts out with '00:' This signs a CRL and checks for a '00' beginning. Each try increments the days parameter to result in a different signature """ zerosig = crypto.CRL() signcert, signkey = ca_certs['mainca'] days = 1 print("creating a CRL with a leading zero byte signature..") while True: good = False nl = '' crl = zerosig.export(signcert, signkey, type=crypto.FILETYPE_TEXT, days=days, digest='sha256') der = zerosig.export(signcert, signkey, type=crypto.FILETYPE_ASN1, days=days, digest='sha256') for index, line in enumerate(crl.splitlines()): if "Signature Algorithm" in line and index >= 5: nl = crl.splitlines()[index + 1].strip() if nl.startswith('00'): good = True break if good: print(nl) print("found after %d signatures!"% days) with open(dirbase + "crls/crl-leading-zero-byte.crl", "wb") as f: f.write(der) break days += 1
def get_crl(ca, **kwargs): """Function to generate a Certificate Revocation List (CRL). All keyword arguments are passed as-is to :py:func:`OpenSSL.crypto.CRL.export`. Please see the documentation of that function for details. Parameters ---------- ca : :py:class:`~django_ca.models.CertificateAuthority` type : int One of OpenSSL.crypto.FILETYPE_*. expires : int, optional The time in seconds until a new CRL will be generated. The default is 86400 (one day). digest : hash Unlike the current pyOpenSSL default (md5), sha512 is the default. Returns ------- Returns the CRL as bytes (since this is what pyOpenSSL returns). """ kwargs.setdefault('digest', b'sha512') kwargs['days'] = Decimal(kwargs.pop('expires', 86400)) / 86400 crl = crypto.CRL() for cert in Certificate.objects.filter( ca=ca, expires__gt=timezone.now()).revoked(): crl.add_revoked(cert.get_revocation()) return crl.export(ca.x509, ca.key, **kwargs)
def main(): pkey = crypto.PKey() pkey.generate_key(crypto.TYPE_RSA, 2048) ca = crypto.X509() ca.set_version(2) ca.set_serial_number(1) ca.get_subject().CN = 'snakeoil' ca.set_notBefore(b'19700101000000Z') ca.set_notAfter(b'20991231235959Z') ca.set_issuer(ca.get_subject()) ca.set_pubkey(pkey) ca.sign(pkey, 'sha256') revoked = crypto.Revoked() revoked.set_serial(b'2a') revoked.set_rev_date(b'19700101000000Z') revoked.set_reason(None) crl = crypto.CRL() crl.set_lastUpdate(b'19700101000000Z') crl.set_nextUpdate(b'20990101000000Z') crl.add_revoked(revoked) crl.sign(issuer_cert=ca, issuer_key=pkey, digest=b'sha256') with open(osp.join(osp.dirname(__file__), 'minimal.crl'), 'wb') as f_crl: f_crl.write(crypto.dump_crl(crypto.FILETYPE_ASN1, crl))
def save_revocation_list(cls): """ Saves the certificate revocation list used by ser2sock. """ ser2sock_config_path = Setting.get_by_name( 'ser2sock_config_path').value if not ser2sock_config_path: raise ValueError('ser2sock_config_path is not set.') path = os.path.join(ser2sock_config_path, 'ser2sock.crl') ca_cert = cls.query.filter_by(type=CA).first() with open(path, 'w') as crl_file: crl = crypto.CRL() for cert in cls.query.all(): if cert.type != CA: if cert.status == REVOKED: revoked = crypto.Revoked() revoked.set_reason(None) # NOTE: crypto.Revoked() expects YYYY instead of YY as needed by the cert index above. revoked.set_rev_date( time.strftime('%Y%m%d%H%M%SZ', cert.revoked_on.utctimetuple())) revoked.set_serial(str(cert.serial_number)) crl.add_revoked(revoked) crl_data = crl.export(ca_cert.certificate_obj, ca_cert.key_obj) crl_file.write(crl_data)
def generate_crl(): # Getting a list of certificates result = Certificate.query.with_entities(Certificate.serial).all() crl = crypto.CRL() # Getting the CA information key = Key.query.filter_by(ca=1).first() private_key = crypto.load_privatekey(crypto.FILETYPE_PEM, key.private, passphrase="testtest") public_key = crypto.load_certificate(crypto.FILETYPE_PEM, key.public) for cert in result: now = datetime.datetime.now().strftime("%Y%m%d%H%M%SZ").encode("ascii") revoked = crypto.Revoked() revoked.set_rev_date(now) revoked.set_reason(revoked.all_reasons()[1]) revoked.set_serial(str(cert.serial[:-1])) crl.add_revoked(revoked) with open("test.crl", "wb") as f: f.write( crl.export(public_key, private_key, crypto.FILETYPE_PEM, days=30, digest=b'sha256')) return ""
def generate_crl(self): """ Generates Certificate Revocation List :return: CRL in PEM format """ lookup_results = self._resource_manager_tools.object_lookup( self.AUTHORITY_NAME, 'crl', {}, []) crl = crypto.CRL() now = dt.datetime.utcnow() for entry in lookup_results: cert_expiration_date = dt.datetime.strptime( entry['CERT_VALID_UNTIL'], '%Y%m%d%H%M%SZ') if cert_expiration_date > now: revoked_entry = crypto.Revoked() revoked_entry.set_serial(hex(entry['CERT_SERIAL_NUMBER'])[2:]) revoked_entry.set_reason(str(entry['REVOKE_REASON'])) revoked_entry.set_rev_date(str(entry['REVOKE_DATE'])) crl.add_revoked(revoked_entry) else: self._resource_manager_tools.object_delete( self.AUTHORITY_NAME, 'crl', {'CERT_SERIAL_NUMBER': entry['CERT_SERIAL_NUMBER']}) return crl.export(self._ma_cert, self._ma_cert_key, days=self.CRL_VALIDITY_PERIOD)
def generate_ca(self, expiry_time_secs: int = 31536000) -> None: """ Generate a CA certificate """ if not os.path.exists(self.cakeypath): print("Cannot find CA locally so generating one") if not os.path.exists(os.path.dirname(self.cakeypath)): print("the directory for storing certificates doesn't exist.") print("Creating one at " + os.path.dirname(self.cakeypath)) os.makedirs(os.path.dirname(self.cakeypath)) ca_key = crypto.PKey() ca_key.generate_key(crypto.TYPE_RSA, 2048) cert = crypto.X509() cert.get_subject().CN = "CA" cert.set_serial_number(0) cert.set_version(2) cert.gmtime_adj_notBefore(0) cert.gmtime_adj_notAfter(expiry_time_secs) cert.set_issuer(cert.get_subject()) cert.add_extensions([ crypto.X509Extension(b'basicConstraints', False, b'CA:TRUE'), crypto.X509Extension(b'keyUsage', False, b'keyCertSign, cRLSign') ]) cert.set_pubkey(ca_key) cert.sign(ca_key, "sha256") f = open(self.cakeypath, "wb") f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, ca_key)) f.close() f = open(self.capempath, "wb") f.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)) f.close() # append empty crl crl = crypto.CRL() crl.sign(cert, ca_key, b"sha256") with open(MainConfig.CRLFile, 'wb') as f: f.write(crl.export(cert=cert, key=ca_key, digest=b"sha256")) delete = 0 with open(self.capempath, "r") as f: lines = f.readlines() with open(self.capempath, "w") as f: for line in lines: if delete: continue elif line.strip("\n") != "-----BEGIN X509 CRL-----": f.write(line) else: delete = 1 with open(self.capempath, "ab") as f: f.write(crl.export(cert=cert, key=ca_key, digest=b"sha256")) else: print("CA found locally, not generating a new one")
def generate_full_crl(caid): ''' This route is used to generate the full CRL. The procedure works like the following: 1. App connects to database 2. App queries a list of certificates bound to this CA with status "Revoked" (2) 3. App generates CRL and puts this CRL into database ''' # Import section from OpenSSL import crypto, SSL # Getting data data = request.get_json() # Getting CA ca = CertificateAuthority.query.get(caid) if not ca: abort(config.http_notfound, {"message": config.error_ca_notfound}) # Getting the CA Key, that will be used to sign certificates key = ca.keys[0] if not key: abort(config.http_notfound, {"message": config.error_pkey_notfound}) try: private_key = crypto.load_privatekey(crypto.FILETYPE_PEM, key.private, passphrase=str(data['pass'])) public_key = crypto.load_certificate(crypto.FILETYPE_PEM, key.public) except Exception as e: abort(config.http_notauthorized, {"message": config.error_pass_incorrect}) # Getting a list of certificates with Revoked status result = Certificate.query.with_entities( Certificate.serial, Certificate.code_revoke).filter( (Certificate.status == config.STATUS_REVOKED) | (Certificate.status == config.STATUS_PAUSED)).all() # Starting the generate CRL crl = crypto.CRL() for cert in result: revoked = crypto.Revoked() revoked.set_rev_date( datetime.datetime.now().strftime("%Y%m%d%H%M%SZ").encode("ascii")) revoked.set_reason(revoked.all_reasons()[cert.code_revoke]) revoked.set_serial(str(cert.serial[:-1])) crl.add_revoked(revoked) # Creating new CRL crlObject = CRL() crlObject.created = datetime.datetime.utcnow() crlObject.crl = crl.export(public_key,private_key,crypto.FILETYPE_ASN1,\ days=config.CRL_VALID_DAYS,digest=b'sha256') ca.crls.append(crlObject) db.session.add(crlObject) db.session.commit() return jsonify(message=config.msg_crl_generated), config.http_created
def _load_crl_from_file(self, filepath): try: crl_file = open(filepath, 'r') crl = crypto.load_crl(crypto.FILETYPE_PEM, crl_file.read()) crl_file.close() except IOError: # Create new CRL file if it doesn't exist crl = crypto.CRL() return crl
def parse_command(self, cmd, body=""): if cmd == "export-crl": """ Generate CRL object based on certificate serial number and revocation timestamp """ crl = crypto.CRL() if body: for line in body.split("\n"): serial_number, timestamp = line.split(":") # TODO: Assert serial against regex revocation = crypto.Revoked() revocation.set_rev_date( datetime.fromtimestamp(int(timestamp)).strftime( "%Y%m%d%H%M%SZ").encode("ascii")) revocation.set_reason(b"keyCompromise") revocation.set_serial(serial_number.encode("ascii")) crl.add_revoked(revocation) self.send( crl.export(self.server.certificate, self.server.private_key, crypto.FILETYPE_PEM, self.server.revocation_list_lifetime)) elif cmd == "ocsp-request": NotImplemented # TODO: Implement OCSP elif cmd == "sign-request": request = crypto.load_certificate_request(crypto.FILETYPE_PEM, body) for e in request.get_extensions(): key = e.get_short_name().decode("ascii") if key not in EXTENSION_WHITELIST: raise ValueError( "Certificte Signing Request contains extension '%s' which is not whitelisted" % key) # TODO: Potential exploits during PEM parsing? cert = raw_sign(self.server.private_key, self.server.certificate, request, basic_constraints=self.server.basic_constraints, key_usage=self.server.key_usage, extended_key_usage=self.server.extended_key_usage, lifetime=self.server.lifetime) self.send(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)) else: raise NotImplementedError("Unknown command: %s" % cmd) self.close_when_done()
def issue_crl(new_revoked=None): global certificate, key, crl if not crl: crl = crypto.CRL() crl.set_lastUpdate( b'20191215152933Z' ) # TODO: adjust with real timestamps according to pyOpenSSL documentation crl.set_nextUpdate(b'20191217152933Z') if new_revoked: crl.add_revoked(new_revoked) crl.sign(certificate, key, b"sha256") crl_dump = crypto.dump_crl(crypto.FILETYPE_PEM, crl) open(CRL, "wt").write(crl_dump.decode("utf-8")) return crl_dump
def crl(self): """ Returns up to date CRL of this CA """ revoked_certs = self.get_revoked_certs() crl = crypto.CRL() now_str = timezone.now().strftime(generalized_time) for cert in revoked_certs: revoked = crypto.Revoked() revoked.set_serial(bytes_compat(cert.serial_number)) revoked.set_reason(b'unspecified') revoked.set_rev_date(bytes_compat(now_str)) crl.add_revoked(revoked) return crl.export(self.x509, self.pkey, days=1, digest=b'sha256')
def create_crl(revokedcert, cakey, cacert, crlfile, next_crl_days=VALID_DAYS): crl = crypto.CRL() revoked = crypto.Revoked() serial_number = "%x" % revokedcert.get_serial_number() now = datetime.utcnow() now_str = now.strftime('%Y%m%d%H%M%SZ') revoked.set_serial(serial_number) revoked.set_reason('unspecified') revoked.set_rev_date(now_str) # revoked as of now crl.add_revoked(revoked) open(crlfile, "wt").write(crl.export(cacert, cakey, days=next_crl_days))
def crl(self): """ Returns up to date CRL of this CA """ revoked_certs = self.get_revoked_certs() crl = crypto.CRL() now_str = datetime_to_string(timezone.now()) for cert in revoked_certs: revoked = crypto.Revoked() revoked.set_serial(bytes(str(cert.serial_number), 'utf8')) revoked.set_reason(b'unspecified') revoked.set_rev_date(bytes(str(now_str), 'utf8')) crl.add_revoked(revoked) return crl.export(self.x509, self.pkey, days=1, digest=b'sha256')
def gen_crl(cert, key, format_crl, serials=[]): crl = crypto.CRL() for s in serials: r = crypto.Revoked() r.set_reason('keyCompromise') r.set_rev_date('19700101000000Z') r.set_serial(s) crl.add_revoked(r) if format_crl == 'pem': format_crl = crypto.FILETYPE_PEM else: format_crl = crypto.FILETYPE_ASN1 crl.set_version(1) crl.sign(cert, key, 'sha256') return crl.export(cert, key, format_crl, 18250, b'sha256')
def create_revoke_list(ca_cert: bytes, ca_key: bytes, serials: List[Tuple[int, datetime]]) -> bytes: crl = crypto.CRL() crl.set_lastUpdate(datetime.utcnow().strftime('%Y%m%d%H%M%SZ').encode()) crl.set_nextUpdate( (datetime.utcnow() + timedelta(days=365)).strftime('%Y%m%d%H%M%SZ').encode()) for serial, revoked_at in serials: revoked = crypto.Revoked() revoked.set_serial(hex(serial)[2:].encode()) revoked.set_reason(b'keyCompromise') revoked.set_rev_date(revoked_at.strftime('%Y%m%d%H%M%SZ').encode()) crl.add_revoked(revoked) key = crypto.load_privatekey(crypto.FILETYPE_PEM, ca_key) cert = crypto.load_certificate(crypto.FILETYPE_PEM, ca_cert) crl.sign(cert, key, digest.encode()) return crypto.dump_crl(crypto.FILETYPE_PEM, crl)
def new_crl(self): self.crl = crypto.CRL() self.write_crl()
def certidude_setup_authority(parent, country, state, locality, organization, organizational_unit, common_name, directory, crl_age, lifetime, pkcs11, group, crl_distribution_url, ocsp_responder_url, email_address, inbox, outbox): logging.info("Creating certificate authority in %s", directory) _, _, uid, gid, gecos, root, shell = pwd.getpwnam(group) os.setgid(gid) click.echo("Generating 4096-bit RSA key...") if pkcs11: raise NotImplementedError( "Hardware token support not yet implemented!") else: key = crypto.PKey() key.generate_key(crypto.TYPE_RSA, 4096) slug = os.path.basename(directory) if not crl_distribution_url: crl_distribution_url = "http://%s/api/%s/revoked/" % (common_name, slug) # File paths ca_key = os.path.join(directory, "ca_key.pem") ca_crt = os.path.join(directory, "ca_crt.pem") ca_crl = os.path.join(directory, "ca_crl.pem") crl_distribution_points = "URI:%s" % crl_distribution_url ca = crypto.X509() #ca.set_version(3) # breaks gcr-viewer?! ca.set_serial_number(1) ca.get_subject().CN = common_name ca.get_subject().C = country ca.get_subject().ST = state ca.get_subject().L = locality ca.get_subject().O = organization ca.get_subject().OU = organizational_unit ca.gmtime_adj_notBefore(0) ca.gmtime_adj_notAfter(lifetime * 24 * 60 * 60) ca.set_issuer(ca.get_subject()) ca.set_pubkey(key) ca.add_extensions([ crypto.X509Extension(b"basicConstraints", True, b"CA:TRUE"), crypto.X509Extension(b"keyUsage", True, b"keyCertSign, cRLSign"), crypto.X509Extension(b"subjectKeyIdentifier", False, b"hash", subject=ca), crypto.X509Extension(b"crlDistributionPoints", False, crl_distribution_points.encode("ascii")) ]) if email_address: subject_alt_name = "email:%s" % email_address ca.add_extensions([ crypto.X509Extension(b"subjectAltName", False, subject_alt_name.encode("ascii")) ]) if not ocsp_responder_url: ocsp_responder_url = "http://%s/api/%s/ocsp/" % (common_name, slug) authority_info_access = "OCSP;URI:%s" % ocsp_responder_url ca.add_extensions([ crypto.X509Extension(b"authorityInfoAccess", False, authority_info_access.encode("ascii")) ]) click.echo("Signing %s..." % subject2dn(ca.get_subject())) # openssl x509 -in ca_crt.pem -outform DER | sha1sum # openssl x509 -fingerprint -in ca_crt.pem ca.sign(key, "sha1") os.umask(0o027) if not os.path.exists(directory): os.makedirs(directory) os.umask(0o007) for subdir in ("signed", "requests", "revoked"): if not os.path.exists(os.path.join(directory, subdir)): os.mkdir(os.path.join(directory, subdir)) with open(ca_crl, "wb") as fh: crl = crypto.CRL() fh.write(crl.export(ca, key, days=crl_age)) with open(os.path.join(directory, "serial"), "w") as fh: fh.write("1") os.umask(0o027) with open(ca_crt, "wb") as fh: fh.write(crypto.dump_certificate(crypto.FILETYPE_PEM, ca)) os.umask(0o077) with open(ca_key, "wb") as fh: fh.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, key)) click.echo("Insert following to /etc/ssl/openssl.cnf:") click.echo() click.secho(env.get_template("openssl.cnf").render(locals()), fg="blue") click.echo() click.echo("Use following commands to inspect the newly created files:") click.echo() click.echo(" openssl crl -inform PEM -text -noout -in %s" % ca_crl) click.echo(" openssl x509 -text -noout -in %s" % ca_crt) click.echo(" openssl rsa -check -in %s" % ca_key) click.echo(" openssl verify -CAfile %s %s" % (ca_crt, ca_crt)) click.echo() click.echo("Use following to launch privilege isolated signer processes:") click.echo() click.echo(" certidude spawn") click.echo() click.echo("Use following command to serve CA read-only:") click.echo() click.echo(" certidude serve")
def revoke_certificate(ca_pem, ca_key, revoked_file, crl_file, user_cert_dir, username, crl_path=None): """ Function to create/update a CRL with revoked user certificates :param ca_pem: The path to your CA PEM file :param ca_key: The Path to your CA key file :param revoked_file: Path to JSON file to be used as a DB for revocation :param crl_file: Path to CRL file :param user_cert_dir: Path to director containing all issued user PEM files :param username: the username to Revoke :param crl_path: The path to your previous CRL file to be loaded and updated :return: bool """ import os import json from OpenSSL import crypto from datetime import datetime data = {} certificate = crypto.load_certificate(crypto.FILETYPE_PEM, open(ca_pem, mode="rb").read()) private_key = crypto.load_privatekey(crypto.FILETYPE_PEM, open(ca_key, mode="r").read()) if crl_path: crl = crypto.load_crl(crypto.FILETYPE_PEM, open(crl_path, mode="rb").read()) else: crl = crypto.CRL() if os.path.exists(revoked_file): with open(revoked_file, 'r') as json_file: data = json.load(json_file) for cert in os.listdir(user_cert_dir): if cert.lower() == f"{username.lower()}.pem": with open(cert, 'rb') as cert: revoked_cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert.read()) data[str(revoked_cert.get_serial_number())] = username break for key in data: revoked_time = _utc_time_from_datetime(datetime.utcnow()) revoked = crypto.Revoked() revoked.set_serial(format(int(key), "02x").encode()) revoked.set_rev_date(bytes(revoked_time, encoding='utf8')) crl.add_revoked(revoked) crl.sign(certificate, private_key, b"sha256") with open(revoked_file, 'w+') as json_file: json.dump(data, json_file) with open(crl_file, 'wb') as f: f.write(crl.export(cert=certificate, key=private_key, digest=b"sha256")) delete = 0 with open(ca_pem, "r") as f: lines = f.readlines() with open(ca_pem, "w") as f: for line in lines: if delete: continue elif line.strip("\n") != "-----BEGIN X509 CRL-----": f.write(line) else: delete = 1 with open(ca_pem, "ab") as f: f.write(crl.export(cert=certificate, key=private_key, digest=b"sha256"))
def revoke(self, cert, rev_reason='unspecified', rev_date=None): """ revoke certificate """ self.logger.debug('CAhandler.revoke({0}: {1})'.format(rev_reason, rev_date)) code = None message = None detail = None # overwrite revocation date - we ignore what has been submitted rev_date = uts_to_date_utc(uts_now(), '%y%m%d%H%M%SZ') if 'issuing_ca_crl' in self.issuer_dict and self.issuer_dict['issuing_ca_crl']: # load ca cert and key (ca_key, ca_cert) = self._ca_load() # turn of chain_check due to issues in pyopenssl (check is not working if key-usage is set) # result = self._certificate_chain_verify(cert, ca_cert) result = None # proceed if the cert and ca-cert belong together # if not result: serial = cert_serial_get(self.logger, cert) # serial = serial.replace('0x', '') if ca_key and ca_cert and serial: serial = hex(serial).replace('0x', '') if os.path.exists(self.issuer_dict['issuing_ca_crl']): # existing CRL with open(self.issuer_dict['issuing_ca_crl'], 'r') as fso: crl = crypto.load_crl(crypto.FILETYPE_PEM, fso.read()) # check CRL already contains serial sn_match = self._crl_check(crl, serial) else: # new CRL crl = crypto.CRL() sn_match = None # this is the revocation operation if not sn_match: revoked = crypto.Revoked() revoked.set_reason(convert_string_to_byte(rev_reason)) revoked.set_serial(convert_string_to_byte(serial)) revoked.set_rev_date(convert_string_to_byte(rev_date)) crl.add_revoked(revoked) # save CRL crl_text = crl.export(ca_cert, ca_key, crypto.FILETYPE_PEM, 7, convert_string_to_byte('sha256')) with open(self.issuer_dict['issuing_ca_crl'], 'wb') as fso: fso.write(crl_text) code = 200 else: code = 400 message = 'urn:ietf:params:acme:error:alreadyRevoked' detail = 'Certificate has already been revoked' else: code = 400 message = 'urn:ietf:params:acme:error:serverInternal' detail = 'configuration error' #else: # code = 400 # message = 'urn:ietf:params:acme:error:serverInternal' # detail = result else: code = 400 message = 'urn:ietf:params:acme:error:serverInternal' detail = 'Unsupported operation' self.logger.debug('CAhandler.revoke() ended') return(code, message, detail)
def certidude_setup_authority(parent, country, state, locality, organization, organizational_unit, common_name, directory, certificate_lifetime, authority_lifetime, revocation_list_lifetime, pkcs11, crl_distribution_url, ocsp_responder_url, email_address, inbox, outbox): slug = os.path.basename( directory[:-1] if directory.endswith('/') else directory) if not slug: raise click.ClickException("Please supply proper target path") # Make sure slug is valid if not re.match(r"^[_a-zA-Z0-9]+$", slug): raise click.ClickException( "CA name can contain only alphanumeric and '_' characters") if os.path.lexists(directory): raise click.ClickException( "Output directory {} already exists.".format(directory)) click.echo("CA configuration files are saved to: {}".format(directory)) click.echo("Generating 4096-bit RSA key...") if pkcs11: raise NotImplementedError( "Hardware token support not yet implemented!") else: key = crypto.PKey() key.generate_key(crypto.TYPE_RSA, 4096) if not crl_distribution_url: crl_distribution_url = "http://%s/api/%s/revoked/" % (common_name, slug) # File paths ca_key = os.path.join(directory, "ca_key.pem") ca_crt = os.path.join(directory, "ca_crt.pem") ca_crl = os.path.join(directory, "ca_crl.pem") crl_distribution_points = "URI:%s" % crl_distribution_url ca = crypto.X509() ca.set_version(2) # This corresponds to X.509v3 ca.set_serial_number(1) ca.get_subject().CN = common_name ca.get_subject().C = country ca.get_subject().ST = state ca.get_subject().L = locality ca.get_subject().O = organization ca.get_subject().OU = organizational_unit ca.gmtime_adj_notBefore(0) ca.gmtime_adj_notAfter(authority_lifetime * 24 * 60 * 60) ca.set_issuer(ca.get_subject()) ca.set_pubkey(key) ca.add_extensions([ crypto.X509Extension(b"basicConstraints", True, b"CA:TRUE"), crypto.X509Extension(b"keyUsage", True, b"keyCertSign, cRLSign"), crypto.X509Extension(b"subjectKeyIdentifier", False, b"hash", subject=ca), crypto.X509Extension(b"crlDistributionPoints", False, crl_distribution_points.encode("ascii")) ]) if email_address: subject_alt_name = "email:%s" % email_address ca.add_extensions([ crypto.X509Extension(b"subjectAltName", False, subject_alt_name.encode("ascii")) ]) if ocsp_responder_url: raise NotImplementedError() """ ocsp_responder_url = "http://%s/api/%s/ocsp/" % (common_name, slug) authority_info_access = "OCSP;URI:%s" % ocsp_responder_url ca.add_extensions([ crypto.X509Extension( b"authorityInfoAccess", False, authority_info_access.encode("ascii")) ]) """ click.echo("Signing %s..." % subject2dn(ca.get_subject())) # openssl x509 -in ca_crt.pem -outform DER | sha256sum # openssl x509 -fingerprint -in ca_crt.pem ca.sign(key, "sha256") os.umask(0o027) if not os.path.exists(directory): os.makedirs(directory) os.umask(0o007) for subdir in ("signed", "requests", "revoked"): if not os.path.exists(os.path.join(directory, subdir)): os.mkdir(os.path.join(directory, subdir)) with open(ca_crl, "wb") as fh: crl = crypto.CRL() fh.write(crl.export(ca, key, days=revocation_list_lifetime)) with open(os.path.join(directory, "serial"), "w") as fh: fh.write("1") os.umask(0o027) with open(ca_crt, "wb") as fh: fh.write(crypto.dump_certificate(crypto.FILETYPE_PEM, ca)) os.umask(0o077) with open(ca_key, "wb") as fh: fh.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, key)) with open(os.path.join(directory, "openssl.cnf.example"), "w") as fh: fh.write(env.get_template("openssl.cnf").render(locals())) click.echo("You need to copy the contents of the 'openssl.cnf.example'") click.echo("to system-wide OpenSSL configuration file, usually located") click.echo("at /etc/ssl/openssl.cnf") click.echo() click.echo("Use following commands to inspect the newly created files:") click.echo() click.echo(" openssl crl -inform PEM -text -noout -in %s" % ca_crl) click.echo(" openssl x509 -text -noout -in %s" % ca_crt) click.echo(" openssl rsa -check -in %s" % ca_key) click.echo(" openssl verify -CAfile %s %s" % (ca_crt, ca_crt)) click.echo() click.echo("Use following to launch privilege isolated signer processes:") click.echo() click.echo(" certidude spawn") click.echo() click.echo("Use following command to serve CA read-only:") click.echo() click.echo(" certidude serve")
def update_crl(): # Load root key and cert root_cert, root_key = load_root() # Load CRL if one is found in current directory root_crl = load_crl() if root_crl: print 'Found %s.crl' % (config.root, ) # Identify revoked certs print print 'Revoked serial numbers:' print 'serial' for rev in root_crl.get_revoked(): print rev.get_serial().lower() else: root_crl = crypto.CRL() # List certificates in current directory print print 'Certificates in current directory:' known_certs = glob.glob('*.crt') # Remove root cert from list, cannot revoke itself known_certs.remove(config.root + '.crt') if len(known_certs) < 1: print 'none found' return name2serial = {} print '%-16s %-20s %-15s %-15s' % ('serial', 'name', 'from', 'to') for certname in known_certs: f = open(certname, 'rt') pem = f.read() f.close() cert = crypto.load_certificate(crypto.FILETYPE_PEM, pem) serial = hex(cert.get_serial_number())[2:-1] name2serial[certname[:-4]] = serial print '%-16s %-20s %-15s %-15s' % (serial, certname[:-4], nice_date(cert.get_notBefore()), nice_date(cert.get_notAfter())) while 1: print req = raw_input('Certificate to revoke by name (return to exit): ') if len(req) < 1: return if not req in name2serial.keys(): print 'cannot find:', req else: break rev = crypto.Revoked() rev.set_serial(name2serial[req]) rev.set_reason('unspecified') rev.set_rev_date(now()) # Update CRL root_crl.add_revoked(rev) # Sign CRL crl_text = root_crl.export(root_cert, root_key, crypto.FILETYPE_PEM, days=365) # Publish CRL f = open(config.root + '.crl', 'w') f.write(crl_text) f.close() return