Ejemplo n.º 1
0
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')))
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
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))
Ejemplo n.º 5
0
    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)
Ejemplo n.º 6
0
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 ""
Ejemplo n.º 7
0
    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)
Ejemplo n.º 8
0
    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")
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
    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
Ejemplo n.º 11
0
    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()
Ejemplo n.º 12
0
Archivo: CA.py Proyecto: sted19/pyCA
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
Ejemplo n.º 13
0
 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')
Ejemplo n.º 14
0
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))
Ejemplo n.º 15
0
 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')
Ejemplo n.º 16
0
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')
Ejemplo n.º 17
0
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)
Ejemplo n.º 18
0
    def new_crl(self):

        self.crl = crypto.CRL()
        self.write_crl()
Ejemplo n.º 19
0
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")
Ejemplo n.º 20
0
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"))
Ejemplo n.º 21
0
    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)
Ejemplo n.º 22
0
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")
Ejemplo n.º 23
0
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