def parse_crls(crls: BinaryIO, store: X509Store) -> None: """ Parse CRLs from the ICAO PKD DSC-CRL ldif """ parser = LDIFRecordList(crls) parser.parse_entry_records() for record in parser.all_records: if "certificateRevocationList;binary" in record[1]: CRL = load_crl(FILETYPE_ASN1, record[1]["certificateRevocationList;binary"][0]) print(f"\t[+] Loaded CRL: {record[1]['cn'][0]}") store.add_crl(CRL)
def assertSignature( # pylint: disable=invalid-name self, chain: typing.Iterable[CertificateAuthority], cert: typing.Union[Certificate, CertificateAuthority], ) -> None: """Assert that `cert` is properly signed by `chain`. .. seealso:: http://stackoverflow.com/questions/30700348 """ store = X509Store() # set the time of the OpenSSL context - freezegun doesn't work, because timestamp comes from OpenSSL now = datetime.utcnow() store.set_time(now) for elem in chain: ca = load_certificate(FILETYPE_PEM, elem.pub.pem.encode()) store.add_cert(ca) # Verify that the CA itself is valid store_ctx = X509StoreContext(store, ca) self.assertIsNone(store_ctx.verify_certificate()) # type: ignore[func-returns-value] loaded_cert = load_certificate(FILETYPE_PEM, cert.pub.pem.encode()) store_ctx = X509StoreContext(store, loaded_cert) self.assertIsNone(store_ctx.verify_certificate()) # type: ignore[func-returns-value]
def ccStore(rootCerts, trustedCerts, crlList): try: store = X509Store() i = 0 for root in rootCerts: store.add_cert(root) i += 1 # print("Root Certificates Added to the X509 Store Context description : {:d}".format(i)) i = 0 for trusted in trustedCerts: store.add_cert(trusted) i += 1 # print("Trusted Authentication Certificates Added to the X509 Store Context description : {:d}".format(i)) i = 0 for crl in crlList: store.add_crl(crl) i += 1 # print("Certificates Revocation Lists Added to the X509 Store Context description : {:d}".format(i)) store.set_flags(X509StoreFlags.CRL_CHECK | X509StoreFlags.IGNORE_CRITICAL) except X509StoreContext: print("Store Context description failed") return None else: return store
def verify_chain(chain_path, cert_bytes_or_path): try: # If certificate bytes are passed load the certificate cert = load_certificate(FILETYPE_PEM, cert_bytes_or_path) except: # If certificate path is passed open the certificate and load it's bytes cert = load_certificate(FILETYPE_PEM, open(cert_bytes_or_path, 'rb').read()) chain_bytes = open(chain_path, 'rb').read() parts = chain_bytes.split(b'-----\n-----') n_certs = len(parts) store = X509Store() if n_certs == 1: store.add_cert(load_certificate(FILETYPE_PEM, parts[0])) else: cert_list = [] store.add_cert(load_certificate(FILETYPE_PEM, (parts[0] + b'-----\n'))) store.add_cert(load_certificate(FILETYPE_PEM, (b'-----' + parts[-1]))) for i in parts[1:-1]: store.add_cert( load_certificate(FILETYPE_PEM, (b'-----' + i + b'-----\n'))) store_ctx = X509StoreContext(store, cert) try: if store_ctx.verify_certificate() == None: return True except: return False
def __init__(self): self.roots = None self.root_store = X509Store() self.root_certs = [] self.root_fprints = set() # sha256 root fingerprints self.trace_logger = Tracelogger(logger)
def validate_certificate(self, certificate: str, chain: str, crl: str = None) -> None: """ Tests if a certificate has been signed by the chain, is not revoked and has not yet been expired. :param certificate: the certificate to test as string :param chain: the certificate chain file content as string :param crl: the certificate revocation list file content as string :raises: InvalidCertificateException if the certificate is invalid :return: None """ # root and intermediary certificate need to be split cas = pem.parse(chain.encode()) store = X509Store() for ca in cas: store.add_cert(self._to_cert(str(ca))) cert = self._to_cert(certificate) if crl: parsed_crl = load_crl(FILETYPE_PEM, crl) store.set_flags(X509StoreFlags.CRL_CHECK) store.add_crl(parsed_crl) ctx = X509StoreContext(store, cert) err_msg = 'Certificate is invalid' try: result = ctx.verify_certificate() if result is not None: raise InvalidCertificateException(err_msg) except Exception as e: raise InvalidCertificateException('%s: %s' % (err_msg, str(e)))
def assertSignature(self, chain, cert): # see: http://stackoverflow.com/questions/30700348 store = X509Store() for elem in chain: store.add_cert(load_certificate(FILETYPE_PEM, elem.dump_certificate())) cert = load_certificate(FILETYPE_PEM, cert.dump_certificate()) store_ctx = X509StoreContext(store, cert) self.assertIsNone(store_ctx.verify_certificate())
def _new_ossl_store(self): """ Creates a new root store for cert verification :return: """ cur_store = X509Store() for crt in self.root_certs: cur_store.add_cert(crt) return cur_store
def new_store(self): """ Creates a new store # define X509_V_FLAG_NO_CHECK_TIME 0x200000 :return: """ store = X509Store() store.set_flags(0x200000) return store
def verify_key_chain(peer_cert): root_cert = Encrypt.get_root_cert() root_cert = crypto.X509.from_cryptography(root_cert) peer_cert = crypto.X509.from_cryptography(peer_cert) store = X509Store() store.add_cert(root_cert) store_ctx = X509StoreContext(store, peer_cert) store_ctx.verify_certificate()
def submitProxy(): """ Submit a proxy certificate of a user. This operation requires user to provide personal certificate as client certificate in request. Proxy certificate that is to be submitted should be provided as raw data in request body. Function first verifies user's personal certificate against a CA certificate. If verification is successful, it procedes to read proxy certificate in body and insert it to database. Returns: status 200: A string with ID of a proxy certificate. status 401 or 500: A string with error message. """ # The following validation procedure is done as per: # https://stackoverflow.com/questions/30700348/how-to-validate-verify-an-x509-certificate-chain-of-trust-in-python # user pem is client certificate in header user_pem = getCertString() if not user_pem: return 'Wrong or no client certificate', 401 # get pem for CA caPath = os.path.join(os.environ['PATH'].split(':')[-1], 'ca.pem') try: caFile = open(caPath, 'r') # TODO: ca.pem in bin directory except Exception as e: return 'Server error: {}'.format(str(e)), 500 else: root_pem = caFile.read() caFile.close() # verify root_cert = load_certificate(FILETYPE_PEM, root_pem) user_cert = load_certificate(FILETYPE_PEM, user_pem) store = X509Store() store.add_cert(root_cert) store_ctx = X509StoreContext(store, user_cert) try: store_ctx.verify_certificate() except Exception as e: return 'Client certificate verification failed', 401 pmgr = proxymgr.ProxyManager() # TODO: handle error with pmgr and jmgr try: # TODO: ARC API does not fail when given genproxy script as proxy!!!! proxyStr = request.get_data() dn, exp_time = pmgr.readProxyString(proxyStr) proxyid = pmgr.actproxy.updateProxy(proxyStr, dn, '', exp_time) except Exception as e: return 'Server error: {}'.format(str(e)), 500 else: return json.dumps(proxyid)
def verify_against_ca(self): if not hasattr(self, '_trusted_ca'): raise VerificationError(str(self), 'did not load trusted CA') store = X509Store() store.add_cert(self._trusted_ca._x509) store_ctx = X509StoreContext(store, self._x509) try: store_ctx.verify_certificate() except X509StoreContextError as e: # [20, 0, 'unable to get local issuer certificate'] raise VerificationError(str(self), *e.args)
def extractcertchains(self, timestamp): store = X509Store() for cert in self.certificates.values(): cert_X509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, ssl.DER_cert_to_PEM_cert(der_encoder.encode(cert))) OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert_X509) fw = open(cert_X509.digest('sha1').decode('UTF-8').replace(':', ''), 'wb') fw.write(OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert_X509)) fw.close() pass
def verify_certs(certs, ca_certs): # Initialize trust store with CA certificates store = X509Store() for cert in ca_certs: store.add_cert(cert) # Incrementally build up trust by first checking intermedaries for cert in reversed(certs): store_ctx = X509StoreContext(store, cert) store_ctx.verify_certificate() # Add intermediary to trust store.add_cert(cert)
def validate_chain(self, file_names, last_cert): store = X509Store() for cert_file in file_names: with open(cert_file, 'rb') as f: cert = load_certificate(FILETYPE_PEM, f.read()) store.add_cert(cert) store_ctx = X509StoreContext(store, load_certificate(FILETYPE_PEM, last_cert)) result = store_ctx.verify_certificate() if result is None: return True else: return False
def get_cert_store(self): """ Get the certificate store for the context. :return: A X509Store object or None if it does not have one. """ store = _lib.SSL_CTX_get_cert_store(self._context) if store == _ffi.NULL: # TODO: This is untested. return None pystore = X509Store.__new__(X509Store) pystore._store = store return pystore
def parse_csca_certs(master_list: BinaryIO, store: X509Store) -> None: """ Parse CSCA certificates from the ICAO PKD ML ldif """ parser = LDIFRecordList(master_list) parser.parse_entry_records() unique_certs: List[X509] = [] for record in parser.all_records: if "CscaMasterListData" not in record[1]: continue print(f"\t[i] Reading {record[1]['cn'][0]}") cmd = "openssl cms -inform der -noverify -verify" (signed_data, err) = execute(cmd, record[1]["CscaMasterListData"][0]) if err.decode("utf8").strip() != "Verification successful": # print(f"\t[-] [{err.decode('utf8')}]") print("\t[-] Verification of Masterlist data failed\n") continue print("\t[+] MasterList Verification successful") cert_list = extract_certificates(signed_data) print("\t[i] Removing duplicates") unique_certs_from_ml = [x for x in cert_list if unique_hash(x)] print(f"\t[i] Removed {len(cert_list)-len(unique_certs_from_ml)} duplicate certificates\n") unique_certs = unique_certs + unique_certs_from_ml print(f"\t[i] Total unique entries: {len(unique_certs)}\n") for cert in unique_certs: if is_self_signed(cert): print(f"\t[+] Loaded certificate: {cert.get_subject().countryName}") print_valid_time("\t\t", cert) store.add_cert(cert)
def cc_store(self): rootCerts, trustedCerts, crlList = self.load_ca() try: cc_store = X509Store() for root in rootCerts: cc_store.add_cert(root) for trusted in trustedCerts: cc_store.add_cert(trusted) for crl in crlList: cc_store.add_crl(crl) cc_store.set_flags(X509StoreFlags.CRL_CHECK | X509StoreFlags.IGNORE_CRITICAL) return cc_store except X509StoreContext: print("Store Context description failed") return None
def is_self_signed(cert: X509) -> bool: """ Checks if a X509 certificate is self signed. """ store = X509Store() store.add_cert(cert) validfrom_time = cert.get_notBefore() validfrom_datetime = datetime.strptime(validfrom_time.decode("utf-8"), "%Y%m%d%H%M%SZ") store.set_time(validfrom_datetime) store_ctx = X509StoreContext(store, cert) try: store_ctx.verify_certificate() return True except X509StoreContextError: return False
def validate_cert(chain, leaf): from datetime import timedelta from OpenSSL.crypto import X509, X509Store, X509StoreContext, X509StoreContextError store = X509Store() store.set_time(leaf.not_valid_before + timedelta(days=1)) for c in chain: store.add_cert(X509.from_cryptography(c)) x509_leaf = X509.from_cryptography(leaf) ctx = X509StoreContext(store, x509_leaf) try: ctx.verify_certificate() except X509StoreContextError as e: return False return True
def verify_certificate(self, crt=None, cacrt=None): try: cert = load_certificate(FILETYPE_PEM, crt) intermediate_cert = load_certificate(FILETYPE_PEM, cacrt) validation_cert = load_certificate(FILETYPE_PEM, cacrt) store = X509Store() store.add_cert(intermediate_cert) store.add_cert(cert) store_ctx = X509StoreContext(store, validation_cert) if (store_ctx.verify_certificate() == None): print "Certificate verification Passed on Client side" return True else: raise Exception( "Certificate Verification Failed on Client side") except Exception as e: raise Exception("Certificate Validation Failed on Client side", e)
def estissuer_create(spec, patch, body, **_): """validate and mark issuers as ready""" # Secret must exist and be the correct type secret = get_secret_from_resource(body) if secret is None: raise kopf.TemporaryError(f"{spec['secretName']} not found") baseUrl = f"https://{spec['host']}:{spec.get('port', 443)}" path = "/".join( i for i in [WELLKNOWN, spec.get("label"), "cacerts"] if i is not None) # fetch /cacerts using explicit TA cacert = base64.b64decode(spec["cacert"]) with tempfile.NamedTemporaryFile(suffix=".pem") as cafile: cafile.write(cacert) cafile.seek(0) session = requests.Session() session.mount(baseUrl, SSLContextAdapter()) try: response = session.get(baseUrl + path, verify=cafile.name) except ( requests.exceptions.SSLError, requests.exceptions.RequestException, ) as err: patch.metadata.annotations["estoperator-perm-fail"] = "yes" raise kopf.PermanentError(err) from err # 200 OK is good, anything else is an error if response.status_code != 200: raise kopf.TemporaryError( f"Unexpected response: {response.status}, {response.reason}", ) # configured cacert must be in EST portal bundle explicit = pem.parse(cacert) store = X509Store() for cert in explicit: store.add_cert(load_certificate(FILETYPE_PEM, cert.as_text())) try: for leaf in pkcs7.load_der_pkcs7_certificates( base64.b64decode(response.content)): context = X509StoreContext( store, load_certificate(FILETYPE_PEM, leaf.public_bytes(Encoding.PEM)), ) context.verify_certificate() except X509StoreContextError as err: raise kopf.PermanentError( f"Unable to verify /cacerts content: {err}") from err return {"Ready": "True"}
def _verify_report(as_root_ca_cert_path: str, enclave_info_path: str, cert: Dict[str, Any], endpoint_name: str): if os.environ.get('SGX_MODE') == 'SW': return cert = x509.load_der_x509_certificate(cert, default_backend()) ext = json.loads(cert.extensions[0].value.value) # print("ext = ", ext) report = bytes(ext["report"]) signature = bytes(ext["signature"]) signing_cert = bytes(ext["signing_cert"]) signing_cert = load_certificate(FILETYPE_ASN1, signing_cert) # verify signing cert with AS root cert with open(as_root_ca_cert_path) as f: as_root_ca_cert = f.read() as_root_ca_cert = load_certificate(FILETYPE_PEM, as_root_ca_cert) store = X509Store() store.add_cert(as_root_ca_cert) store.add_cert(signing_cert) store_ctx = X509StoreContext(store, as_root_ca_cert) store_ctx.verify_certificate() # verify report's signature crypto.verify(signing_cert, signature, bytes(ext["report"]), 'sha256') report = json.loads(report) quote = report['isvEnclaveQuoteBody'] quote = base64.b64decode(quote) # get mr_enclave and mr_signer from the quote mr_enclave = quote[112:112 + 32].hex() mr_signer = quote[176:176 + 32].hex() # get enclave_info enclave_info = toml.load(enclave_info_path) # verify mr_enclave and mr_signer enclave_name = "teaclave_" + endpoint_name + "_service" if mr_enclave != enclave_info[enclave_name]["mr_enclave"]: raise Exception("mr_enclave error") if mr_signer != enclave_info[enclave_name]["mr_signer"]: raise Exception("mr_signer error")
def assertSignature(self, chain, cert): # see: http://stackoverflow.com/questions/30700348 store = X509Store() # set the time of the OpenSSL context - freezegun doesn't work, because timestamp comes from OpenSSL now = datetime.utcnow() store.set_time(now) for elem in chain: ca = load_certificate(FILETYPE_PEM, elem.dump_certificate()) store.add_cert(ca) # Verify that the CA itself is valid store_ctx = X509StoreContext(store, ca) self.assertIsNone(store_ctx.verify_certificate()) cert = load_certificate(FILETYPE_PEM, cert.dump_certificate()) store_ctx = X509StoreContext(store, cert) self.assertIsNone(store_ctx.verify_certificate())
def check_certificates_on_disk(self): """ this function checks certificates stored on disk """ self.log.info('reading certificates') with open(self.ca_path, 'r') as f: ca_certificate = load_certificate(FILETYPE_PEM, f.read()) with open(self.clientcert_path, 'r') as f: client_certificate = load_certificate(FILETYPE_PEM, f.read()) store = X509Store() store.add_cert(ca_certificate) now = datetime.utcnow().replace(tzinfo=pytz.UTC) client_cert_notafter_date = (datetime.strptime( client_certificate.get_notAfter().decode('utf-8'), "%Y%m%d%H%M%SZ").replace(tzinfo=pytz.UTC)) ca_notafter_date = (datetime.strptime( ca_certificate.get_notAfter().decode('utf-8'), "%Y%m%d%H%M%SZ").replace(tzinfo=pytz.UTC)) return ((client_cert_notafter_date - now).days, (ca_notafter_date - now).days)
def verify(cert_path, ca_path, fqdn=False, port=443): """ Verify a couple of certificate and CA """ if fqdn: st_cert = get_server_certificate((cert_path, port)) else: st_cert = open(cert_path, "rt").read() st_ca = open(ca_path, "rt").read() cert = load_certificate(FILETYPE_PEM, st_cert) ca_cert = load_certificate(FILETYPE_PEM, st_ca) store = X509Store() store.add_cert(ca_cert) store_ctx = X509StoreContext(store, cert) try: if store_ctx.verify_certificate() is None: print( color_message("Verification successful !", "green", bold=True)) except X509StoreContextError as error: print( color_message("Verification error: ", "red", bold=True) + str(error))
def build_store(CSCA_certs_dir: Path, crls_dir: Path, ml_dir: Path, dsccrl_dir: Path) -> X509Store: """ Add CSCA certificates and CRLs into the store """ if "store" in build_store.__dict__: return build_store.store else: build_store.store = X509Store() # Add CA certificates to the store # https://www2.politsei.ee/en/nouanded/isikut-toendavad-dokumendid/cert.dot print("[↳] Loading up CSCA certificates") # Load individual CSCA certificates for file in os.listdir(CSCA_certs_dir): with open(os.path.join(CSCA_certs_dir, file), "rb") as infile: cert = infile.read() if not cert.startswith(b"-----BEGIN CERTIFICATE-----"): try: CSCA = load_certificate(FILETYPE_ASN1, cert) except: print( f"\t[-] Error while reading {os.path.join(CSCA_certs_dir, file)}, skipping..." ) continue if is_self_signed(CSCA): build_store.store.add_cert(CSCA) print( f"\t[+] Loaded certificate: {CSCA.get_subject().countryName}" ) print_valid_time("\t\t", CSCA) continue for onecert in cert.split(b"-----END CERTIFICATE-----"): onecert = onecert.strip() if not onecert.startswith(b"-----BEGIN CERTIFICATE-----"): continue try: CSCA = load_certificate( FILETYPE_PEM, onecert + b"\n-----END CERTIFICATE-----") except: print( f"\t[-] Error while reading {os.path.join(CSCA_certs_dir, file)}, skipping..." ) continue if is_self_signed(CSCA): build_store.store.add_cert(CSCA) print( f"\t[+] Loaded certificate: {CSCA.get_subject().countryName}" ) print_valid_time("\t\t", CSCA) # Load CSCA certificates from ICAO PKD ML ldif ml_items = os.listdir(ml_dir) latest_ml = max(ml_items) with open(os.path.join(ml_dir, latest_ml), "rb") as infile: parse_csca_certs(infile, build_store.store) print("[↳] Loading up CRLs") # Load individual CRLs for file in os.listdir(crls_dir): with open(os.path.join(crls_dir, file), "rb") as infile: try: CRL = load_crl(FILETYPE_ASN1, infile.read()) except: print( f"\t[-] Error while reading {os.path.join(crls_dir, file)}, skipping..." ) continue build_store.store.add_crl(CRL) print(f"\t[+] Loaded CRL: {file}") # Load CRLs from ICAO PKD DSC-CRL ldif dsccrl_items = os.listdir(dsccrl_dir) latest_dsccrl = max(dsccrl_items) with open(os.path.join(dsccrl_dir, latest_dsccrl), "rb") as infile: parse_crls(infile, build_store.store) # store.set_flags(X509StoreFlags.CRL_CHECK | X509StoreFlags.CRL_CHECK_ALL) # some countries don't have CRL in ICAO PKD build_store.store.set_flags(X509StoreFlags.CRL_CHECK_ALL) return build_store.store
#!/usr/bin/env python3 """Small test script for CDS verification""" from OpenSSL.crypto import ( load_certificate, FILETYPE_ASN1, FILETYPE_PEM, X509Store, X509StoreContext, ) store = X509Store() certs = { "csca_Estonia_2007.cer": FILETYPE_PEM, "csca_Estonia_2007-2009-link.cer": FILETYPE_PEM, "csca_Estonia_2009.crt": FILETYPE_ASN1, "csca_Estonia_2009-2012-link.cer": FILETYPE_PEM, "csca_Estonia_2012.cer": FILETYPE_ASN1, "csca_Estonia_2012-2015-link.crt": FILETYPE_ASN1, "csca_Estonia_2015.cer": FILETYPE_ASN1, "csca_Estonia_2015-2016-link.crt": FILETYPE_ASN1, "csca_Estonia_2016.cer": FILETYPE_ASN1, "csca_Estonia_2016-2019-link.crt": FILETYPE_ASN1, "csca_Estonia_2019.cer": FILETYPE_ASN1, "csca_Estonia_2019-2020-link.der": FILETYPE_ASN1, "csca_Estonia_2020.der": FILETYPE_ASN1, } for fn, ft in certs.items(): with open("CSCA_certs/" + fn, "rb") as infile: CSCA = load_certificate(ft, infile.read())
def validate_certificate_chain( *, x5c: List[bytes], pem_root_certs_bytes: Optional[List[bytes]] = None, ) -> bool: """Validate that the certificates in x5c chain back to a known root certificate Args: `x5c`: X5C certificates from a registration response's attestation statement (optional) `pem_root_certs_bytes`: Any additional (PEM-formatted) root certificates that may complete the certificate chain Raises: `helpers.exceptions.InvalidCertificateChain` if chain cannot be validated """ if pem_root_certs_bytes is None or len(pem_root_certs_bytes) < 1: # We have no root certs to chain back to, so just pass on validation return True # Make sure we have at least one certificate to try and link back to a root cert if len(x5c) < 1: raise InvalidCertificateChain("x5c was empty") # Prepare leaf cert try: leaf_cert_bytes = x5c[0] leaf_cert_crypto = load_der_x509_certificate(leaf_cert_bytes, default_backend()) leaf_cert = X509().from_cryptography(leaf_cert_crypto) except Exception as err: raise InvalidCertificateChain(f"Could not prepare leaf cert: {err}") # Prepare any intermediate certs try: # May be an empty array, that's fine intermediate_certs_bytes = x5c[1:] intermediate_certs_crypto = [ load_der_x509_certificate(cert, default_backend()) for cert in intermediate_certs_bytes ] intermediate_certs = [ X509().from_cryptography(cert) for cert in intermediate_certs_crypto ] except Exception as err: raise InvalidCertificateChain( f"Could not prepare intermediate certs: {err}") # Prepare a collection of possible root certificates root_certs_store = X509Store() try: for cert in pem_root_certs_bytes: root_certs_store.add_cert(pem_cert_bytes_to_open_ssl_x509(cert)) except Exception as err: raise InvalidCertificateChain(f"Could not prepare root certs: {err}") # Load certs into a "context" for validation context = X509StoreContext( store=root_certs_store, certificate=leaf_cert, chain=intermediate_certs, ) # Validate the chain (will raise if it can't) try: context.verify_certificate() except X509StoreContextError: raise InvalidCertificateChain( "Certificate chain could not be validated") return True