Пример #1
0
def export_crl(pem=True):
    # To migrate older installations run following:
    # for j in /var/lib/certidude/*/revoked/*.pem; do echo $(attr -s 'revocation.reason' -V key_compromise $j); done
    builder = CertificateListBuilder(config.AUTHORITY_CRL_URL, certificate,
                                     generate_serial())

    for filename in os.listdir(config.REVOKED_DIR):
        if not filename.endswith(".pem"):
            continue
        serial_number = filename[:-4]
        # TODO: Assert serial against regex
        revoked_path = os.path.join(config.REVOKED_DIR, filename)
        try:
            reason = getxattr(revoked_path, "user.revocation.reason").decode(
                "ascii")  # TODO: dedup
        except IOError:  # TODO: make sure it's not required
            reason = "key_compromise"

        # TODO: Skip expired certificates
        s = os.stat(revoked_path)
        builder.add_certificate(int(filename[:-4], 16),
                                datetime.utcfromtimestamp(s.st_ctime), reason)

    certificate_list = builder.build(private_key)
    if pem:
        return pem_armor_crl(certificate_list)
    return certificate_list.dump()
    def test_build_basic_crl(self):
        root_private_key = asymmetric.load_private_key(os.path.join(fixtures_dir, 'root.key'), 'password123')
        root_certificate = asymmetric.load_certificate(os.path.join(fixtures_dir, 'root.crt'))

        builder = CertificateListBuilder(
            'http://crl.example.com',
            root_certificate,
            50000
        )
        revoked_at = datetime(2015, 8, 1, 12, 0, 0, tzinfo=timezone.utc)
        builder.add_certificate(29232181, revoked_at, 'key_compromise')
        certificate_list = builder.build(root_private_key)
        der_bytes = certificate_list.dump()

        new_cert_list = crl.CertificateList.load(der_bytes)
        tbs_cert_list = new_cert_list['tbs_cert_list']
        revoked_certificates = tbs_cert_list['revoked_certificates']

        now = datetime.now(timezone.utc)

        self.assertEqual('v3', tbs_cert_list['version'].native)
        self.assertEqual('rsassa_pkcs1v15', tbs_cert_list['signature'].signature_algo)
        self.assertEqual('sha256', tbs_cert_list['signature'].hash_algo)
        self.assertEqual(root_certificate.asn1.subject, tbs_cert_list['issuer'])
        self.assertEqual(root_certificate.asn1.subject.sha256, tbs_cert_list['issuer'].sha256)
        self.assertGreaterEqual(now, tbs_cert_list['this_update'].native)
        self.assertLess(now, tbs_cert_list['next_update'].native)
        self.assertEqual(set(['issuing_distribution_point']), new_cert_list.critical_extensions)

        self.assertEqual(1, len(revoked_certificates))
        revoked_cert = revoked_certificates[0]
        self.assertEqual(29232181, revoked_cert['user_certificate'].native)
        self.assertEqual(revoked_at, revoked_cert['revocation_date'].native)
        self.assertEqual(set(), revoked_cert.critical_extensions)
        self.assertEqual('key_compromise', revoked_cert.crl_reason_value.native)
        self.assertEqual(None, revoked_cert.invalidity_date_value)
        self.assertEqual(None, revoked_cert.certificate_issuer_value)
        self.assertEqual(None, revoked_cert.issuer_name)

        self.assertEqual(None, new_cert_list.issuer_alt_name_value)
        self.assertEqual(50000, new_cert_list.crl_number_value.native)
        self.assertEqual(None, new_cert_list.delta_crl_indicator_value)
        self.assertEqual('full_name', new_cert_list.issuing_distribution_point_value['distribution_point'].name)
        self.assertEqual(
            'uniform_resource_identifier',
            new_cert_list.issuing_distribution_point_value['distribution_point'].chosen[0].name
        )
        self.assertEqual(
            'http://crl.example.com',
            new_cert_list.issuing_distribution_point_value['distribution_point'].chosen[0].native
        )
        self.assertEqual(root_certificate.asn1.key_identifier, new_cert_list.authority_key_identifier)
        self.assertEqual(None, new_cert_list.freshest_crl_value)
        self.assertEqual(None, new_cert_list.authority_information_access_value)
    def test_build_basic_crl(self):
        root_private_key = asymmetric.load_private_key(os.path.join(fixtures_dir, "root.key"), "password123")
        root_certificate = asymmetric.load_certificate(os.path.join(fixtures_dir, "root.crt"))

        builder = CertificateListBuilder("http://crl.example.com", root_certificate, 50000)
        revoked_at = datetime(2015, 8, 1, 12, 0, 0, tzinfo=timezone.utc)
        builder.add_certificate(29232181, revoked_at, "key_compromise")
        certificate_list = builder.build(root_private_key)
        der_bytes = certificate_list.dump()

        new_cert_list = crl.CertificateList.load(der_bytes)
        tbs_cert_list = new_cert_list["tbs_cert_list"]
        revoked_certificates = tbs_cert_list["revoked_certificates"]

        now = datetime.now(timezone.utc)

        self.assertEqual("v3", tbs_cert_list["version"].native)
        self.assertEqual("rsassa_pkcs1v15", tbs_cert_list["signature"].signature_algo)
        self.assertEqual("sha256", tbs_cert_list["signature"].hash_algo)
        self.assertEqual(root_certificate.asn1.subject, tbs_cert_list["issuer"])
        self.assertEqual(root_certificate.asn1.subject.sha256, tbs_cert_list["issuer"].sha256)
        self.assertGreaterEqual(now, tbs_cert_list["this_update"].native)
        self.assertLess(now, tbs_cert_list["next_update"].native)
        self.assertEqual(set(["issuing_distribution_point"]), new_cert_list.critical_extensions)

        self.assertEqual(1, len(revoked_certificates))
        revoked_cert = revoked_certificates[0]
        self.assertEqual(29232181, revoked_cert["user_certificate"].native)
        self.assertEqual(revoked_at, revoked_cert["revocation_date"].native)
        self.assertEqual(set(), revoked_cert.critical_extensions)
        self.assertEqual("key_compromise", revoked_cert.crl_reason_value.native)
        self.assertEqual(None, revoked_cert.invalidity_date_value)
        self.assertEqual(None, revoked_cert.certificate_issuer_value)
        self.assertEqual(None, revoked_cert.issuer_name)

        self.assertEqual(None, new_cert_list.issuer_alt_name_value)
        self.assertEqual(50000, new_cert_list.crl_number_value.native)
        self.assertEqual(None, new_cert_list.delta_crl_indicator_value)
        self.assertEqual("full_name", new_cert_list.issuing_distribution_point_value["distribution_point"].name)
        self.assertEqual(
            "uniform_resource_identifier",
            new_cert_list.issuing_distribution_point_value["distribution_point"].chosen[0].name,
        )
        self.assertEqual(
            "http://crl.example.com",
            new_cert_list.issuing_distribution_point_value["distribution_point"].chosen[0].native,
        )
        self.assertEqual(root_certificate.asn1.key_identifier, new_cert_list.authority_key_identifier)
        self.assertEqual(None, new_cert_list.freshest_crl_value)
        self.assertEqual(None, new_cert_list.authority_information_access_value)
    def test_build_delta_crl(self):
        root_certificate = asymmetric.load_certificate(os.path.join(fixtures_dir, "root.crt"))

        crl_issuer_private_key = asymmetric.load_private_key(
            os.path.join(fixtures_dir, "crl_issuer.key"), "password123"
        )
        crl_issuer_certificate = asymmetric.load_certificate(os.path.join(fixtures_dir, "crl_issuer.crt"))

        builder = CertificateListBuilder("http://crl.example.com/delta", crl_issuer_certificate, 50001)
        builder.certificate_issuer = root_certificate
        builder.issuer_certificate_url = "http://download.example.com/crl_issuer"
        builder.delta_of = 50000

        certificate_list = builder.build(crl_issuer_private_key)
        der_bytes = certificate_list.dump()

        new_cert_list = crl.CertificateList.load(der_bytes)
        tbs_cert_list = new_cert_list["tbs_cert_list"]
        revoked_certificates = tbs_cert_list["revoked_certificates"]

        now = datetime.now(timezone.utc)

        self.assertEqual("v3", tbs_cert_list["version"].native)
        self.assertEqual("rsassa_pkcs1v15", tbs_cert_list["signature"].signature_algo)
        self.assertEqual("sha256", tbs_cert_list["signature"].hash_algo)
        self.assertEqual(crl_issuer_certificate.asn1.subject, tbs_cert_list["issuer"])
        self.assertEqual(crl_issuer_certificate.asn1.subject.sha256, tbs_cert_list["issuer"].sha256)
        self.assertGreaterEqual(now, tbs_cert_list["this_update"].native)
        self.assertLess(now, tbs_cert_list["next_update"].native)
        self.assertEqual(set(["issuing_distribution_point", "delta_crl_indicator"]), new_cert_list.critical_extensions)

        self.assertEqual(0, len(revoked_certificates))

        self.assertEqual(None, new_cert_list.issuer_alt_name_value)
        self.assertEqual(50001, new_cert_list.crl_number_value.native)
        self.assertEqual(50000, new_cert_list.delta_crl_indicator_value.native)
        self.assertEqual("full_name", new_cert_list.issuing_distribution_point_value["distribution_point"].name)
        self.assertEqual(
            "uniform_resource_identifier",
            new_cert_list.issuing_distribution_point_value["distribution_point"].chosen[0].name,
        )
        self.assertEqual(
            "http://crl.example.com/delta",
            new_cert_list.issuing_distribution_point_value["distribution_point"].chosen[0].native,
        )
        self.assertEqual(crl_issuer_certificate.asn1.key_identifier, new_cert_list.authority_key_identifier)
        self.assertEqual([], new_cert_list.delta_crl_distribution_points)
        self.assertEqual(["http://download.example.com/crl_issuer"], new_cert_list.issuer_cert_urls)
Пример #5
0
def build_ca():
    if not os.path.exists(settings.CA_PATH):
        os.makedirs(settings.CA_PATH)

    root_ca_public_key, root_ca_private_key = asymmetric.generate_pair(
        'rsa', bit_size=4096)

    with open(settings.CA_KEY, 'wb') as f:
        f.write(
            asymmetric.dump_private_key(root_ca_private_key,
                                        settings.CA_KEY_PASSWD))

    builder = CertificateBuilder(
        {
            'country_name': 'CR',
            'state_or_province_name': 'San Jose',
            'locality_name': 'Costa Rica',
            'organization_name': 'DFVA Independiente',
            'common_name': 'DFVA Root CA 1',
        }, root_ca_public_key)
    now = timezone.now()
    builder.self_signed = True
    builder.ca = True
    builder.end_date = now + timedelta(settings.CA_CERT_DURATION * 10)
    root_ca_certificate = builder.build(root_ca_private_key)

    with open(settings.CA_CERT, 'wb') as f:
        f.write(pem_armor_certificate(root_ca_certificate))

    builder = CertificateListBuilder('http://crl.dfva.info',
                                     root_ca_certificate, 1000)
    crl_list = builder.build(root_ca_private_key)

    with open(settings.CA_CRL, 'wb') as f:
        f.write(crl_list.dump())
Пример #6
0
def crl():
    builder = CertificateListBuilder(unicode(CAS_CRL_URL), certificate, 1000)
    builder._issuing_distribution_point = None

    connection = pymysql.connect(host=CAS_CRL_MYSQL_HOST,
                                 port=CAS_CRL_MYSQL_PORT,
                                 user=CAS_CRL_MYSQL_USER,
                                 password=CAS_CRL_MYSQL_PASSWD,
                                 db=CAS_CRL_MYSQL_DB,
                                 charset=CAS_CRL_MYSQL_CHARSET,
                                 cursorclass=cursors.DictCursor)

    with connection.cursor() as cursor:
        # Read a single record
        sql = "SELECT `id`, `updated_at` FROM `pki` where is_delete=1"
        cursor.execute(sql)
        for row in cursor:
            revoked_cert_serial = row['id']
            revoked_time = row['updated_at']
            builder.add_certificate(revoked_cert_serial, revoked_time,
                                    'key_compromise')

    certificate_list = builder.build(private_key)
    crl = certificate_list.dump()
    strIO = StringIO.StringIO()
    strIO.write(crl)
    strIO.seek(0)

    return send_file(strIO, attachment_filename="cas.crl", as_attachment=True)
Пример #7
0
def export_crl(pem=True):
    builder = CertificateListBuilder(
        config.AUTHORITY_CRL_URL,
        certificate,
        1  # TODO: monotonically increasing
    )

    for filename in os.listdir(config.REVOKED_DIR):
        if not filename.endswith(".pem"):
            continue
        serial_number = filename[:-4]
        # TODO: Assert serial against regex
        revoked_path = os.path.join(config.REVOKED_DIR, filename)
        # TODO: Skip expired certificates
        s = os.stat(revoked_path)
        builder.add_certificate(int(filename[:-4], 16),
                                datetime.utcfromtimestamp(s.st_ctime),
                                u"key_compromise")

    certificate_list = builder.build(private_key)
    if pem:
        return pem_armor_crl(certificate_list)
    return certificate_list.dump()
    def test_build_delta_crl(self):
        root_certificate = asymmetric.load_certificate(os.path.join(fixtures_dir, 'root.crt'))

        crl_issuer_private_key = asymmetric.load_private_key(
            os.path.join(fixtures_dir, 'crl_issuer.key'),
            'password123'
        )
        crl_issuer_certificate = asymmetric.load_certificate(os.path.join(fixtures_dir, 'crl_issuer.crt'))

        builder = CertificateListBuilder(
            'http://crl.example.com/delta',
            crl_issuer_certificate,
            50001
        )
        builder.certificate_issuer = root_certificate
        builder.issuer_certificate_url = 'http://download.example.com/crl_issuer'
        builder.delta_of = 50000

        certificate_list = builder.build(crl_issuer_private_key)
        der_bytes = certificate_list.dump()

        new_cert_list = crl.CertificateList.load(der_bytes)
        tbs_cert_list = new_cert_list['tbs_cert_list']
        revoked_certificates = tbs_cert_list['revoked_certificates']

        now = datetime.now(timezone.utc)

        self.assertEqual('v3', tbs_cert_list['version'].native)
        self.assertEqual('rsassa_pkcs1v15', tbs_cert_list['signature'].signature_algo)
        self.assertEqual('sha256', tbs_cert_list['signature'].hash_algo)
        self.assertEqual(crl_issuer_certificate.asn1.subject, tbs_cert_list['issuer'])
        self.assertEqual(crl_issuer_certificate.asn1.subject.sha256, tbs_cert_list['issuer'].sha256)
        self.assertGreaterEqual(now, tbs_cert_list['this_update'].native)
        self.assertLess(now, tbs_cert_list['next_update'].native)
        self.assertEqual(set(['issuing_distribution_point', 'delta_crl_indicator']), new_cert_list.critical_extensions)

        self.assertEqual(0, len(revoked_certificates))

        self.assertEqual(None, new_cert_list.issuer_alt_name_value)
        self.assertEqual(50001, new_cert_list.crl_number_value.native)
        self.assertEqual(50000, new_cert_list.delta_crl_indicator_value.native)
        self.assertEqual('full_name', new_cert_list.issuing_distribution_point_value['distribution_point'].name)
        self.assertEqual(
            'uniform_resource_identifier',
            new_cert_list.issuing_distribution_point_value['distribution_point'].chosen[0].name
        )
        self.assertEqual(
            'http://crl.example.com/delta',
            new_cert_list.issuing_distribution_point_value['distribution_point'].chosen[0].native
        )
        self.assertEqual(crl_issuer_certificate.asn1.key_identifier, new_cert_list.authority_key_identifier)
        self.assertEqual([], new_cert_list.delta_crl_distribution_points)
        self.assertEqual(['http://download.example.com/crl_issuer'], new_cert_list.issuer_cert_urls)
Пример #9
0
    def revoke_certificate(self, certificate):
        # Fixme: Esta función abre y reconstruye el crl
        # El problema es que la concurrencia puede afectar la reconstrucción
        # del crl.
        # Esto podría ayudar https://github.com/ambitioninc/django-db-mutex
        # Fixme: Este método no es eficiente pues requiere reconstruir otra
        # lista y pasar los valores de la anterior cuando debería ser
        # solamente agregar el nuevo valor, pero  no logré descifrar como
        # hacerlo
        _, _, certificate_bytes = pem.unarmor(
            certificate.encode(), multiple=False)
        certificate = x509.Certificate.load(certificate_bytes)

        ca_private_key = asymmetric.load_private_key(
            self.ca_key,
            password=settings.CA_KEY_PASSWD)
        ca_certificate = asymmetric.load_certificate(self.ca_crt)

        with open(settings.CA_CRL, 'rb') as f:
            cert_list = crl.CertificateList.load(f.read())

        builder = CertificateListBuilder(
            cert_list.issuing_distribution_point_value.native[
                'distribution_point'][0],
            ca_certificate,
            1000
        )

        for revoked_cert in cert_list[
                'tbs_cert_list']['revoked_certificates']:
            revoked_cert_serial = revoked_cert['user_certificate'].native
            revoked_time = revoked_cert['revocation_date'].native
            reason = revoked_cert['crl_entry_extensions'][0][
                'extn_value'].native
            builder.add_certificate(revoked_cert_serial, revoked_time,
                                    reason)

        builder.add_certificate(certificate.serial_number,
                                timezone.now(),
                                "cessation_of_operation")

        crl_list = builder.build(ca_private_key)

        with open(settings.CA_CRL, 'wb') as f:
            f.write(crl_list.dump())

        logger.info("SimpleCA: revoke certificate, don't make anything")
Пример #10
0
def generate_client_certs(domain, base_year, quiet=False):
    ca_private_key = load_private('ca')
    ca_cert = load_cert('ca')
    ca2_private_key = load_private('ca2')
    ca2_cert = load_cert('ca2')
    public_key = load_public('client')
    crl_url = 'http://crls.{}:9991/client.crl'.format(domain)

    # Certificate that is valid
    if not quiet:
        write('Generating good client cert ... ', end='')

    builder = CertificateBuilder(
        {
            'country_name': 'US',
            'state_or_province_name': 'Massachusetts',
            'locality_name': 'Newbury',
            'organization_name': 'TLS Client Certificates Limited',
            'common_name': 'Good TLS Client Certificate',
        }, public_key)
    builder.issuer = ca_cert
    builder.crl_url = crl_url
    builder.begin_date = datetime(base_year,
                                  1,
                                  1,
                                  0,
                                  0,
                                  0,
                                  tzinfo=timezone.utc)
    builder.end_date = datetime(base_year + 3,
                                1,
                                1,
                                0,
                                0,
                                0,
                                tzinfo=timezone.utc)
    certificate = builder.build(ca_private_key)

    dump_cert('client-good', certificate)

    if not quiet:
        write('done')

    # Certificate that has expired
    if not quiet:
        write('Generating expired client cert ... ', end='')

    builder = CertificateBuilder(
        {
            'country_name': 'US',
            'state_or_province_name': 'Massachusetts',
            'locality_name': 'Newbury',
            'organization_name': 'TLS Client Certificates Limited',
            'common_name': 'Expired TLS Client Certificate',
        }, public_key)
    builder.issuer = ca_cert
    builder.crl_url = crl_url
    builder.begin_date = datetime(base_year - 1,
                                  1,
                                  1,
                                  0,
                                  0,
                                  0,
                                  tzinfo=timezone.utc)
    builder.end_date = datetime(base_year, 1, 1, 0, 0, 0, tzinfo=timezone.utc)
    certificate = builder.build(ca_private_key)

    dump_cert('client-expired', certificate)

    if not quiet:
        write('done')

    # Certificate that is not yet valid
    if not quiet:
        write('Generating future client cert ... ', end='')

    builder = CertificateBuilder(
        {
            'country_name': 'US',
            'state_or_province_name': 'Massachusetts',
            'locality_name': 'Newbury',
            'organization_name': 'TLS Client Certificates Limited',
            'common_name': 'Future TLS Client Certificate',
        }, public_key)
    builder.issuer = ca_cert
    builder.crl_url = crl_url
    builder.begin_date = datetime(base_year + 3,
                                  1,
                                  1,
                                  0,
                                  0,
                                  0,
                                  tzinfo=timezone.utc)
    builder.end_date = datetime(base_year + 4,
                                1,
                                1,
                                0,
                                0,
                                0,
                                tzinfo=timezone.utc)
    certificate = builder.build(ca_private_key)

    dump_cert('client-future', certificate)

    if not quiet:
        write('done')

    # Certificate issued by untrusted CA
    if not quiet:
        write('Generating untrusted client cert ... ', end='')

    builder = CertificateBuilder(
        {
            'country_name': 'US',
            'state_or_province_name': 'Massachusetts',
            'locality_name': 'Newbury',
            'organization_name': 'TLS Client Certificates Limited',
            'common_name': 'Untrusted TLS Client Certificate',
        }, public_key)
    builder.issuer = ca2_cert
    builder.begin_date = datetime(base_year,
                                  1,
                                  1,
                                  0,
                                  0,
                                  0,
                                  tzinfo=timezone.utc)
    builder.end_date = datetime(base_year + 3,
                                1,
                                1,
                                0,
                                0,
                                0,
                                tzinfo=timezone.utc)
    certificate = builder.build(ca2_private_key)

    dump_cert('client-untrusted', certificate)

    if not quiet:
        write('done')

    # Certificate that has a weak signature
    if not quiet:
        write('Generating weak client cert ... ', end='')

    builder = CertificateBuilder(
        {
            'country_name': 'US',
            'state_or_province_name': 'Massachusetts',
            'locality_name': 'Newbury',
            'organization_name': 'TLS Client Certificates Limited',
            'common_name': 'Weak TLS Client Certificate',
        }, public_key)
    builder.issuer = ca_cert
    builder.crl_url = crl_url
    # Hack since API doesn't allow selection of weak algo
    builder._hash_algo = 'md5'
    builder.begin_date = datetime(base_year,
                                  1,
                                  1,
                                  0,
                                  0,
                                  0,
                                  tzinfo=timezone.utc)
    builder.end_date = datetime(base_year + 3,
                                1,
                                1,
                                0,
                                0,
                                0,
                                tzinfo=timezone.utc)
    certificate = builder.build(ca_private_key)

    dump_cert('client-weak', certificate)

    if not quiet:
        write('done')

    # Certificate that has bad key usage
    if not quiet:
        write('Generating bad key usage client cert ... ', end='')

    builder = CertificateBuilder(
        {
            'country_name': 'US',
            'state_or_province_name': 'Massachusetts',
            'locality_name': 'Newbury',
            'organization_name': 'TLS Client Certificates Limited',
            'common_name': 'Bad Key Usage TLS Client Certificate',
        }, public_key)
    builder.issuer = ca_cert
    builder.crl_url = crl_url
    builder.begin_date = datetime(base_year,
                                  1,
                                  1,
                                  0,
                                  0,
                                  0,
                                  tzinfo=timezone.utc)
    builder.end_date = datetime(base_year + 3,
                                1,
                                1,
                                0,
                                0,
                                0,
                                tzinfo=timezone.utc)
    builder.key_usage = set(['crl_sign'])
    builder.extended_key_usage = set(['email_protection'])
    certificate = builder.build(ca_private_key)

    dump_cert('client-bad-key-usage', certificate)

    if not quiet:
        write('done')

    # Certificate that has been revoked
    if not quiet:
        write('Generating revoked client cert ... ', end='')

    builder = CertificateBuilder(
        {
            'country_name': 'US',
            'state_or_province_name': 'Massachusetts',
            'locality_name': 'Newbury',
            'organization_name': 'TLS Client Certificates Limited',
            'common_name': 'Revoked TLS Client Certificate',
        }, public_key)
    builder.issuer = ca_cert
    builder.crl_url = crl_url
    builder.begin_date = datetime(base_year,
                                  1,
                                  1,
                                  0,
                                  0,
                                  0,
                                  tzinfo=timezone.utc)
    builder.end_date = datetime(base_year + 3,
                                1,
                                1,
                                0,
                                0,
                                0,
                                tzinfo=timezone.utc)
    revoked_certificate = builder.build(ca_private_key)

    dump_cert('client-revoked', revoked_certificate)

    if not quiet:
        write('done')

    crl_number = 1000
    crl_builder = CertificateListBuilder(crl_url, ca_cert, crl_number)

    crl_builder.add_certificate(
        revoked_certificate.serial_number,
        datetime(base_year, 1, 2, 0, 0, 0, tzinfo=timezone.utc),
        'key_compromise')

    certificate_list = crl_builder.build(ca_private_key)
    dump_crl('client', certificate_list)