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 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)
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 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")
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 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)