# Path: nassl/ocsp_response.py
# def verify_ocsp_response(ocsp_response: _nassl.OCSP_RESPONSE, trust_store_path: Path) -> None:
#     """Verify that the OCSP response is trusted.
# 
#     Args:
#         ocsp_response: The OCSP response to verify.
#         trust_store_path: The file path to a trust store containing pem-formatted certificates, to be used for
#         validating the OCSP response.
# 
#     Raises OcspResponseNotTrustedError if the validation failed ie. the OCSP response is not trusted.
#     """
#     # Ensure that the trust store file exists
#     with trust_store_path.open():
#         pass
# 
#     try:
#         ocsp_response.basic_verify(str(trust_store_path))
#     except _nassl.OpenSSLError as e:
#         if "certificate verify error" in str(e):
#             raise OcspResponseNotTrustedError(
#                 "OCSP Response verification failed: the response is not trusted", trust_store_path
#             )
#         raise
# 
# Path: nassl/ssl_client.py
# class OpenSslVersionEnum(IntEnum):
#     """SSL version constants."""
# 
#     SSLV23 = 0
#     SSLV2 = 1
#     SSLV3 = 2
#     TLSV1 = 3
#     TLSV1_1 = 4
#     TLSV1_2 = 5
#     TLSV1_3 = 6
# 
# class SslClient(BaseSslClient):
#     """High level API implementing an SSL client.
# 
#     Hostname validation is NOT performed by the SslClient and MUST be implemented at the end of the SSL handshake on the
#     server's certificate.
#     """
# 
#     # The default client uses the modern OpenSSL
#     _NASSL_MODULE = _nassl
# 
#     def write_early_data(self, data: bytes) -> int:
#         """Returns the number of (encrypted) bytes sent."""
#         if self._is_handshake_completed:
#             raise IOError("SSL Handshake was completed; cannot send early data.")
# 
#         # Pass the cleartext data to the SSL engine
#         self._ssl.write_early_data(data)
# 
#         # Recover the corresponding encrypted data
#         final_length = self._flush_ssl_engine()
#         return final_length
# 
#     def get_early_data_status(self) -> OpenSslEarlyDataStatusEnum:
#         return OpenSslEarlyDataStatusEnum(self._ssl.get_early_data_status())
# 
#     def set_ciphersuites(self, cipher_suites: str) -> None:
#         """https://github.com/openssl/openssl/pull/5392
#         ."""
#         # TODO(AD): Eventually merge this method with get/set_cipher_list()
#         self._ssl.set_ciphersuites(cipher_suites)
# 
#     def set_groups(self, supported_groups: List[OpenSslEcNidEnum]) -> None:
#         """Specify elliptic curves or DH groups that are supported by the client in descending order."""
#         self._ssl.set1_groups(supported_groups)
# 
#     def get_verified_chain(self) -> List[str]:
#         """Returns the verified PEM-formatted certificate chain.
# 
#         If certificate validation failed, CertificateChainValidationFailed will be raised.
#         The leaf certificate is at index 0.
#         Each certificate can be parsed using the cryptography module at https://github.com/pyca/cryptography.
#         """
#         verify_code = self._ssl.get_verify_result()
#         if verify_code != 0:  # X509_V_OK
#             raise CertificateChainVerificationFailed(verify_code)
# 
#         return [x509.as_pem() for x509 in self._ssl.get0_verified_chain()]
# 
# class OpenSslVerifyEnum(IntEnum):
#     """SSL validation options which map to the SSL_VERIFY_XXX OpenSSL constants."""
# 
#     NONE = 0
#     PEER = 1
#     FAIL_IF_NO_PEER_CERT = 2
#     CLIENT_ONCE = 4


from pathlib import Path
from nassl.ocsp_response import verify_ocsp_response
from nassl.ssl_client import OpenSslVersionEnum, SslClient, OpenSslVerifyEnum
import socket

ssl_client = SslClient(
    ssl_version=OpenSslVersionEnum.TLSV1_2,
    underlying_socket=sock,
    ssl_verify=OpenSslVerifyEnum.PEER,
    ssl_verify_locations=mozilla_store,
)
ssl_client.set_tlsext_status_ocsp()
ssl_client.do_handshake()

print("Received certificate chain")
for pem_cert in ssl_client.get_received_chain():
    print(pem_cert)

print("Verified certificate chain")
for pem_cert in ssl_client.get_verified_chain():
    print(pem_cert)

ocsp_resp = ssl_client.get_tlsext_status_ocsp_resp()
if ocsp_resp:
    print("OCSP Stapling")
    verify_ocsp_response(ocsp_resp, Path(mozilla_store))

print("\nCipher suite")
print(ssl_client.get_current_cipher_name())

print("\nEphemeral Key")
print(ssl_client.get_ephemeral_key())

print("\nHTTP response")

# Path: nassl/ocsp_response.py
# def verify_ocsp_response(ocsp_response: _nassl.OCSP_RESPONSE, trust_store_path: Path) -> None:
#     """Verify that the OCSP response is trusted.
# 
#     Args:
#         ocsp_response: The OCSP response to verify.
#         trust_store_path: The file path to a trust store containing pem-formatted certificates, to be used for
#         validating the OCSP response.
# 
#     Raises OcspResponseNotTrustedError if the validation failed ie. the OCSP response is not trusted.
#     """
#     # Ensure that the trust store file exists
#     with trust_store_path.open():
#         pass
# 
#     try:
#         ocsp_response.basic_verify(str(trust_store_path))
#     except _nassl.OpenSSLError as e:
#         if "certificate verify error" in str(e):
#             raise OcspResponseNotTrustedError(
#                 "OCSP Response verification failed: the response is not trusted", trust_store_path
#             )
#         raise
# 
# Path: nassl/ssl_client.py
# class OpenSslVersionEnum(IntEnum):
#     """SSL version constants."""
# 
#     SSLV23 = 0
#     SSLV2 = 1
#     SSLV3 = 2
#     TLSV1 = 3
#     TLSV1_1 = 4
#     TLSV1_2 = 5
#     TLSV1_3 = 6
# 
# class SslClient(BaseSslClient):
#     """High level API implementing an SSL client.
# 
#     Hostname validation is NOT performed by the SslClient and MUST be implemented at the end of the SSL handshake on the
#     server's certificate.
#     """
# 
#     # The default client uses the modern OpenSSL
#     _NASSL_MODULE = _nassl
# 
#     def write_early_data(self, data: bytes) -> int:
#         """Returns the number of (encrypted) bytes sent."""
#         if self._is_handshake_completed:
#             raise IOError("SSL Handshake was completed; cannot send early data.")
# 
#         # Pass the cleartext data to the SSL engine
#         self._ssl.write_early_data(data)
# 
#         # Recover the corresponding encrypted data
#         final_length = self._flush_ssl_engine()
#         return final_length
# 
#     def get_early_data_status(self) -> OpenSslEarlyDataStatusEnum:
#         return OpenSslEarlyDataStatusEnum(self._ssl.get_early_data_status())
# 
#     def set_ciphersuites(self, cipher_suites: str) -> None:
#         """https://github.com/openssl/openssl/pull/5392
#         ."""
#         # TODO(AD): Eventually merge this method with get/set_cipher_list()
#         self._ssl.set_ciphersuites(cipher_suites)
# 
#     def set_groups(self, supported_groups: List[OpenSslEcNidEnum]) -> None:
#         """Specify elliptic curves or DH groups that are supported by the client in descending order."""
#         self._ssl.set1_groups(supported_groups)
# 
#     def get_verified_chain(self) -> List[str]:
#         """Returns the verified PEM-formatted certificate chain.
# 
#         If certificate validation failed, CertificateChainValidationFailed will be raised.
#         The leaf certificate is at index 0.
#         Each certificate can be parsed using the cryptography module at https://github.com/pyca/cryptography.
#         """
#         verify_code = self._ssl.get_verify_result()
#         if verify_code != 0:  # X509_V_OK
#             raise CertificateChainVerificationFailed(verify_code)
# 
#         return [x509.as_pem() for x509 in self._ssl.get0_verified_chain()]
# 
# class OpenSslVerifyEnum(IntEnum):
#     """SSL validation options which map to the SSL_VERIFY_XXX OpenSSL constants."""
# 
#     NONE = 0
#     PEER = 1
#     FAIL_IF_NO_PEER_CERT = 2
#     CLIENT_ONCE = 4


# Path: sample_client.py
from pathlib import Path
from nassl.ocsp_response import verify_ocsp_response
from nassl.ssl_client import OpenSslVersionEnum, SslClient, OpenSslVerifyEnum
import socket


ssl_client = SslClient(
    ssl_version=OpenSslVersionEnum.TLSV1_2,
    underlying_socket=sock,
    ssl_verify=OpenSslVerifyEnum.PEER,
    ssl_verify_locations=mozilla_store,
)
ssl_client.set_tlsext_status_ocsp()
ssl_client.do_handshake()

print("Received certificate chain")
for pem_cert in ssl_client.get_received_chain():
    print(pem_cert)

print("Verified certificate chain")
for pem_cert in ssl_client.get_verified_chain():
    print(pem_cert)

ocsp_resp = ssl_client.get_tlsext_status_ocsp_resp()
if ocsp_resp:
    print("OCSP Stapling")
    verify_ocsp_response(ocsp_resp, Path(mozilla_store))

print("\nCipher suite")
print(ssl_client.get_current_cipher_name())

print("\nEphemeral Key")
print(ssl_client.get_ephemeral_key())

print("\nHTTP response")

ssl_client.write(f"GET / HTTP/1.0\r\nUser-Agent: Test\r\nHost: {hostname}\r\n\r\n".encode("ascii"))