├── ca ├── serial ├── intermediate │ ├── crlnumber │ ├── serial │ ├── index.txt.attr │ ├── index.txt │ ├── private │ │ ├── server.ed25519.key.pem │ │ ├── client.key.pem │ │ ├── server.key.pem │ │ ├── server.alt.key.pem │ │ └── intermediate.key.pem │ ├── csr │ │ ├── server.ed25519.csr.pem │ │ ├── client.csr.pem │ │ ├── server.csr.pem │ │ ├── server.alt.csr.pem │ │ └── intermediate.csr.pem │ ├── newcerts │ │ ├── 1002.pem │ │ ├── 1000.pem │ │ └── 1001.pem │ ├── certs │ │ ├── client.cert.cer │ │ ├── client.cert.pem │ │ ├── server.cert.cer │ │ ├── server.cert.pem │ │ ├── server.alt.cert.cer │ │ ├── server.alt.cert.pem │ │ ├── intermediate.cert.cer │ │ └── intermediate.cert.pem │ └── openssl.cfg ├── index.txt.attr ├── index.txt ├── newcerts │ └── 1000.pem ├── certs │ ├── ca.cert.cer │ └── ca.cert.pem ├── private │ └── ca.key.pem ├── openssl.cfg └── README.md ├── python ├── exercise3 │ ├── datatypes │ │ ├── __init__.py │ │ └── BankCustomer.py │ ├── SSLClient.py │ ├── SSLImposterServer.py │ └── SSLServer.py ├── resources │ ├── client │ │ ├── pinned.hash │ │ ├── client.key.pem │ │ ├── ca.cert.pem │ │ └── client.intermediate.chain.pem │ └── server │ │ ├── server.alt.key.pem │ │ ├── server.key.pem │ │ ├── ca.cert.pem │ │ ├── server.intermediate.chain.pem │ │ └── server.intermediate.alt.chain.pem ├── exercise1 │ ├── SSLClient.py │ └── SSLServer.py ├── exercise2 │ ├── SSLClient.py │ └── SSLServer.py └── README.md ├── glossary.pdf ├── java ├── src │ └── main │ │ ├── resources │ │ ├── client │ │ │ ├── pinned.hash │ │ │ ├── ClientKeyStore.jks │ │ │ └── ClientTrustStore.jks │ │ └── server │ │ │ ├── ServerKeyStore.jks │ │ │ ├── ServerAltKeyStore.jks │ │ │ └── ServerTrustStore.jks │ │ └── java │ │ └── com │ │ └── tlsexercises │ │ ├── exercise2 │ │ ├── SSLClient.java │ │ └── SSLServer.java │ │ ├── exercise1 │ │ ├── SSLClient.java │ │ └── SSLServer.java │ │ └── exercise3 │ │ ├── BankCustomer.java │ │ ├── SSLServer.java │ │ ├── SSLImposterServer.java │ │ └── SSLClient.java ├── pom.xml └── README.md ├── .gitignore ├── answers ├── python │ ├── exercise1 │ │ ├── SSLClient.py │ │ └── SSLServer.py │ ├── exercise2 │ │ ├── SSLClient.py │ │ └── SSLServer.py │ └── exercise3 │ │ └── SSLClient.py └── java │ ├── exercise2 │ ├── SSLClient.java │ └── SSLServer.java │ ├── exercise1 │ ├── SSLClient.java │ └── SSLServer.java │ └── exercise3 │ └── SSLClient.java ├── LICENSE.md ├── README.md └── glossary.tex /ca/serial: -------------------------------------------------------------------------------- 1 | 1001 2 | -------------------------------------------------------------------------------- /ca/intermediate/crlnumber: -------------------------------------------------------------------------------- 1 | 1000 -------------------------------------------------------------------------------- /ca/intermediate/serial: -------------------------------------------------------------------------------- 1 | 1003 2 | -------------------------------------------------------------------------------- /ca/index.txt.attr: -------------------------------------------------------------------------------- 1 | unique_subject = yes 2 | -------------------------------------------------------------------------------- /ca/intermediate/index.txt.attr: -------------------------------------------------------------------------------- 1 | unique_subject = yes 2 | -------------------------------------------------------------------------------- /python/exercise3/datatypes/__init__.py: -------------------------------------------------------------------------------- 1 | from .BankCustomer import BankCustomer -------------------------------------------------------------------------------- /glossary.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikepound/tls-exercises/HEAD/glossary.pdf -------------------------------------------------------------------------------- /ca/index.txt: -------------------------------------------------------------------------------- 1 | V 290424173429Z 1000 unknown /C=GB/ST=England/O=Expert TLS/OU=IT Training/CN=Expert TLS Int CA 2 | -------------------------------------------------------------------------------- /python/resources/client/pinned.hash: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikepound/tls-exercises/HEAD/python/resources/client/pinned.hash -------------------------------------------------------------------------------- /java/src/main/resources/client/pinned.hash: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikepound/tls-exercises/HEAD/java/src/main/resources/client/pinned.hash -------------------------------------------------------------------------------- /java/src/main/resources/client/ClientKeyStore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikepound/tls-exercises/HEAD/java/src/main/resources/client/ClientKeyStore.jks -------------------------------------------------------------------------------- /java/src/main/resources/server/ServerKeyStore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikepound/tls-exercises/HEAD/java/src/main/resources/server/ServerKeyStore.jks -------------------------------------------------------------------------------- /java/src/main/resources/client/ClientTrustStore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikepound/tls-exercises/HEAD/java/src/main/resources/client/ClientTrustStore.jks -------------------------------------------------------------------------------- /java/src/main/resources/server/ServerAltKeyStore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikepound/tls-exercises/HEAD/java/src/main/resources/server/ServerAltKeyStore.jks -------------------------------------------------------------------------------- /java/src/main/resources/server/ServerTrustStore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikepound/tls-exercises/HEAD/java/src/main/resources/server/ServerTrustStore.jks -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #### 2 | ## JAVA 3 | 4 | # Intellij 5 | java/.idea/ 6 | java/*.iml 7 | java/*.iws 8 | 9 | # Maven 10 | java/log/ 11 | java/target/ 12 | 13 | #### 14 | ## PYTHON 15 | 16 | # Pycharm 17 | python/.idea/ 18 | 19 | # Caching 20 | __pycache__/ 21 | 22 | #### 23 | ## CA 24 | *.old 25 | -------------------------------------------------------------------------------- /ca/intermediate/index.txt: -------------------------------------------------------------------------------- 1 | V 260816095146Z 1000 unknown /C=GB/ST=England/O=Expert TLS/OU=IT Training/CN=Expert TLS Server 2 | V 260816095221Z 1001 unknown /C=GB/ST=England/O=Expert TLS/OU=IT Training/CN=Expert TLS Imposter 3 | V 260816095241Z 1002 unknown /C=GB/ST=England/O=Expert TLS/OU=IT Training/CN=Expert TLS Client 4 | -------------------------------------------------------------------------------- /ca/intermediate/private/server.ed25519.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN ENCRYPTED PRIVATE KEY----- 2 | MIGbMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAgpmPlvnxM3BgICCAAw 3 | DAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEJ6ja5GL0a6bfQsbuyg4TOoEQOO5 4 | Q01MUXwiVMa2DPG8bmJ94tlaT88w3JpKZNclHW4bRQZCqz+qcov+iAiUKBYXljm/ 5 | c581uEyFqwtBAIn6/O8= 6 | -----END ENCRYPTED PRIVATE KEY----- 7 | -------------------------------------------------------------------------------- /ca/intermediate/csr/server.ed25519.csr.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIHpMIGcAgEAMGkxCzAJBgNVBAYTAkdCMRAwDgYDVQQIDAdFbmdsYW5kMRYwFAYD 3 | VQQKDA1FeHBlcnQgVExTIEVkMRQwEgYDVQQLDAtJVCBUcmFpbmluZzEaMBgGA1UE 4 | AwwRRXhwZXJ0IFRMUyBTZXJ2ZXIwKjAFBgMrZXADIQCAVqJgfZZ/egidbpCxOdRC 5 | j909oX/cPvV8g33fyLgCRaAAMAUGAytlcANBAE3DEVG0mrDqhRL1VER55bf4VVTr 6 | 5DxIZ3FXa5C4r3UCbol9e9zKOhf60a4Jmf4qpnAM2Dlkl1QER7VxykkwCA8= 7 | -----END CERTIFICATE REQUEST----- 8 | -------------------------------------------------------------------------------- /python/exercise3/datatypes/BankCustomer.py: -------------------------------------------------------------------------------- 1 | class BankCustomer: 2 | def __init__(self, id, name, email, accn, srtc, add1, add2, town, pc): 3 | self.id = id 4 | self.name = name 5 | self.emailAddress = email 6 | self.accountNumber = accn 7 | self.sortCode = srtc 8 | self.address1 = add1 9 | self.address2 = add2 10 | self.town = town 11 | self.postCode = pc 12 | 13 | def __eq__(self, other): 14 | return self.id == other.id 15 | 16 | def __hash__(self): 17 | return hash(self.id) 18 | 19 | def __repr__(self): 20 | return self.__str__() 21 | 22 | def __str__(self): 23 | format_string = "----------\n{0:d}\n{1}\nAccount: {2:d} ({3})\n{4}, {5}, {6}, {7}\n----------" 24 | strt = str(self.sortCode) 25 | strt = "{0}-{1}-{2}".format(strt[0:2],strt[2:4],strt[4:6]) 26 | return format_string.format(self.id, self.name, self.accountNumber, strt, 27 | self.address1, self.address2, self.town, self.postCode) 28 | -------------------------------------------------------------------------------- /ca/intermediate/csr/client.csr.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIICqzCCAZMCAQAwZjELMAkGA1UEBhMCR0IxEDAOBgNVBAgMB0VuZ2xhbmQxEzAR 3 | BgNVBAoMCkV4cGVydCBUTFMxFDASBgNVBAsMC0lUIFRyYWluaW5nMRowGAYDVQQD 4 | DBFFeHBlcnQgVExTIENsaWVudDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC 5 | ggEBANCZuZCWLjCW2jy/vPZZShnWKhRvsMIoKRPlcvBFJPQA9d4BHbfgHxCKvwSC 6 | liJh823aMtYT5utGQpASM9v6UDSaU3IdVA0qx4vIHbeY+gxL7HTWuM0T9omd//ly 7 | J7hSti16Fak3HbAEhmMgg1pLkNVSNkkT4Hv7UtWmnFecMn5wUnHbvzaX1OZUpR2M 8 | mUT+7Fh2qU/sfVJ0mf1yOS6x0IFxE5YEKBW1OX00BtypY3FmcCy7BFdWVvqjhLeT 9 | ZP4wylIM59tkrlwhb1/U0LFVf9G6bOanIrPxaiOvU9l1DxPDqgW+YQmfE4ACWLrD 10 | uexKTkj1s+GTCINDcl5ggt+3OHUCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQAe 11 | TBsqnkxFkVulIjo1DfHIradqh5Y/h7qraXrE+b14Yx/Veetmk+YSUtKJ3BWs0bgs 12 | 7o4x+E+2Ro58mUc0WElzsPPZdOr74CtHu0X/WpDhMXdZexDJYTSeCfPzsEHoq4zs 13 | RyAzQzVOXe+5mvfxTi8jbMO1eeDg009BLqnIF7Yv8J/Kio5xXIDZ68QialNnkAvO 14 | T0ioRlX9lpAEzUUIV4HHrRCNsd8+QROfYwyoyCqAVf7pmAKhadR/N4lEHmZe9nel 15 | 0BAmW9wsa3/Hul8npjxrjvSMQskj6XzDoZe7mi6eLDefSt4LokLIQiHlllFPnBQr 16 | rxQ49a9MLW3phqtcX3dH 17 | -----END CERTIFICATE REQUEST----- 18 | -------------------------------------------------------------------------------- /ca/intermediate/csr/server.csr.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIICqzCCAZMCAQAwZjELMAkGA1UEBhMCR0IxEDAOBgNVBAgMB0VuZ2xhbmQxEzAR 3 | BgNVBAoMCkV4cGVydCBUTFMxFDASBgNVBAsMC0lUIFRyYWluaW5nMRowGAYDVQQD 4 | DBFFeHBlcnQgVExTIFNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC 5 | ggEBAME3lIaJd9A2jcI29G9ECfNPbPre9ACpat4f0GB+DOdhJb81Z7MBne80aoaQ 6 | lHRm/UxII2jQolFuiwrsCyz/3X/mjtu+Wvk1nqmxFiqKT1jBiJ1mEcdIEpUIqShz 7 | teRCfYJM7BbcWI6X9pAOgVkVGlQyVE9GQqHa4Q0phyeuNZsSa0Xgn4Gzxq9/NbU3 8 | UA/NsoREmq+6ji2G6PQ/fo1fvtTT5nW6WN22UTaoi7nTWNvsY7+yKnved9kWY6w6 9 | dINEMo+UnxTgGKNs7L8uUYxVTYn+u6fGLV3iktFro2eIi1Fy8W4AhV3rSaCJh85e 10 | +rgMDLzVGY8g/PwpPrqLIO4plzMCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQBC 11 | r2B0zbWq74jQNnghOh/XIYueIYx5GYU0vrGsHIgCUGQ6UpPIpN9g/2Ej9yGC4MBG 12 | btgufdls6cuU3+lh8C/wehqf0A5gBkKEg3p3YJVTKsEMQcdy4jwBycZAutHoDv1c 13 | Ac8ZEJ2ZioPAExlkIpAAqf3sPjMkSwKoYjMl49YZu/uFrRJTViuRW09UQsgQPFvC 14 | 5QV/1olV0sT75/0lWpgcuEMOy5/XcVA26Rv1a8QxITw8GJT4CD4/2EtmmEbC85z3 15 | sD+X9w7qG0P/kU0aN2LilDJmnSbWMMnX8V9z/SCH5VcWYk4hl+9RjdZ8Nf4CJMDk 16 | aysnoc7fDySFe8qep/Dk 17 | -----END CERTIFICATE REQUEST----- 18 | -------------------------------------------------------------------------------- /ca/intermediate/csr/server.alt.csr.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIICrTCCAZUCAQAwaDELMAkGA1UEBhMCR0IxEDAOBgNVBAgMB0VuZ2xhbmQxEzAR 3 | BgNVBAoMCkV4cGVydCBUTFMxFDASBgNVBAsMC0lUIFRyYWluaW5nMRwwGgYDVQQD 4 | DBNFeHBlcnQgVExTIEltcG9zdGVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB 5 | CgKCAQEA2kaM7EtNcVvjoQZggDGVkri8PAZhWd9RNbKqwrF45eni76FzLdnBXfAr 6 | osdzF9R0dmtxcASR7bPcGdb8k1mVvgEckJjOGHiftZR+ylbIImpjjRKqa4iobI6l 7 | KerYGSqnDEMM8qvIBX8xnmZaT9KeI0LQ+lKZ+8ip2ddJM5ekrI4TGZK+98CG45+k 8 | Kpn4v4aHEwHR6slbWghT6GktocgqEolKbD6Ij5EQYXJYOiL0rwLrrVA2sKYj1Iqp 9 | Ue+rxm+QKawM9IPR2P994sPxPF2dJJ6i/IblHkZ7TRtref4Tnt5aemt8QxpVqLyt 10 | G5APG+lhV+Js6wBcc0nGuuJV66ccBQIDAQABoAAwDQYJKoZIhvcNAQELBQADggEB 11 | ALaZ/bQL422r9J1wgQiTfR9Ig9qdliV78W64DlVGktDRDgavJ/P6R1iJOH/XAhDb 12 | zOZA51NSXqusqHsC3Y3pOHaymcQCs1Ineh/dxlzSvzrw3luloiN1XvEZpgTKcVRD 13 | d0oxm4eXPHhZcwhWxhxV4XjiYSC3kqM5sIZKOE6FSAFa1qWCh/qt7YcToi76F7MS 14 | RCTRYXxqAFay+ISt7QLTqU/sMcD1DMlZIqnHdPDI2dJFqV2BIuyWkRGB4F4Qn2Ym 15 | CTYVkL0fqvf/VcpJqLfRMYiT/Tpg8BYIPmoTYb4GKEIersVHhHvlyEAiwvfvnOlQ 16 | Zmu3aXhgTJHBM11SqWUotOY= 17 | -----END CERTIFICATE REQUEST----- 18 | -------------------------------------------------------------------------------- /answers/python/exercise1/SSLClient.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import ssl 3 | from pathlib import Path 4 | 5 | 6 | LOCAL_HOST = 'localhost' 7 | LOCAL_PORT = 8282 8 | RESOURCE_DIRECTORY = Path(__file__).resolve().parent.parent / 'resources' / 'client' 9 | CA_CERT = RESOURCE_DIRECTORY / 'ca.cert.pem' 10 | 11 | 12 | def main(): 13 | """ 14 | Exercise 1 Client 15 | """ 16 | # Create a standard TCP Socket 17 | sock = socket.socket(socket.AF_INET) 18 | 19 | # Create SSL context which holds the parameters for any sessions 20 | context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH) 21 | context.load_verify_locations(CA_CERT) 22 | 23 | # Restrict available protocols and ciphers 24 | context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 | ssl.OP_NO_SSLv3 25 | context.set_ciphers('ALL:!DSS:!DHE:!aNULL:!eNull') 26 | 27 | # We can wrap in an SSL context first, then connect 28 | conn = context.wrap_socket(sock, server_hostname="Expert TLS Server") 29 | try: 30 | # Handshake - conn is an SSLSocket 31 | conn.connect((LOCAL_HOST, LOCAL_PORT)) 32 | 33 | # What parameters were established? 34 | print("Negotiated session using cipher suite: {0}\n".format(conn.cipher()[0])) 35 | 36 | # In python sockets send and receive bytes. Send some numbers: 37 | conn.send(bytes([2, 3, 5, 7, 11, 13, 17, 19, 23])) 38 | 39 | # Receive a number back from the server 40 | server_response = conn.recv(1024) 41 | 42 | # Server response is an int, convert it back 43 | print(int.from_bytes(server_response, 'big')) 44 | finally: 45 | conn.close() 46 | 47 | 48 | if __name__ == '__main__': 49 | main() 50 | -------------------------------------------------------------------------------- /python/exercise1/SSLClient.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import ssl 3 | from pathlib import Path 4 | 5 | 6 | LOCAL_HOST = 'localhost' 7 | LOCAL_PORT = 8282 8 | RESOURCE_DIRECTORY = Path(__file__).resolve().parent.parent / 'resources' / 'client' 9 | CA_CERT = RESOURCE_DIRECTORY / 'ca.cert.pem' 10 | 11 | 12 | def main(): 13 | """ 14 | Exercise 1 Client 15 | """ 16 | 17 | # Part 1 18 | # Add code here to create and configure an SSLContext, wrap a socket and connect using TLS 19 | # For help check out: 20 | # https://github.com/mikepound/tls-exercises/blob/master/python/README.md 21 | 22 | # Create a standard TCP Socket 23 | sock = None 24 | 25 | # Create SSL context which holds the parameters for any sessions 26 | context = None 27 | 28 | # We can wrap in an SSL context first, then connect 29 | conn = None 30 | try: 31 | # Connect using conn 32 | 33 | # The code below is complete, it will use a connection to send and receive from the server 34 | 35 | if conn is None: 36 | return 37 | 38 | # What parameters were established? 39 | print("Negotiated session using cipher suite: {0}\n".format(conn.cipher()[0])) 40 | 41 | # In python sockets send and receive bytes. Send some numbers: 42 | conn.send(bytes([2, 3, 5, 7, 11, 13, 17, 19, 23])) 43 | 44 | # Receive a number back from the server 45 | server_response = conn.recv(1024) 46 | 47 | # Server response is an int, convert it back 48 | print(int.from_bytes(server_response, 'big')) 49 | finally: 50 | if conn is not None: 51 | conn.close() 52 | 53 | 54 | if __name__ == '__main__': 55 | main() 56 | -------------------------------------------------------------------------------- /answers/python/exercise2/SSLClient.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import ssl 3 | from pathlib import Path 4 | 5 | 6 | LOCAL_HOST = 'localhost' 7 | LOCAL_PORT = 8383 8 | RESOURCE_DIRECTORY = Path(__file__).resolve().parent.parent / 'resources' / 'client' 9 | CLIENT_CERT_CHAIN = RESOURCE_DIRECTORY / 'client.intermediate.chain.pem' 10 | CLIENT_KEY = RESOURCE_DIRECTORY / 'client.key.pem' 11 | CA_CERT = RESOURCE_DIRECTORY / 'ca.cert.pem' 12 | 13 | 14 | def main(): 15 | """ 16 | Exercise 2 Client 17 | """ 18 | # Create a standard TCP Socket 19 | sock = socket.socket(socket.AF_INET) 20 | 21 | # Create SSL context which holds the parameters for any sessions 22 | context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH) 23 | context.load_verify_locations(CA_CERT) 24 | context.load_cert_chain(certfile=CLIENT_CERT_CHAIN, keyfile=CLIENT_KEY) 25 | 26 | # We can wrap in an SSL context first, then connect 27 | conn = context.wrap_socket(sock, server_hostname="Expert TLS Server") 28 | try: 29 | # Handshake - conn is an SSLSocket 30 | conn.connect((LOCAL_HOST, LOCAL_PORT)) 31 | 32 | # What parameters were established? 33 | print("Negotiated session using cipher suite: {0}\n".format(conn.cipher()[0])) 34 | 35 | # This time we are sending a string as bytes 36 | conn.send(b"GET /index.html HTTP/1.1\n") 37 | 38 | # Receive a binary string response 39 | server_response = conn.recv(1024) 40 | 41 | # Convert the response into a unicode string as that's what the server sent us 42 | print(server_response.decode("UTF-8")) 43 | finally: 44 | conn.close() 45 | 46 | 47 | if __name__ == '__main__': 48 | main() 49 | -------------------------------------------------------------------------------- /python/exercise2/SSLClient.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import ssl 3 | from pathlib import Path 4 | 5 | 6 | LOCAL_HOST = 'localhost' 7 | LOCAL_PORT = 8383 8 | RESOURCE_DIRECTORY = Path(__file__).resolve().parent.parent / 'resources' / 'client' 9 | CA_CERT = RESOURCE_DIRECTORY / 'ca.cert.pem' 10 | 11 | 12 | def main(): 13 | """ 14 | Exercise 2 Client 15 | """ 16 | # Create a standard TCP Socket 17 | sock = socket.socket(socket.AF_INET) 18 | 19 | # Create SSL context which holds the parameters for any sessions 20 | context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH) 21 | context.load_verify_locations(CA_CERT) 22 | 23 | # Part 2: Client 24 | # Since the server now requires a certificate, load the clients certificate and key here. 25 | # 26 | # For help check out: 27 | # https://github.com/mikepound/tls-exercises/blob/master/python/README.md 28 | 29 | # We can wrap in an SSL context first, then connect 30 | conn = context.wrap_socket(sock, server_hostname="Expert TLS Server") 31 | try: 32 | # Handshake - conn is an SSLSocket 33 | conn.connect((LOCAL_HOST, LOCAL_PORT)) 34 | 35 | # What parameters were established? 36 | print("Negotiated session using cipher suite: {0}\n".format(conn.cipher()[0])) 37 | 38 | # This time we are sending a string as bytes 39 | conn.send(b"GET /index.html HTTP/1.1\n") 40 | 41 | # Receive a binary string response 42 | server_response = conn.recv(1024) 43 | 44 | # Convert the response into a unicode string as that's what the server sent us 45 | print(server_response.decode("UTF-8")) 46 | finally: 47 | conn.close() 48 | 49 | 50 | if __name__ == '__main__': 51 | main() 52 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ## TLS Exercises License 2 | 3 | This work is licensed under a [Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International license](https://creativecommons.org/licenses/by-nc-nd/4.0/). 4 | 5 | 6 | ## TLS Exercises Copyright 7 | 8 | Copyright 2019 Michael Pound 9 | All rights reserved. 10 | 11 | Redistribution and use in source and binary forms, with or without modification, 12 | are permitted provided that the following conditions are met: 13 | 14 | * Redistributions of source code must retain the above copyright notice, this 15 | list of conditions and the following disclaimer. 16 | 17 | * Redistributions in binary form must reproduce the above copyright notice, 18 | this list of conditions and the following disclaimer in the documentation 19 | and/or other materials provided with the distribution. 20 | 21 | * Neither the name of the author nor the names of contributors may be used to 22 | endorse or promote products derived from this software without specific prior 23 | written permission. 24 | 25 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /python/resources/client/client.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEA0Jm5kJYuMJbaPL+89llKGdYqFG+wwigpE+Vy8EUk9AD13gEd 3 | t+AfEIq/BIKWImHzbdoy1hPm60ZCkBIz2/pQNJpTch1UDSrHi8gdt5j6DEvsdNa4 4 | zRP2iZ3/+XInuFK2LXoVqTcdsASGYyCDWkuQ1VI2SRPge/tS1aacV5wyfnBScdu/ 5 | NpfU5lSlHYyZRP7sWHapT+x9UnSZ/XI5LrHQgXETlgQoFbU5fTQG3KljcWZwLLsE 6 | V1ZW+qOEt5Nk/jDKUgzn22SuXCFvX9TQsVV/0bps5qcis/FqI69T2XUPE8OqBb5h 7 | CZ8TgAJYusO57EpOSPWz4ZMIg0NyXmCC37c4dQIDAQABAoIBAGVr2IUr/5kwPzt6 8 | He3Iy/Zz4lG9XDuKOy6pSJD5jVX1gZVHBaP5HCF21BjlRQnChhDLHhxn4MZTitlx 9 | gDVcJtLsldXN3KfqPMsBqTEy96Ay6eyE2aUcJ6oRX/twPU+pJ1pFGXMEkTKbgJuB 10 | m1uzkd+l8S7msyaUs1mdgDY4g3RlVw5jG8FegFdiUBeDK9YiBu24DWNnnqFe0Z0n 11 | 4aT8Zy4VgyYtPSWjzQIhMUw8pB5WhnQG7MMqf6ztBHmDeHGPLkpwZ/8kQlYRQY9A 12 | 8yxtIn1oGOXJIIFV64AuJiL+3WmcqLnppvuDW88l3Cf+pRkvXqRTEdzt3ZHQIp5T 13 | UXyVFwECgYEA9aieRNhq5m51e6eoL3X66pHmwXBgKZ56uB6Jf9L+Os+a3qWb/4XZ 14 | Gjt5BNIQjGdHkbE5OBIGlFa96dUX2HpbHl4eE+7WKLgi4Qu8nAbfzTdhhQQILiO/ 15 | CA/WjomvtFGd217uaSIXu9Up7NyNA6K/WxBU92urkkMar2g2FXbCat0CgYEA2WG+ 16 | My53eYIR4LBKUtpH1rbzsm85Azme2PgXlr16BtwXPcd2NSLowzv12sqIgwK1OtKN 17 | z4gpXczdj0NXu6aseUrnrIc6YGhiYAw3jTDqrvuzSZjylqPw+nwFMnAwTUHXgPTz 18 | DeiaPoQ0LUh/v+37XX/UK1TvJ5U2B899Z9GrLnkCgYAycx2Fv/g8OIUSDv1gOdd8 19 | 4tfD9CMbiPtk4oiUYq1pQIdqoBIoaMGMPJh+3/EcFH3DMuUwWatWPXYlFmkeQQqD 20 | cwq0R0Fd/WrUUse6N0Mw7uWtHoXbi+XIbxA+F5Ko8nX7vkQx/Rlorr88cJLZI0wv 21 | FGyOn2MN15AcY8dvowMMVQKBgQCxgyS7TM2ZdsK8lZkL0V3qk1mrszF+VbZGfUld 22 | +fpE0cNU2qXHvGsQysz4Tn1tZm+xyjCtcQY+p8WhcJ+bB/89yRIojAD6qyLyReez 23 | L2flXnrItdIbe2KUWWQxDPYUkJi3oM8941zZgkHNXK+dfmvOrU0H2YK18x29AQ3q 24 | EohUGQKBgQChTE6QcwOAshuuTjFiwMyGe2/QPccZotShY6ebRLbq31z/ylpCBgVU 25 | YGjEhEhyaWfUmBKFTZeFW1dJXpCHN4st7TX9wTwKHKIbyYH0AMPTMD9k7LDvRtnt 26 | rfCVz7sQEKi6PqelH/BZih9YkGmgjtccySWfufAxb86Xe45dkWMhLg== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /python/resources/server/server.alt.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEogIBAAKCAQEA2kaM7EtNcVvjoQZggDGVkri8PAZhWd9RNbKqwrF45eni76Fz 3 | LdnBXfArosdzF9R0dmtxcASR7bPcGdb8k1mVvgEckJjOGHiftZR+ylbIImpjjRKq 4 | a4iobI6lKerYGSqnDEMM8qvIBX8xnmZaT9KeI0LQ+lKZ+8ip2ddJM5ekrI4TGZK+ 5 | 98CG45+kKpn4v4aHEwHR6slbWghT6GktocgqEolKbD6Ij5EQYXJYOiL0rwLrrVA2 6 | sKYj1IqpUe+rxm+QKawM9IPR2P994sPxPF2dJJ6i/IblHkZ7TRtref4Tnt5aemt8 7 | QxpVqLytG5APG+lhV+Js6wBcc0nGuuJV66ccBQIDAQABAoIBAAppTxN+TAVaMrNd 8 | kIDM3KuQ8DmUvFQDGOaMzSRYPsIIs/BmLQ5E0rpeWFZ9WPoMAjobyd9j+Gn0KE17 9 | ObT1kvTrLKehAkOcjVGl8Z5JIWay2GjEOSjD7fSvoSUstH4O0MT+9cElfHb2qDE8 10 | BJbGHxDjgQBPrFScL63aXP1/ADXSwnoAEpI04ZBlkXHeJg37JA493qFAR7w75VL0 11 | 1EmVYIvzARcRwb9/I17sdyXc8pKbioD/t8Up74TdAzFK29d3Gl9L8uCFDusnn2i4 12 | y8ytXzm03sB2whznZwvLwHr/Uzp6nA/iLZGBFkyE4Kf4OEvEml71Isn36DIsIigf 13 | ZwRImQkCgYEA9LkDG3ct4ydlZerYCUPz0hEeNDS34vYKO0mVCVNRmaH3bn5IcNky 14 | DO8lrYXVkvSh8CU/kDSCkLRAdPFoplUr9Gvbu9WHY5zl8cDoSk1e0NVAXKTdt3aE 15 | mUVZELFVX194AAsU+XyEWeUmBtP8aInAFptxXiLARR0033XYwpo5pAsCgYEA5FWK 16 | 15BXXgVZDFcMdxaU/0D0FlS0McGLpRSUU5t4hN2wZvqq2OEMEN87TKnP4oBjgxp5 17 | FXXwasTaVUX9WMimOMfxOVVea+yeVTw2BSeR4ybnp6/Rli3wZxdq3pJMJUbygtmd 18 | zacVwP8cXiTINGl35grvr7HrEmqHMz8DbAjmui8CgYBeF5yYPNSJ2CXmb8sslNH0 19 | XNyOGg7x1sPMU9hXw49GUL3/39IegYP68SA9fY3GeQSifs/XtDjXRlbaH8+q1GiY 20 | C7hqmgj6ReMrdo5ZszHXfYbHmCQfXBRTkhRSlLxMdTqAWcJwwm1o2vAqA+uyjfQr 21 | PQzzsszWRgqEOJ1lBUNQTQKBgCx5UPLNxYalqgOSTPZBKsJRB3n2A6cRWL7NtFpY 22 | lO/kMkDMoExgATakFGvJQ5mNglR96om4kBxrvU8Qs9kANAgpQZ32N87zpp9Ze/gj 23 | DfJdmI972mnTBtk9oW46tqQoHoJIGsl8uur9hav8pBY5WMYw6SCimfPbVfwwUN1R 24 | Goe3AoGAIY4oE8BFqeGviHDPPPK0g7sd1oCV0boTEkeH4NMYBrQZzrum2MicahLQ 25 | 4b8yJTfbQhsipWO0hYnRffPtunoiWhsQsbwNLBhKIa19wdT64OcVYl+8hD9iK2XU 26 | yGooSkgH3Tg5TDkWGnWMK6CZG/MA3gHMOuNVfyWmhqFHRqerlio= 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /python/resources/server/server.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEogIBAAKCAQEAwTeUhol30DaNwjb0b0QJ809s+t70AKlq3h/QYH4M52ElvzVn 3 | swGd7zRqhpCUdGb9TEgjaNCiUW6LCuwLLP/df+aO275a+TWeqbEWKopPWMGInWYR 4 | x0gSlQipKHO15EJ9gkzsFtxYjpf2kA6BWRUaVDJUT0ZCodrhDSmHJ641mxJrReCf 5 | gbPGr381tTdQD82yhESar7qOLYbo9D9+jV++1NPmdbpY3bZRNqiLudNY2+xjv7Iq 6 | e9532RZjrDp0g0Qyj5SfFOAYo2zsvy5RjFVNif67p8YtXeKS0WujZ4iLUXLxbgCF 7 | XetJoImHzl76uAwMvNUZjyD8/Ck+uosg7imXMwIDAQABAoIBAAqSgfwClZ28/nC8 8 | FQ/phynbFLl9bZiDrKdO0lYVT5txg2E9CNmQoxWtpo6KZrUf1YhRAi8AC4GtLMqC 9 | M/JYZcRT10lK1yt/tZjPackWHFVc8Z67MQnYdbvV53uhKTi+MqPolZqCoA3dXs5v 10 | HMDFGNW2k0prK8YzddEEjrKrI5/Cf9x7uzxBgHvaYwkYAjDQ/R7ct7FAg/LbtHXu 11 | Qe/QX0bGOVChu6oTDA577yqjqml/YNUDzLcM7cGmP93YsxEXjgJvdeI249yer7ZG 12 | fEOn6WVu1iTEz+HaxmzgEPLtxYxZMU9Uc0I9ITWDm4vE/E4nIbUmP+1BXOyokOup 13 | 9SW5YRECgYEA7Sz4z2OYvxB4ZPSqtC7RsfZ1AUzbQNpMySpJ1YapnAvAxR6+sL2K 14 | ZdqkJkupqKcptPe/KeE4FN6xLiYCXnyNpQl2vhku494ihwshtHxidwtVNJ718yyZ 15 | HpqXb6CBRQxYSS0Y2MtPhdsBAbVScpRM79o86pMS0ZS5H1hyA9yx6g8CgYEA0I1w 16 | 5j+/mXFrH+NP+sRYPaxgeoxn2rgyCNPnGz4611EtZRkV6BqNbVIF/eAuwNP46iX+ 17 | liyYDSCoxwH3fEUP/uPRCrKI7/ymLfOSNvdg2ByzRD4k2Q5m/Smohl/kQoyVL0ih 18 | 0FxTRfBO6KilJ9OLuRBJSyWnf+1Bv/3OPYBeNJ0CgYBVvnVxHJOjN4QfE2kHXQnI 19 | ac5hGvUFHCa4b0ZkIJv+4yzc1sGfydZX/lRr19zNMSnd19dPf7GzsdKiWXFv0V2v 20 | 9ZztGtOd47fd1INp6bH7UaiLLpDCSjRNIRxwablySgU850XdUps8TDGv+WqGK+Eo 21 | sWBmeadLB5Zpo6MMjGPxtwKBgGIi3IiMYOWcmFMmDQGsmPVUgwXHwisK2AiNZkfM 22 | jbW6bkkPd96DeB+EJGulrXpxhMTx4g3aqCYtQx56T3H7sZ44p6qH/qYnVi9zWU9i 23 | MwEe6EBpmb9F5rKkgrfQscGbE6xvWi2I9GqJvSgAC89k3W/VORgSfPJWu8TTctQ/ 24 | 7pSFAoGAdECZxVQdTHmAQFt/F2LdpDB55du1kcJ0NMCQr1kq1lc3KD7UhlnROQ1P 25 | 0OhgphDceAwy8qq/6Pnv+2VjH2hn0RSJy+Bx9NJ3l8uyncmAlGXWKJAp5y+pPWQ0 26 | OrmnVGjbh4qHyi+d39KekZCvrOb5MnP1kQ4BfRsBXhp6Zx87mq4= 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /ca/intermediate/csr/intermediate.csr.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIEqzCCApMCAQAwZjELMAkGA1UEBhMCR0IxEDAOBgNVBAgMB0VuZ2xhbmQxEzAR 3 | BgNVBAoMCkV4cGVydCBUTFMxFDASBgNVBAsMC0lUIFRyYWluaW5nMRowGAYDVQQD 4 | DBFFeHBlcnQgVExTIEludCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC 5 | ggIBALcdGpp4tw3F69nYkGBYtCAH3FfVeNri5DJXoeT0x8uAH/vjIdnW9k9bx04X 6 | AcDTUsbfF/yCYuAYyF8tmV6kpWUFSTWdBlghoygPtRuYW2B/X3IFFDzLz6XJtp4B 7 | aPi7ZFt936uiGlyYiGpAcQrz+7CIgtiewf/yVwPHQjJ+4lTIbKf1Rj1f2GtDk/e8 8 | 4Ji8Uunn3p0usWF9Kg8KkIycO6XyDXJxbPapbjj4g28FTKFRQ4yO/2ivWArKZfwz 9 | 0eQ46QOgnXGpa36+YDEq5grIniM/UGeN1zi5AwrOQiJtjFAZKWaOoA0YHLhG8ZxY 10 | ENuvsT0SgolvSoXjJs/OGqt+ABIlpmLbTMqZkcRFih3OnQ8c5mBvU0hlNpjWRSTr 11 | h4w+aQDHjwqpds4IYS8rlUHaNxZloqiIoJpd+LZIORO7ypPrwkuaaHbC6uvTpNrp 12 | AOTu1J57HfkQkh2FWZZLw+L/iLuOZZmfUewNfHrY7ESRYc7zzu7tK/kkll1wadfR 13 | jwba0ZTP/97eTMDQyRfQS4xmftkkqPMneWUtRvqQk3thJOMJNLfjtbXBJZisHjZ0 14 | JYH+arRlfpQoHkuj0AQF1nRcfkB5iBtD1+Ck9NiiMQFbargi6EaEiD5u4cCWFHGI 15 | opDTz+wQEsQ1xMxIilXObsvppML45E7ktGGRo1AXgNvHrIWbAgMBAAGgADANBgkq 16 | hkiG9w0BAQsFAAOCAgEAmB2TgIrLoPJYRYXYSU6Vm0HY4U654zJQAnk2Wnfcbg1l 17 | A0xJizZGqScvNY5zJlci0onur8lEnTRNNszqFDJ+dOaqFgod262fmAMDARsEeqcK 18 | S0Y3Sio+FHzAoEB0Qa4g8vBXzSi7yplkmub9XMU7VtPiK2pfm06172ywboz0OX0z 19 | wjrPj8WNQzepE+Uk6Thtv7IFzk5ryQ+ep5D1u4bR1hdn/rqpsZupRn/7lsN82JkA 20 | cha8ctjy2BPHEaIJE5mE4m0iSrk65IMCDGzWQuQjuz1EQ2vUfK9kPIxhR2ZDtZck 21 | 5XPpdj1TXSHJu62aav4wZEvH6iSKA+KeoQ0WDkhQuMlWcvwZYCdOpuY1gUuiebWE 22 | 6Xr0BxMpty5H7PO9pzqcWk8DZRiXwfFsoDK8YrcSZr5P31rfI4v8vPr3GCdmEtMg 23 | u1JPev3PxeapnwNVXAOiO85sUd23jgLugHH69P4yhfEVWkxszVHYdHFLYiufPtW+ 24 | ZK4cmwdNtwbmV83J+of0EYhtQt1Am0Wg5m8RGDBYTIO58oPxmcLT/i5w4O6x2Jz4 25 | +8jdts5S1f9XhEo4PHxaMnSGFXp5RXFWgz27wBFX/nc8Qcrhr2gmq44Q8GIuRJXL 26 | 5nKgMkCSgWBsNzQJ9i+M2hEdgBXJNrDJudTbS1cTq2mgAImXAK3Gd2FcV8ZEVtc= 27 | -----END CERTIFICATE REQUEST----- 28 | -------------------------------------------------------------------------------- /ca/intermediate/private/client.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: AES-256-CBC,56C34355E4203C89408D50A34403E6A4 4 | 5 | /ezo0EmpHau8f0QvDAep037dcSE8d6Jwv+Wqhz5WdWapINOXW4b5v9S1gPDUkIoo 6 | BSmpkyaOcH5FhWd9qFbr0VClz1zlDmwy/W6Rgp8mgqkBUDnqLSKzi/NPCjiEIjp/ 7 | I93q3ZOXJ7xJO+0atLcCNlh/U37SOB5cSEjDj39eWQ46GZU+/TRtKVytwB1NuFe/ 8 | CRYGoOiKIqx0TZYIzwZnE1yvClwIAzcEMJ0gZY7vznAfwEIXPS1Eq1qa1lfbt3Eu 9 | agq6nCzoOQY5vjCVhSxcQODv9yBhhuYYuxKkCUhcnUvZhH3rJfkYL9zWmAirmZ90 10 | n+nHmSS/22KMbR4XM3aFY55fykYh6KcUsMDlggVcn2QTA1kiDifVbtb797jxltEi 11 | F6WrANuPEsVnb2s8cDxXxghLBG/PW3tMNSLDB2cNPh/BzKxTaKSfr0wDO4+nA6Hy 12 | 3C+KBaII3L2Py1zl/z7kDTqYLl9p/YS5N5gmq6Fu3p37MrqIKA0N5vQO0qSo1D4k 13 | 67qu3Ph1z8AKIlibPwd3e9KzEK6j2irkQifP4pvEHxvD/zFu9/18qq2eL6W+tNzY 14 | Dc511viov+v8eEKqZV5NIonhUMAltFrU8I0UKOuD3jPocTdnt43YpPkv4toBU/Vi 15 | 37XK1EmpSqga90W4oabBqbvd0dxfGKZQsmcDD0DJbgvknz0WHqlkPHdcOJKHPViA 16 | UklQ1VYwbFOY94IGC+E1GzyjbpaeVRHXnuz/LRYMwdOF64xOuqC6OFchL3r8+k6j 17 | Q6bZX0iVZKUVHWkYJQWHeUHmCRRTj7wLh3zRAfJ8wf3eiyZ1TZaNdqBEZQZUIWFJ 18 | iStVq/WENs1goMx0MJikIXFb6kqkuMare3GzHf4UuU1K9BP0q/PauZ5aB8PnDMLb 19 | dmu3ey87Wod2JjFfVU1KOwTiED1LaHasiFBSlCuvEm78xMo1Sdp1f6Jiuujg2ja5 20 | P7Gi22KbV0dHqDtGi5CsGMogsyxEOIGTrVjbnfhos+UXzZG40bCoocuevHCut7L6 21 | iLBQ9Kyy4ilig4hmW/3MQw5nCzB/lMGT5uk5bmQ2gO/ZEiwWhriDaWf4YIjGFI+w 22 | jPVPLLqymUdLNLnNsOM2tZ/O9LCjsjnay7lUId4TRdCrwMmtOrJlxHe9rEsiVTs1 23 | xE0l/t/h+3wDZtaj4R22oGlZhGppYDCve5BrNWxBCfI0Cl5V5O7Sj0Dw8Inqhh5h 24 | 5EOauO6YuI91V5saoQtGY5c/Wk719Ro5UedLeQhRR9U41QVnJRho4IdkZBBI0J6i 25 | f85k0v1xiUOf5H7bCr7UirQ3hgFyc5ggQs+7o0wnPO8xX+ied61mj4OV0NNMCOtw 26 | dUNJLoTbTrLvSy5D0l2ErQd5JT2NDEA9hW/VD6RAY3aLkhNvAoliuUbJi+MMDMFV 27 | GSjmkjlm7X1ktWqGu84j5eLVawwQxArxISYn23MVqz7lvGOQpXswHevqamxtTbfy 28 | VCdTIxaWMSwcWOw8IRR8EoVomX8ZlRW5jr3vuBRZIcA90NVO1GaBOSDFbOul+pPM 29 | 7R8jCcDyWJPpAS04piY38sttRCxtEHW3eGMMms8zoY8jEaffV8NqmmaP9KZczF6P 30 | -----END RSA PRIVATE KEY----- 31 | -------------------------------------------------------------------------------- /ca/intermediate/private/server.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: AES-256-CBC,7D3F9023C20CF5BD812492A13422B368 4 | 5 | OzYS7c0biaCsVbJD0bmQGk3BmAdMjmP3bCITZ0AiJdpc0SUglA3uTMmFRiN1lMn7 6 | Qx62Xk5aji6tY+/2cobxvBLn6a2fujn6IgSUDplSr+YBBNTyaQVxlHtPdSGwA9bm 7 | absvDtq0zqJRnOwZ5/Pke3Z4EjNbtvfAEXpa3p5RU7T3MgBap02RkaaiPUSbRxoQ 8 | sW7NuOIrL7tALRF/IsB3ap1AzX7LqfM4dBbJzZirjeiP/h4AwSb+4fhAFtAJ7Sf/ 9 | SFhY1SNf+AnfqpUZdu5n3JfqhH+di3wF+w8wW7RVHAPux7DO66j8Z73fQfcs4Zqm 10 | D0vLP5cqkhux7zsPgYuw2WsjPEVqc0COkcVi8/NyXy77JwzEPFkl+XQfPGgeU6r3 11 | KgMLV4+rW+BMunyKf1vLEq2ULHr0NE/b5Xz7El/wzL377pM4DyFixA1ecKezKdMA 12 | CVOEq5HIWMifp1s/gu6MKon1A8hrFz6v0f7DLz926uGlKZI/11PZXwMLScjnCvTv 13 | TUhhBpfadGtGHiDi4aF4OTudaVKP1qrv9+H9M4BXlEbSL0FnK+TkkcUUhTuSrvft 14 | U6LqXbvZ1gRj/vqi9Rb1Aor0Bx+pp9wlI7kpSc0PDtxFkA/7seoj7GbTIbUFWygW 15 | tPQTZnCX4KSJzcxoDgX2+AFDAlZIXhqesiRoZhvKfcVFulE8nqI9A54Yt26flVoG 16 | Hwo3fqW0h6gpPY6KdvXf3I1zHJYh1Tc3RQpP0QETzPPtJh51HpHCAgyBcNdEDqJI 17 | 15jCD8WKQaSKqpGQKSoraTDm3bA1qJaUwJzW6KIfzE+PfV2BmK5KdkjbZb49tGQR 18 | p5XasHdKHaIgKOewnD2QIA4RKy7GCkkZ6RCAbKUbdLBr59EFd+htUVD20xVYUbVI 19 | QPS9le9IOumrSzifUds0OmL8zRIS0Fzhx+oVLOw2+Pn2qiJzR2qIrPS/Cv81m7Jk 20 | wyv0p4aVEQvZf5o2PjQl+DETgU6anXIhTNKbCAYgTt6UwBdwIOGZfjzSXMPk0s/t 21 | qeLSwwTQ2W2WlhBkHhe3r04UKfgtGMS0nP1JPF6jiqnGPopWzGoIKiGq61RVF5op 22 | 8TmnyYnBOH0ed3T4DIhL8la/zhvCIvQq73v+hHnnx3aVYYh04Cy5BzyOWseVhR7Z 23 | BwvhjoE0AVCSLckIEzb+cD7t4vF7d6DpJ1xpRnyQQqdc8q2XklCEqf0MnaQNuw7a 24 | ec8JEUdNuBsTFftnCT2BwjcpxkHdfUj95/De0ja1zA5ugMLNuAFdxT5IdaPBiQZA 25 | OSUvvWp/h5Gg99FDpQJUU6zaGoSnp5wsMCEmyuNKUPHCgbHendDRLbe1L8WAIgkq 26 | aF3ce0eVhWStACAt2BExdVq75Zwh5xz4Jt52cnDyrXetaU4SJD5e1P+BPgm4SUnA 27 | S1R2R8kIdHxOBuP0t26ArA3ytxGLOGs/+FUN/VXvsyXT7+9SkBeTlqRrEAz9RpbQ 28 | /NOpLJCSdkJJPfpFgrMmxAZ5jcl7QoU7AvJsI8LF/Rwifsp/RZk2tnHvERRt6dTG 29 | JD5opoTUiFneZ43BEgRDQ5keV+TgWSnSJxG/jtoYsG9b2Q6IEj2m36hpVK+4EFYL 30 | -----END RSA PRIVATE KEY----- 31 | -------------------------------------------------------------------------------- /ca/intermediate/private/server.alt.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: AES-256-CBC,FA06BA2F324E02975D982EA17C76F003 4 | 5 | XCHWkx3ljhLfZHFOUUDD89ERxZawY5AY4KtSOc9fHhhMKE+N+9yc2S4r6yABw5cK 6 | 4EvMowldhWX6SHJfn55vR5HcluE+e+EnkHb3M6mao3pPSivavdEGEp+nqPYPYmwm 7 | UYB9ivFdWg2h9+u/p6zEE8bX/KlLEBy68T1V/zgpPwAWUygsk+HcC+qwrrByw8hs 8 | LI6Y+GeAv52XIZsEjnvHGO9cums2jtr4Xwcj3PvnY0zN2V1ekuRnAqBQ0IaW+1+8 9 | hcoDItOC2/HxGGJzEiKhca6SCZ4rDdQb37SuCKeshRirrUmZoY8AcqSQNLgPYVTR 10 | 8C3kpXm3UsGyP+e5IeGDwrH1qInmAI88ZfxMU+oRY6QwsWe9SW6PZiVTvjuZ9lIk 11 | hhPhQj1xoUcWxMJlJLZEu+L5Weeb+FrcCZbRhQwrX1CKz1ojz7CSBuUcF88S5YYB 12 | pjLGMx3IT/ps9Nm+DAADNrP7XDM0/7SqoOrkqmGL6h5er6QFsYxdIfnjV/4BoAES 13 | /P386upr6B7NrSwQopaA1Zrt86QX6MFsRq52hXWFp8w159PlbLFbMAiPyldaOxCp 14 | +Evzp9c/nr+7HD8aUygDbMM3w68vuAj8KuWgZ/Lr4YwWVLP8NeInlidEx9voR+UJ 15 | oCwpqnHN74j59Vo7zJ/rsT/dANxRCLToKrAVm5yfmO6BHXgk+VZJPkTqrlZmH6yu 16 | dWPqzgEJATpEnahTKx8nVAH7C3gfqqUYTOL99yxWQwDm9r1jEU5gNwZgHkPYE5SJ 17 | PR+UIof4kqaoEnlGvh2bDeFsmj+9LOy+Zh60PKbxd87Mn6tcGteV0N8bM0Pge/VG 18 | gJEkuKhT8s9bgIQ53+vpB5z3JXZx0+HEPtUwKB8rBI1zQxb9oyqKRD8UVTbvu/Bl 19 | Ib6BJ8me2Gy+FqitFLps8gQ/1/RE4MQ/Zk20z4vpa8NzXUENiogdI6GVBrXJ+KwC 20 | BveGMJcHcgzJQsvPkxM3QGKwyueFVhCIrY8xSGPFmN4cyMtOPanyFkPMhwkFPbxj 21 | f4nAsMBDM8Bl94BlzZ95DkBU5eBcyrKVP+56jWLJU3eEaovov1llbz5ZDTTcGuF4 22 | +Dg56N5A+STaIAlKiQBSXVlKn08VtyLoF6i/CxQtsW0emVZB3Op7/cF9AeLfWaJD 23 | XPs3eu/q9xizkC5dgD/OXybZ6VvRMyfp/wBl/RZSb669Dui/kv4f3KwS6QOauC0H 24 | H0QMlg8jqgSIjoPDa3pfZeSbS7AMBlP82GaUBIhqxDS5lGAw5HM14D/lHu81ku2o 25 | l7AqlmGk4PWi2cMYAuZODAIrrnnArSpneoymZyB5woY1+CDY/INE73VHvMIhK9VM 26 | jNtltuCTEAuB2epCQDygl4vBFeRHOnJBJd6iRCArM36jV1qonXakOSih1QsKC15i 27 | Sm65lw/5czXOHfj5IXY32T6PqLJ4zLzkpTN4S3Fvflkd4WrYEUCDbW7JeJwwKeDl 28 | cqPZpeXLrSL63EVNHwv7rCKi/apBgh7DU+tTO0jBXyOe1mN0I/EOrr+sSNSFCgcl 29 | xDK6S63ERvhWCbVqpXY4gGm5HKkHgK668MA6qEu7wWrZP0EpkNGkBD6htUm4XN92 30 | -----END RSA PRIVATE KEY----- 31 | -------------------------------------------------------------------------------- /ca/intermediate/newcerts/1002.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFDjCCAvagAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwZjELMAkGA1UEBhMCR0Ix 3 | EDAOBgNVBAgMB0VuZ2xhbmQxEzARBgNVBAoMCkV4cGVydCBUTFMxFDASBgNVBAsM 4 | C0lUIFRyYWluaW5nMRowGAYDVQQDDBFFeHBlcnQgVExTIEludCBDQTAeFw0yNTA4 5 | MDYwOTUyNDFaFw0yNjA4MTYwOTUyNDFaMGYxCzAJBgNVBAYTAkdCMRAwDgYDVQQI 6 | DAdFbmdsYW5kMRMwEQYDVQQKDApFeHBlcnQgVExTMRQwEgYDVQQLDAtJVCBUcmFp 7 | bmluZzEaMBgGA1UEAwwRRXhwZXJ0IFRMUyBDbGllbnQwggEiMA0GCSqGSIb3DQEB 8 | AQUAA4IBDwAwggEKAoIBAQDQmbmQli4wlto8v7z2WUoZ1ioUb7DCKCkT5XLwRST0 9 | APXeAR234B8Qir8EgpYiYfNt2jLWE+brRkKQEjPb+lA0mlNyHVQNKseLyB23mPoM 10 | S+x01rjNE/aJnf/5cie4UrYtehWpNx2wBIZjIINaS5DVUjZJE+B7+1LVppxXnDJ+ 11 | cFJx2782l9TmVKUdjJlE/uxYdqlP7H1SdJn9cjkusdCBcROWBCgVtTl9NAbcqWNx 12 | ZnAsuwRXVlb6o4S3k2T+MMpSDOfbZK5cIW9f1NCxVX/RumzmpyKz8Wojr1PZdQ8T 13 | w6oFvmEJnxOAAli6w7nsSk5I9bPhkwiDQ3JeYILftzh1AgMBAAGjgcUwgcIwCQYD 14 | VR0TBAIwADARBglghkgBhvhCAQEEBAMCBaAwMwYJYIZIAYb4QgENBCYWJE9wZW5T 15 | U0wgR2VuZXJhdGVkIENsaWVudCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUg6W0GJgs 16 | Q5wBy0l2c97oMIuzA9EwHwYDVR0jBBgwFoAUCcQk3r9hhR0h2MkN3r3qiz4SYHIw 17 | DgYDVR0PAQH/BAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDAN 18 | BgkqhkiG9w0BAQsFAAOCAgEAD0yo6ZQea6b511sLmbozWvrs0aYmyHphE5Uqyxot 19 | tY8F+oU7pWEOdOTcVbDXj/0kObr+mAQ+b5X4pCTUPzYKMzbUnwb9mOUvjaBwbZsa 20 | XvFFwXGP7WlKxfWuLhwjXKgVNFDCeIR1VfH3EXXRqp2bFMItxhHizBZ3tQA2KqQp 21 | rLlC0uAv5vuIbuwcYbJjoVs6fzb/0YA5fYpFYRbMdwn3jpU6v8OCedPDKagdPr7x 22 | zs0cyw9xlFOfP+TlbVIbQJDANFiG2fh3LrYsLAtyvwciDLMGEsyk/491QGYWmMFJ 23 | h2YqIxQhd7DLBwqnzulUASY7J1ukdf7fIRzPYN3s8xIa4a/PrfFG8p18ZkZXfIUP 24 | e6nVBbs736hblnF1WsDMsdXkNNYUfxn273rIDuo3/QCwN4mu4QI+AiqzyL31cixv 25 | qETCFAAbgvxmjMpXAszk0jryfx2gcuYltY+u4WUx+24ut2c8WmOth6nT3YyP6SFS 26 | sndYLwpzpT5MmOS2FFsA5WsSzuXMNEQdENIPPZiQIC9doWatwjps732rN1fnZN0Q 27 | 1eY4YWMZ5wqE+PHER35Yyv7xJSYFzjTNVZ5NVH1sKtPctfyrhiWvabmowWWALy2T 28 | tpdpb8XHhVd7coa4BxaYjtZQHxv4Q9tD7cLM0yVhbitwYxJe2Q7kF8IrIwXeCueC 29 | NfY= 30 | -----END CERTIFICATE----- 31 | -------------------------------------------------------------------------------- /ca/intermediate/certs/client.cert.cer: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFDjCCAvagAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwZjELMAkGA1UEBhMCR0Ix 3 | EDAOBgNVBAgMB0VuZ2xhbmQxEzARBgNVBAoMCkV4cGVydCBUTFMxFDASBgNVBAsM 4 | C0lUIFRyYWluaW5nMRowGAYDVQQDDBFFeHBlcnQgVExTIEludCBDQTAeFw0yNTA4 5 | MDYwOTUyNDFaFw0yNjA4MTYwOTUyNDFaMGYxCzAJBgNVBAYTAkdCMRAwDgYDVQQI 6 | DAdFbmdsYW5kMRMwEQYDVQQKDApFeHBlcnQgVExTMRQwEgYDVQQLDAtJVCBUcmFp 7 | bmluZzEaMBgGA1UEAwwRRXhwZXJ0IFRMUyBDbGllbnQwggEiMA0GCSqGSIb3DQEB 8 | AQUAA4IBDwAwggEKAoIBAQDQmbmQli4wlto8v7z2WUoZ1ioUb7DCKCkT5XLwRST0 9 | APXeAR234B8Qir8EgpYiYfNt2jLWE+brRkKQEjPb+lA0mlNyHVQNKseLyB23mPoM 10 | S+x01rjNE/aJnf/5cie4UrYtehWpNx2wBIZjIINaS5DVUjZJE+B7+1LVppxXnDJ+ 11 | cFJx2782l9TmVKUdjJlE/uxYdqlP7H1SdJn9cjkusdCBcROWBCgVtTl9NAbcqWNx 12 | ZnAsuwRXVlb6o4S3k2T+MMpSDOfbZK5cIW9f1NCxVX/RumzmpyKz8Wojr1PZdQ8T 13 | w6oFvmEJnxOAAli6w7nsSk5I9bPhkwiDQ3JeYILftzh1AgMBAAGjgcUwgcIwCQYD 14 | VR0TBAIwADARBglghkgBhvhCAQEEBAMCBaAwMwYJYIZIAYb4QgENBCYWJE9wZW5T 15 | U0wgR2VuZXJhdGVkIENsaWVudCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUg6W0GJgs 16 | Q5wBy0l2c97oMIuzA9EwHwYDVR0jBBgwFoAUCcQk3r9hhR0h2MkN3r3qiz4SYHIw 17 | DgYDVR0PAQH/BAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDAN 18 | BgkqhkiG9w0BAQsFAAOCAgEAD0yo6ZQea6b511sLmbozWvrs0aYmyHphE5Uqyxot 19 | tY8F+oU7pWEOdOTcVbDXj/0kObr+mAQ+b5X4pCTUPzYKMzbUnwb9mOUvjaBwbZsa 20 | XvFFwXGP7WlKxfWuLhwjXKgVNFDCeIR1VfH3EXXRqp2bFMItxhHizBZ3tQA2KqQp 21 | rLlC0uAv5vuIbuwcYbJjoVs6fzb/0YA5fYpFYRbMdwn3jpU6v8OCedPDKagdPr7x 22 | zs0cyw9xlFOfP+TlbVIbQJDANFiG2fh3LrYsLAtyvwciDLMGEsyk/491QGYWmMFJ 23 | h2YqIxQhd7DLBwqnzulUASY7J1ukdf7fIRzPYN3s8xIa4a/PrfFG8p18ZkZXfIUP 24 | e6nVBbs736hblnF1WsDMsdXkNNYUfxn273rIDuo3/QCwN4mu4QI+AiqzyL31cixv 25 | qETCFAAbgvxmjMpXAszk0jryfx2gcuYltY+u4WUx+24ut2c8WmOth6nT3YyP6SFS 26 | sndYLwpzpT5MmOS2FFsA5WsSzuXMNEQdENIPPZiQIC9doWatwjps732rN1fnZN0Q 27 | 1eY4YWMZ5wqE+PHER35Yyv7xJSYFzjTNVZ5NVH1sKtPctfyrhiWvabmowWWALy2T 28 | tpdpb8XHhVd7coa4BxaYjtZQHxv4Q9tD7cLM0yVhbitwYxJe2Q7kF8IrIwXeCueC 29 | NfY= 30 | -----END CERTIFICATE----- 31 | -------------------------------------------------------------------------------- /ca/intermediate/certs/client.cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFDjCCAvagAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwZjELMAkGA1UEBhMCR0Ix 3 | EDAOBgNVBAgMB0VuZ2xhbmQxEzARBgNVBAoMCkV4cGVydCBUTFMxFDASBgNVBAsM 4 | C0lUIFRyYWluaW5nMRowGAYDVQQDDBFFeHBlcnQgVExTIEludCBDQTAeFw0yNTA4 5 | MDYwOTUyNDFaFw0yNjA4MTYwOTUyNDFaMGYxCzAJBgNVBAYTAkdCMRAwDgYDVQQI 6 | DAdFbmdsYW5kMRMwEQYDVQQKDApFeHBlcnQgVExTMRQwEgYDVQQLDAtJVCBUcmFp 7 | bmluZzEaMBgGA1UEAwwRRXhwZXJ0IFRMUyBDbGllbnQwggEiMA0GCSqGSIb3DQEB 8 | AQUAA4IBDwAwggEKAoIBAQDQmbmQli4wlto8v7z2WUoZ1ioUb7DCKCkT5XLwRST0 9 | APXeAR234B8Qir8EgpYiYfNt2jLWE+brRkKQEjPb+lA0mlNyHVQNKseLyB23mPoM 10 | S+x01rjNE/aJnf/5cie4UrYtehWpNx2wBIZjIINaS5DVUjZJE+B7+1LVppxXnDJ+ 11 | cFJx2782l9TmVKUdjJlE/uxYdqlP7H1SdJn9cjkusdCBcROWBCgVtTl9NAbcqWNx 12 | ZnAsuwRXVlb6o4S3k2T+MMpSDOfbZK5cIW9f1NCxVX/RumzmpyKz8Wojr1PZdQ8T 13 | w6oFvmEJnxOAAli6w7nsSk5I9bPhkwiDQ3JeYILftzh1AgMBAAGjgcUwgcIwCQYD 14 | VR0TBAIwADARBglghkgBhvhCAQEEBAMCBaAwMwYJYIZIAYb4QgENBCYWJE9wZW5T 15 | U0wgR2VuZXJhdGVkIENsaWVudCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUg6W0GJgs 16 | Q5wBy0l2c97oMIuzA9EwHwYDVR0jBBgwFoAUCcQk3r9hhR0h2MkN3r3qiz4SYHIw 17 | DgYDVR0PAQH/BAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDAN 18 | BgkqhkiG9w0BAQsFAAOCAgEAD0yo6ZQea6b511sLmbozWvrs0aYmyHphE5Uqyxot 19 | tY8F+oU7pWEOdOTcVbDXj/0kObr+mAQ+b5X4pCTUPzYKMzbUnwb9mOUvjaBwbZsa 20 | XvFFwXGP7WlKxfWuLhwjXKgVNFDCeIR1VfH3EXXRqp2bFMItxhHizBZ3tQA2KqQp 21 | rLlC0uAv5vuIbuwcYbJjoVs6fzb/0YA5fYpFYRbMdwn3jpU6v8OCedPDKagdPr7x 22 | zs0cyw9xlFOfP+TlbVIbQJDANFiG2fh3LrYsLAtyvwciDLMGEsyk/491QGYWmMFJ 23 | h2YqIxQhd7DLBwqnzulUASY7J1ukdf7fIRzPYN3s8xIa4a/PrfFG8p18ZkZXfIUP 24 | e6nVBbs736hblnF1WsDMsdXkNNYUfxn273rIDuo3/QCwN4mu4QI+AiqzyL31cixv 25 | qETCFAAbgvxmjMpXAszk0jryfx2gcuYltY+u4WUx+24ut2c8WmOth6nT3YyP6SFS 26 | sndYLwpzpT5MmOS2FFsA5WsSzuXMNEQdENIPPZiQIC9doWatwjps732rN1fnZN0Q 27 | 1eY4YWMZ5wqE+PHER35Yyv7xJSYFzjTNVZ5NVH1sKtPctfyrhiWvabmowWWALy2T 28 | tpdpb8XHhVd7coa4BxaYjtZQHxv4Q9tD7cLM0yVhbitwYxJe2Q7kF8IrIwXeCueC 29 | NfY= 30 | -----END CERTIFICATE----- 31 | -------------------------------------------------------------------------------- /ca/intermediate/newcerts/1000.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 31 | H9vS5e996cxVQZgalhc= 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /ca/intermediate/certs/server.cert.cer: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 31 | H9vS5e996cxVQZgalhc= 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /ca/intermediate/certs/server.cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 31 | H9vS5e996cxVQZgalhc= 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /ca/intermediate/newcerts/1001.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 31 | qe4zfsGG6g/zRunxBz19QA== 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /ca/intermediate/certs/server.alt.cert.cer: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 31 | qe4zfsGG6g/zRunxBz19QA== 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /ca/intermediate/certs/server.alt.cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 31 | qe4zfsGG6g/zRunxBz19QA== 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /ca/newcerts/1000.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFrzCCA5egAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwZzELMAkGA1UEBhMCR0Ix 3 | EDAOBgNVBAgMB0VuZ2xhbmQxEzARBgNVBAoMCkV4cGVydCBUTFMxFDASBgNVBAsM 4 | C0lUIFRyYWluaW5nMRswGQYDVQQDDBJFeHBlcnQgVExTIFJvb3QgQ0EwHhcNMTkw 5 | NDI3MTczNDI5WhcNMjkwNDI0MTczNDI5WjBmMQswCQYDVQQGEwJHQjEQMA4GA1UE 6 | CAwHRW5nbGFuZDETMBEGA1UECgwKRXhwZXJ0IFRMUzEUMBIGA1UECwwLSVQgVHJh 7 | aW5pbmcxGjAYBgNVBAMMEUV4cGVydCBUTFMgSW50IENBMIICIjANBgkqhkiG9w0B 8 | AQEFAAOCAg8AMIICCgKCAgEAtx0amni3DcXr2diQYFi0IAfcV9V42uLkMleh5PTH 9 | y4Af++Mh2db2T1vHThcBwNNSxt8X/IJi4BjIXy2ZXqSlZQVJNZ0GWCGjKA+1G5hb 10 | YH9fcgUUPMvPpcm2ngFo+LtkW33fq6IaXJiIakBxCvP7sIiC2J7B//JXA8dCMn7i 11 | VMhsp/VGPV/Ya0OT97zgmLxS6efenS6xYX0qDwqQjJw7pfINcnFs9qluOPiDbwVM 12 | oVFDjI7/aK9YCspl/DPR5DjpA6Cdcalrfr5gMSrmCsieIz9QZ43XOLkDCs5CIm2M 13 | UBkpZo6gDRgcuEbxnFgQ26+xPRKCiW9KheMmz84aq34AEiWmYttMypmRxEWKHc6d 14 | DxzmYG9TSGU2mNZFJOuHjD5pAMePCql2zghhLyuVQdo3FmWiqIigml34tkg5E7vK 15 | k+vCS5podsLq69Ok2ukA5O7Unnsd+RCSHYVZlkvD4v+Iu45lmZ9R7A18etjsRJFh 16 | zvPO7u0r+SSWXXBp19GPBtrRlM//3t5MwNDJF9BLjGZ+2SSo8yd5ZS1G+pCTe2Ek 17 | 4wk0t+O1tcElmKweNnQlgf5qtGV+lCgeS6PQBAXWdFx+QHmIG0PX4KT02KIxAVtq 18 | uCLoRoSIPm7hwJYUcYiikNPP7BASxDXEzEiKVc5uy+mkwvjkTuS0YZGjUBeA28es 19 | hZsCAwEAAaNmMGQwHQYDVR0OBBYEFAnEJN6/YYUdIdjJDd696os+EmByMB8GA1Ud 20 | IwQYMBaAFE3xxC9g42fddFPITOx3hNyeTWM8MBIGA1UdEwEB/wQIMAYBAf8CAQAw 21 | DgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQAP/1/sU3TJMk6iNF+2 22 | T4nPjc4N7eU4sv2d6C2o5Z7xMp530ebpB0PKY2hOfzZoGKdxoG7XOVuixBQoGRqX 23 | cNv4znJB/qg7aOMSa5CADM44Uq6stI7JytD1qjDo/q86SILujtRYjPtXzxpk6ZD1 24 | eIyhqkx9yPOHcOIHGEg6Ev+GCgy3oGRjbD8WNQ4bCde1RGj81kmOuXwepSMzaoqU 25 | giJ82hYCUyr0vxHwvuhu/GKljeu9RlNN5vG5KvmwPJWtn36P/vD6WGctW4Dsbnyy 26 | 0D3kCdJ77HBAvQFUiV+oNC2NqreuTrKKzfvStl0HVa+UBMcwIi7hu18vVjntMM66 27 | vd7Ruz4yvEDy14Gz9WWstJde4TCDaOfQMU9dmfyZoc3ObWwSCseY3efADJ1HFgMB 28 | RAKmWEEZmPwHtJ6ZU5nSixRDMqAKTE1s4/CZ0DT+tX8/Q2pZqO+k9brLI5UDcSLD 29 | dW1dtHu1oJCOWoEg9DOIWtuRmexU4DbJsvV0//7pJ+C80MERVG5B4zB+r2fZfiEI 30 | DCu7GcuyM9Ns+qIoYD1rV30rOI83B3HBatQO91I/kLMgR6Xupm1Pe1VsCm3zQauJ 31 | QYngOVgB23x/dBXmeXA1dmSpYpKKuywbVRycWcJ8QvwWodPxIDkq8qdDoZK7aTSO 32 | pr5tpd5cz3O/xysCtjjxDn5Duw== 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /ca/certs/ca.cert.cer: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /ca/certs/ca.cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /ca/intermediate/certs/intermediate.cert.cer: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFrzCCA5egAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwZzELMAkGA1UEBhMCR0Ix 3 | EDAOBgNVBAgMB0VuZ2xhbmQxEzARBgNVBAoMCkV4cGVydCBUTFMxFDASBgNVBAsM 4 | C0lUIFRyYWluaW5nMRswGQYDVQQDDBJFeHBlcnQgVExTIFJvb3QgQ0EwHhcNMTkw 5 | NDI3MTczNDI5WhcNMjkwNDI0MTczNDI5WjBmMQswCQYDVQQGEwJHQjEQMA4GA1UE 6 | CAwHRW5nbGFuZDETMBEGA1UECgwKRXhwZXJ0IFRMUzEUMBIGA1UECwwLSVQgVHJh 7 | aW5pbmcxGjAYBgNVBAMMEUV4cGVydCBUTFMgSW50IENBMIICIjANBgkqhkiG9w0B 8 | AQEFAAOCAg8AMIICCgKCAgEAtx0amni3DcXr2diQYFi0IAfcV9V42uLkMleh5PTH 9 | y4Af++Mh2db2T1vHThcBwNNSxt8X/IJi4BjIXy2ZXqSlZQVJNZ0GWCGjKA+1G5hb 10 | YH9fcgUUPMvPpcm2ngFo+LtkW33fq6IaXJiIakBxCvP7sIiC2J7B//JXA8dCMn7i 11 | VMhsp/VGPV/Ya0OT97zgmLxS6efenS6xYX0qDwqQjJw7pfINcnFs9qluOPiDbwVM 12 | oVFDjI7/aK9YCspl/DPR5DjpA6Cdcalrfr5gMSrmCsieIz9QZ43XOLkDCs5CIm2M 13 | UBkpZo6gDRgcuEbxnFgQ26+xPRKCiW9KheMmz84aq34AEiWmYttMypmRxEWKHc6d 14 | DxzmYG9TSGU2mNZFJOuHjD5pAMePCql2zghhLyuVQdo3FmWiqIigml34tkg5E7vK 15 | k+vCS5podsLq69Ok2ukA5O7Unnsd+RCSHYVZlkvD4v+Iu45lmZ9R7A18etjsRJFh 16 | zvPO7u0r+SSWXXBp19GPBtrRlM//3t5MwNDJF9BLjGZ+2SSo8yd5ZS1G+pCTe2Ek 17 | 4wk0t+O1tcElmKweNnQlgf5qtGV+lCgeS6PQBAXWdFx+QHmIG0PX4KT02KIxAVtq 18 | uCLoRoSIPm7hwJYUcYiikNPP7BASxDXEzEiKVc5uy+mkwvjkTuS0YZGjUBeA28es 19 | hZsCAwEAAaNmMGQwHQYDVR0OBBYEFAnEJN6/YYUdIdjJDd696os+EmByMB8GA1Ud 20 | IwQYMBaAFE3xxC9g42fddFPITOx3hNyeTWM8MBIGA1UdEwEB/wQIMAYBAf8CAQAw 21 | DgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQAP/1/sU3TJMk6iNF+2 22 | T4nPjc4N7eU4sv2d6C2o5Z7xMp530ebpB0PKY2hOfzZoGKdxoG7XOVuixBQoGRqX 23 | cNv4znJB/qg7aOMSa5CADM44Uq6stI7JytD1qjDo/q86SILujtRYjPtXzxpk6ZD1 24 | eIyhqkx9yPOHcOIHGEg6Ev+GCgy3oGRjbD8WNQ4bCde1RGj81kmOuXwepSMzaoqU 25 | giJ82hYCUyr0vxHwvuhu/GKljeu9RlNN5vG5KvmwPJWtn36P/vD6WGctW4Dsbnyy 26 | 0D3kCdJ77HBAvQFUiV+oNC2NqreuTrKKzfvStl0HVa+UBMcwIi7hu18vVjntMM66 27 | vd7Ruz4yvEDy14Gz9WWstJde4TCDaOfQMU9dmfyZoc3ObWwSCseY3efADJ1HFgMB 28 | RAKmWEEZmPwHtJ6ZU5nSixRDMqAKTE1s4/CZ0DT+tX8/Q2pZqO+k9brLI5UDcSLD 29 | dW1dtHu1oJCOWoEg9DOIWtuRmexU4DbJsvV0//7pJ+C80MERVG5B4zB+r2fZfiEI 30 | DCu7GcuyM9Ns+qIoYD1rV30rOI83B3HBatQO91I/kLMgR6Xupm1Pe1VsCm3zQauJ 31 | QYngOVgB23x/dBXmeXA1dmSpYpKKuywbVRycWcJ8QvwWodPxIDkq8qdDoZK7aTSO 32 | pr5tpd5cz3O/xysCtjjxDn5Duw== 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /ca/intermediate/certs/intermediate.cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 32 | pr5tpd5cz3O/xysCtjjxDn5Duw== 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /python/resources/client/ca.cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /python/resources/server/ca.cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /answers/python/exercise3/SSLClient.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import ssl 3 | from pathlib import Path 4 | import pickle 5 | import hashlib 6 | 7 | 8 | LOCAL_HOST = 'localhost' 9 | LOCAL_PORT = 8484 10 | RESOURCE_DIRECTORY = Path(__file__).resolve().parent.parent / 'resources' / 'client' 11 | CA_CERT = RESOURCE_DIRECTORY / 'ca.cert.pem' 12 | PINNED_FILE = RESOURCE_DIRECTORY / 'pinned.hash' 13 | 14 | 15 | def main(): 16 | """ 17 | Exercise 3 Client 18 | """ 19 | # Create a standard TCP Socket 20 | sock = socket.socket(socket.AF_INET) 21 | 22 | # Create SSL context which holds the parameters for any sessions 23 | context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH) 24 | context.check_hostname = False 25 | context.load_verify_locations(CA_CERT) 26 | 27 | # We can wrap in an SSL context first, then connect 28 | conn = context.wrap_socket(sock, server_hostname="Expert TLS Server") 29 | try: 30 | # Handshake - conn is an SSLSocket 31 | conn.connect((LOCAL_HOST, LOCAL_PORT)) 32 | 33 | # Verify against pinned hash 34 | dat = conn.getpeercert(binary_form=True) 35 | hashalg = hashlib.sha256() 36 | hashalg.update(dat) 37 | cert_hash = hashalg.digest() 38 | 39 | with open(PINNED_FILE, 'rb') as pinned: 40 | pinned_hash = pinned.read() 41 | 42 | if cert_hash != pinned_hash: 43 | raise ssl.CertificateError("Non-pinned certificate!") 44 | 45 | # What parameters were established? 46 | print("Negotiated session using cipher suite: {0}\n".format(conn.cipher()[0])) 47 | 48 | # We are sending a 4 byte int, convert into bytes 49 | conn.send((100124796).to_bytes(4, 'big')) 50 | 51 | # Receive a number back from the server 52 | server_response = conn.recv(1024) 53 | 54 | # Unpickle the bytes from the server into a datatypes.BankCustomer 55 | customer_returned = pickle.loads(server_response) 56 | print(customer_returned) 57 | 58 | except ssl.CertificateError: 59 | print("The host's certificate has not been pinned by this application") 60 | finally: 61 | conn.close() 62 | 63 | 64 | if __name__ == '__main__': 65 | main() 66 | -------------------------------------------------------------------------------- /python/exercise3/SSLClient.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import ssl 3 | from pathlib import Path 4 | import pickle 5 | import hashlib 6 | 7 | 8 | LOCAL_HOST = 'localhost' 9 | LOCAL_PORT = 8484 10 | RESOURCE_DIRECTORY = Path(__file__).resolve().parent.parent / 'resources' / 'client' 11 | CA_CERT = RESOURCE_DIRECTORY / 'ca.cert.pem' 12 | PINNED_FILE = RESOURCE_DIRECTORY / 'pinned.hash' 13 | 14 | 15 | def main(): 16 | """ 17 | Exercise 3 Client 18 | """ 19 | # Create a standard TCP Socket 20 | sock = socket.socket(socket.AF_INET) 21 | 22 | # Create SSL context which holds the parameters for any sessions 23 | context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH) 24 | context.check_hostname = False 25 | context.load_verify_locations(CA_CERT) 26 | 27 | # We can wrap in an SSL context first, then connect 28 | conn = context.wrap_socket(sock, server_hostname="Expert TLS Server") 29 | try: 30 | # Handshake - conn is an SSLSocket 31 | conn.connect((LOCAL_HOST, LOCAL_PORT)) 32 | 33 | # Part 1: Client 34 | # Both the regular and "imposter" servers have certificates signed by the CA. This means the 35 | # best way to limit connections to a *single* server is to pin its certificate. 36 | # 37 | # Here you need to add hashing validation against the received certificate, comparing it to 38 | # the hash you have on file in 'pinned.hash'. 39 | # 40 | # For help check out: 41 | # https://github.com/mikepound/tls-exercises/blob/master/python/README.md 42 | 43 | # What parameters were established? 44 | print("Negotiated session using cipher suite: {0}\n".format(conn.cipher()[0])) 45 | 46 | # We are sending a 4 byte int, convert into bytes 47 | conn.send((100124796).to_bytes(4, 'big')) 48 | 49 | # Receive a number back from the server 50 | server_response = conn.recv(1024) 51 | 52 | # Unpickle the bytes from the server into a datatypes.BankCustomer 53 | customer_returned = pickle.loads(server_response) 54 | print(customer_returned) 55 | 56 | except ssl.CertificateError: 57 | print("The host's certificate has not been pinned by this application") 58 | finally: 59 | conn.close() 60 | 61 | 62 | if __name__ == '__main__': 63 | main() 64 | -------------------------------------------------------------------------------- /java/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 4.0.0 6 | 7 | com.tlsexercises 8 | tlsexercises 9 | 1.0-SNAPSHOT 10 | 11 | tlsexercises 12 | 13 | http://www.example.com 14 | 15 | 16 | UTF-8 17 | 1.8 18 | 1.8 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | maven-clean-plugin 27 | 3.1.0 28 | 29 | 30 | 31 | maven-resources-plugin 32 | 3.0.2 33 | 34 | 35 | maven-compiler-plugin 36 | 3.8.0 37 | 38 | 39 | maven-surefire-plugin 40 | 2.22.1 41 | 42 | 43 | maven-jar-plugin 44 | 3.0.2 45 | 46 | 47 | maven-install-plugin 48 | 2.5.2 49 | 50 | 51 | maven-deploy-plugin 52 | 2.8.2 53 | 54 | 55 | 56 | maven-site-plugin 57 | 3.7.1 58 | 59 | 60 | maven-project-info-reports-plugin 61 | 3.0.0 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /java/src/main/java/com/tlsexercises/exercise2/SSLClient.java: -------------------------------------------------------------------------------- 1 | package com.tlsexercises.exercise2; 2 | 3 | import javax.net.ssl.SSLSocket; 4 | import javax.net.ssl.SSLSocketFactory; 5 | import java.io.*; 6 | import java.nio.ByteBuffer; 7 | import java.util.Arrays; 8 | 9 | /** 10 | * Exercise 2 Client 11 | */ 12 | public class SSLClient { 13 | 14 | private static final String REMOTE_HOST = "localhost"; 15 | private static final int REMOTE_PORT = 8383; 16 | private static final String TRUSTSTORE_LOCATION = SSLClient.class.getResource("/client/ClientTrustStore.jks").getPath(); 17 | private static final String TRUSTSTORE_PASSWORD = "experttls"; 18 | 19 | // Entry point 20 | public static void main(String[] args) { 21 | // You can also update properties as a command line parameter e.g. 22 | // -Djavax.net.ssl.keyStore="keystore_location" 23 | System.setProperty("javax.net.ssl.trustStore", TRUSTSTORE_LOCATION); 24 | System.setProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD); 25 | 26 | // Part 2 27 | // The server is now expecting a certificate, add relevant keystore definitions and properties above. 28 | // 29 | // For help check out: 30 | // https://github.com/mikepound/tls-exercises/blob/master/java/README.md 31 | 32 | // Obtain the default socket factory 33 | SSLSocketFactory f = (SSLSocketFactory) SSLSocketFactory.getDefault(); 34 | 35 | try { 36 | // Create a socket - will not connect yet 37 | SSLSocket socket = (SSLSocket) f.createSocket(REMOTE_HOST, REMOTE_PORT); 38 | 39 | // Handshake to create a session 40 | socket.startHandshake(); 41 | 42 | // What parameters were established? 43 | System.out.println(String.format("Negotiated Session: %s", socket.getSession().getProtocol())); 44 | System.out.println(String.format("Cipher Suite: %s", socket.getSession().getCipherSuite())); 45 | 46 | // We're reading and writing characters this time 47 | BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream())); 48 | BufferedWriter output = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); 49 | 50 | output.write("GET /index.html HTTP/1.1\n"); 51 | output.flush(); 52 | 53 | System.out.println("\nServer Response:"); 54 | String currentLine = null; 55 | System.out.println(input.readLine()); 56 | while ((currentLine = input.readLine()) != null) { 57 | System.out.println(currentLine); 58 | } 59 | 60 | input.close(); 61 | output.close(); 62 | socket.close(); 63 | } catch (Exception e) { 64 | System.err.println("Exception: " + e.toString()); 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /java/src/main/java/com/tlsexercises/exercise1/SSLClient.java: -------------------------------------------------------------------------------- 1 | package com.tlsexercises.exercise1; 2 | 3 | import java.io.*; 4 | import javax.net.ssl.*; 5 | import java.nio.*; 6 | 7 | /** 8 | * Exercise 1 Client 9 | */ 10 | public class SSLClient { 11 | 12 | private static final String REMOTE_HOST = "localhost"; 13 | private static final int REMOTE_PORT = 8282; 14 | private static final String TRUSTSTORE_LOCATION = SSLClient.class.getResource("/client/ClientTrustStore.jks").getPath(); 15 | private static final String TRUSTSTORE_PASSWORD = "experttls"; 16 | 17 | // Entry point 18 | public static void main(String[] args) { 19 | // You can also update properties as a command line parameter e.g. 20 | // -Djavax.net.ssl.keyStore="keystore_location" 21 | System.setProperty("javax.net.ssl.trustStore", TRUSTSTORE_LOCATION); 22 | System.setProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD); 23 | 24 | // Part 1 25 | // Add code here to obtain a default socket factory, an SSL socket, and then make a connection 26 | // For help check out: 27 | // https://github.com/mikepound/tls-exercises/blob/master/java/README.md 28 | 29 | // Obtain the default socket factory 30 | SSLSocketFactory f = null; 31 | 32 | try { 33 | // Create a socket - will not connect yet 34 | SSLSocket socket = null; 35 | 36 | // Handshake to create a session 37 | 38 | 39 | 40 | if (socket == null) { 41 | return; 42 | } 43 | 44 | // What parameters were established? 45 | System.out.println(String.format("Negotiated Session: %s", socket.getSession().getProtocol())); 46 | System.out.println(String.format("Cipher Suite: %s", socket.getSession().getCipherSuite())); 47 | 48 | // We're reading and writing bytes. Other streams can be used. 49 | BufferedOutputStream output = new BufferedOutputStream(socket.getOutputStream()); 50 | BufferedInputStream input = new BufferedInputStream(socket.getInputStream()); 51 | output.write(new byte[] { 2, 3, 5, 7, 11, 13, 17, 19, 23 }); 52 | output.flush(); 53 | 54 | // Read the server response up to a max of 64 bytes. 55 | byte[] serverResponse = new byte[64]; 56 | int len = input.read(serverResponse, 0, 64); 57 | 58 | // Server response is an int, so should be 4 bytes 59 | if (len == 4) { 60 | ByteBuffer result = ByteBuffer.allocate(4).put(serverResponse, 0, 4); 61 | System.out.println("\nServer result: " + result.getInt(0)); 62 | } 63 | 64 | input.close(); 65 | output.close(); 66 | socket.close(); 67 | } catch (Exception e) { 68 | System.err.println("Exception: " + e.toString()); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /answers/java/exercise2/SSLClient.java: -------------------------------------------------------------------------------- 1 | package com.tlsexercises.exercise2; 2 | 3 | import javax.net.ssl.SSLSocket; 4 | import javax.net.ssl.SSLSocketFactory; 5 | import java.io.*; 6 | import java.nio.ByteBuffer; 7 | import java.util.Arrays; 8 | 9 | /** 10 | * Exercise 2 Client 11 | */ 12 | public class SSLClient { 13 | 14 | private static final String REMOTE_HOST = "localhost"; 15 | private static final int REMOTE_PORT = 8383; 16 | private static final String TRUSTSTORE_LOCATION = SSLClient.class.getResource("/client/ClientTrustStore.jks").getPath(); 17 | private static final String TRUSTSTORE_PASSWORD = "experttls"; 18 | private static final String KEYSTORE_LOCATION = SSLClient.class.getResource("/client/ClientKeyStore.jks").getPath(); 19 | private static final String KEYSTORE_PASSWORD = "experttls"; 20 | 21 | // Entry point 22 | public static void main(String[] args) { 23 | // You can also update properties as a command line parameter e.g. 24 | // -Djavax.net.ssl.keyStore="keystore_location" 25 | System.setProperty("javax.net.ssl.trustStore", TRUSTSTORE_LOCATION); 26 | System.setProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD); 27 | System.setProperty("javax.net.ssl.keyStore", KEYSTORE_LOCATION); 28 | System.setProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD); 29 | 30 | // Obtain the default socket factory 31 | SSLSocketFactory f = (SSLSocketFactory) SSLSocketFactory.getDefault(); 32 | 33 | try { 34 | // Create a socket - will not connect yet 35 | SSLSocket socket = (SSLSocket) f.createSocket(REMOTE_HOST, REMOTE_PORT); 36 | 37 | // Handshake to create a session 38 | socket.startHandshake(); 39 | 40 | // What parameters were established? 41 | System.out.println(String.format("Negotiated Session: %s", socket.getSession().getProtocol())); 42 | System.out.println(String.format("Cipher Suite: %s", socket.getSession().getCipherSuite())); 43 | 44 | // We're reading and writing characters this time 45 | BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream())); 46 | BufferedWriter output = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); 47 | 48 | output.write("GET /index.html HTTP/1.1\n"); 49 | output.flush(); 50 | 51 | System.out.println("\nServer Response:"); 52 | String currentLine = null; 53 | System.out.println(input.readLine()); 54 | while ((currentLine = input.readLine()) != null) { 55 | System.out.println(currentLine); 56 | } 57 | 58 | input.close(); 59 | output.close(); 60 | socket.close(); 61 | } catch (Exception e) { 62 | System.err.println("Exception: " + e.toString()); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /answers/java/exercise1/SSLClient.java: -------------------------------------------------------------------------------- 1 | package com.tlsexercises.exercise1; 2 | 3 | import java.io.*; 4 | import javax.net.ssl.*; 5 | import java.nio.*; 6 | 7 | /** 8 | * Exercise 1 Client 9 | */ 10 | public class SSLClient { 11 | 12 | private static final String REMOTE_HOST = "localhost"; 13 | private static final int REMOTE_PORT = 8282; 14 | private static final String TRUSTSTORE_LOCATION = SSLClient.class.getResource("/client/ClientTrustStore.jks").getPath(); 15 | private static final String TRUSTSTORE_PASSWORD = "experttls"; 16 | 17 | // Entry point 18 | public static void main(String[] args) { 19 | // You can also update properties as a command line parameter e.g. 20 | // -Djavax.net.ssl.keyStore="keystore_location" 21 | System.setProperty("javax.net.ssl.trustStore", TRUSTSTORE_LOCATION); 22 | System.setProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD); 23 | 24 | // Obtain the default socket factory 25 | SSLSocketFactory f = (SSLSocketFactory) SSLSocketFactory.getDefault(); 26 | 27 | try { 28 | // Create a socket - will not connect yet 29 | SSLSocket socket = (SSLSocket) f.createSocket(REMOTE_HOST, REMOTE_PORT); 30 | 31 | // Set protocols and suites 32 | socket.setEnabledCipherSuites(new String[]{ "TLS_AES_128_GCM_SHA256", "TLS_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" }); 33 | socket.setEnabledProtocols(new String[]{ "TLSv1.3", "TLSv1.2" }); 34 | 35 | // Handshake to create a session 36 | socket.startHandshake(); 37 | 38 | // What parameters were established? 39 | System.out.println(String.format("Negotiated Session: %s", socket.getSession().getProtocol())); 40 | System.out.println(String.format("Cipher Suite: %s", socket.getSession().getCipherSuite())); 41 | 42 | // We're reading and writing bytes. Other streams can be used. 43 | BufferedOutputStream output = new BufferedOutputStream(socket.getOutputStream()); 44 | BufferedInputStream input = new BufferedInputStream(socket.getInputStream()); 45 | output.write(new byte[] { 2, 3, 5, 7, 11, 13, 17, 19, 23 }); 46 | output.flush(); 47 | 48 | // Read the server response up to a max of 64 bytes. 49 | byte[] serverResponse = new byte[64]; 50 | int len = input.read(serverResponse, 0, 64); 51 | 52 | // Server response is an int, so should be 4 bytes 53 | if (len == 4) { 54 | ByteBuffer result = ByteBuffer.allocate(4).put(serverResponse, 0, 4); 55 | System.out.println("\nServer result: " + result.getInt(0)); 56 | } 57 | 58 | input.close(); 59 | output.close(); 60 | socket.close(); 61 | } catch (Exception e) { 62 | System.err.println("Exception: " + e.toString()); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SSL/TLS Exercises 2 | 3 | These exercises are associated with my course on Transport Layer Security (TLS). This course is delivered via O'Reilly Live Training. When not teaching online I am a lecturer at the University of Nottingham, and appear on YouTube. 4 | 5 | - [O’Reilly live training](https://www.oreilly.com/live-training/courses/expert-transport-layer-security-tls/0636920282907) 6 | - [My university page](https://www.nottingham.ac.uk/research/groups/cvl/people/michael.pound) 7 | - [Computerphile](https://youtube.com/computerphile) 8 | 9 | ## Introduction 10 | Exercises are available in either Python or Java, depending on which language you are most familiar with. Although the languages and their support for TLS are quite different, the exercises are identical - at least in general structure and the goal. In each case you need to complete any code necessary to establish the required TLS connection between a client and server. If you're familiar with the language, each exercise should not take too long. 11 | 12 | **Note:** The focus of these exercises is an introduction in TLS, not a lesson in production ready code! With this in mind, I've kept unnecessary structure and error correcting code to a minimum. It's quite possible to produce exceptions, use these as a guide to find out what requires fixing. 13 | 14 | ## The Exercises 15 | There are three exercises involving different client-server communications. In each case you have some or all of both the client and server implementations, and you must either fix or add to the existing code. 16 | 17 | **Exercise 1:** You have a working server, and some of a client implementation. You need to add the remaining SSL code necessary to get the two programs communicating. Once this is done, you should add some code to ensure only the most recent ciphers and protocols are negotiated between the parties. 18 | 19 | **Exercise 2:** You have working client and server implementations. You need to alter both in order to create a mutually authenticated session. That is, one in which the client is also authenticated using a certificate 20 | 21 | **Exercise 3:** You have a working server and client, but a second "imposter" server exists that also has a valid certificate from the CA. You need to implement pinning on the original certificate in order to verify which server is the real one. 22 | 23 | ## Materials 24 | The repository contains a number of subfolders, most contain their own readme file with more detailed information. 25 | ### Python 26 | Exercises in python using the standard ssl library. These exercises have been written to work in Python 3.6 and 3.7. 27 | - [Exercises](./python/) 28 | - [Answers](answers/python/) 29 | 30 | ### Java 31 | Exercises in Java using the javax.net and javax.net.ssl packages. These exercises were compiled using a modern Java SDK targeting Java 8. 32 | - [Exercises](./java/) 33 | - [Answers](answers/java/) 34 | 35 | ### OpenSSL CA 36 | An example certificate authority created using [OpenSSL](https://www.openssl.org/) 1.1.1b. This CA was used to generate the keys and signed certificates found in the exercises. If you wish to manage your own certificate chains, you can use this folder as an example. Instructions on the use of this CA are provided in the readme, but bear in mind that correct certificate management is extremely important, be sure to read up! 37 | -------------------------------------------------------------------------------- /answers/python/exercise1/SSLServer.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import ssl 3 | import threading 4 | from pathlib import Path 5 | import select 6 | 7 | LOCAL_HOST = 'localhost' 8 | LOCAL_PORT = 8282 9 | RESOURCE_DIRECTORY = Path(__file__).resolve().parent.parent / 'resources' / 'server' 10 | SERVER_CERT_CHAIN = RESOURCE_DIRECTORY / 'server.intermediate.chain.pem' 11 | SERVER_KEY = RESOURCE_DIRECTORY / 'server.key.pem' 12 | 13 | 14 | class SSLServer: 15 | """ 16 | Exercise 1 Server 17 | """ 18 | def __init__(self): 19 | """ 20 | Creates an SSLContext which provides parameters for any future SSL connections 21 | """ 22 | context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) 23 | context.load_cert_chain(certfile=SERVER_CERT_CHAIN, keyfile=SERVER_KEY) 24 | context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 | ssl.OP_NO_SSLv3 25 | context.set_ciphers('ALL:!DSS:!DHE:!aNULL:!eNull') 26 | self.context = context 27 | 28 | def start_server(self): 29 | """ 30 | Begins listening on a socket. Any connections that arrive are wrapped in an SSLSocket using the context 31 | created during initialisation 32 | 33 | Makes use of the OS select function to perform basic non-blocking IO. Once a connection has established 34 | an instance of ClientHandler is created to serve the client 35 | """ 36 | server_socket = socket.socket() 37 | server_socket.bind((LOCAL_HOST, LOCAL_PORT)) 38 | server_socket.listen(5) 39 | read_list = [server_socket] 40 | 41 | print("Listening on port {0}...".format(LOCAL_PORT)) 42 | 43 | while True: 44 | readable, writable, errored = select.select(read_list, [], [], 2) 45 | for s in readable: 46 | if s is server_socket: 47 | client_socket, address = server_socket.accept() 48 | try: 49 | # Wrap the socket in an SSL connection (will perform a handshake) 50 | conn = self.context.wrap_socket(client_socket, server_side=True) 51 | ClientHandler(conn).start() 52 | except ssl.SSLError as e: 53 | print(e) 54 | 55 | 56 | class ClientHandler(threading.Thread): 57 | """ 58 | Thread handler leaves the main thread free to handle any other incoming connections 59 | """ 60 | def __init__(self, conn): 61 | threading.Thread.__init__(self) 62 | self.conn = conn 63 | 64 | def run(self): 65 | try: 66 | # Read up to 1024 bytes from the client 67 | client_request = self.conn.recv(1024) 68 | print("Received from client:", client_request) 69 | 70 | # Return the product of the client's byte values 71 | product = 1 72 | for n in client_request: 73 | product *= n 74 | 75 | # You are responsible for converting any data into bytes strings 76 | self.conn.send(product.to_bytes(4, 'big')) 77 | except ssl.SSLError as e: 78 | print(e) 79 | except Exception as e: 80 | print(e) 81 | finally: 82 | self.conn.close() 83 | 84 | 85 | def main(): 86 | server = SSLServer() 87 | server.start_server() 88 | 89 | 90 | if __name__ == '__main__': 91 | main() 92 | -------------------------------------------------------------------------------- /ca/private/ca.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: AES-256-CBC,5DFF0FC290DB14D5A2A953753A92FDBD 4 | 5 | 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 54 | -----END RSA PRIVATE KEY----- 55 | -------------------------------------------------------------------------------- /python/exercise1/SSLServer.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import ssl 3 | import threading 4 | from pathlib import Path 5 | import select 6 | 7 | LOCAL_HOST = 'localhost' 8 | LOCAL_PORT = 8282 9 | RESOURCE_DIRECTORY = Path(__file__).resolve().parent.parent / 'resources' / 'server' 10 | SERVER_CERT_CHAIN = RESOURCE_DIRECTORY / 'server.intermediate.chain.pem' 11 | SERVER_KEY = RESOURCE_DIRECTORY / 'server.key.pem' 12 | 13 | 14 | class SSLServer: 15 | """ 16 | Exercise 1 Server 17 | """ 18 | def __init__(self): 19 | """ 20 | Creates an SSLContext which provides parameters for any future SSL connections 21 | """ 22 | context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) 23 | context.load_cert_chain(certfile=SERVER_CERT_CHAIN, keyfile=SERVER_KEY) 24 | 25 | # Part 2 26 | # Add code here to disable older protocols and cipher suites. You can add similar code to the client, too. 27 | # For help check out: 28 | # https://github.com/mikepound/tls-exercises/blob/master/python/README.md 29 | 30 | self.context = context 31 | 32 | def start_server(self): 33 | """ 34 | Begins listening on a socket. Any connections that arrive are wrapped in an SSLSocket using the context 35 | created during initialisation 36 | 37 | Makes use of the OS select function to perform basic non-blocking IO. Once a connection has established 38 | an instance of ClientHandler is created to serve the client 39 | """ 40 | server_socket = socket.socket() 41 | server_socket.bind((LOCAL_HOST, LOCAL_PORT)) 42 | server_socket.listen(5) 43 | read_list = [server_socket] 44 | 45 | print("Listening on port {0}...".format(LOCAL_PORT)) 46 | 47 | while True: 48 | readable, writable, errored = select.select(read_list, [], [], 2) 49 | for s in readable: 50 | if s is server_socket: 51 | client_socket, address = server_socket.accept() 52 | try: 53 | # Wrap the socket in an SSL connection (will perform a handshake) 54 | conn = self.context.wrap_socket(client_socket, server_side=True) 55 | ClientHandler(conn).start() 56 | except ssl.SSLError as e: 57 | print(e) 58 | 59 | 60 | class ClientHandler(threading.Thread): 61 | """ 62 | Thread handler leaves the main thread free to handle any other incoming connections 63 | """ 64 | def __init__(self, conn): 65 | threading.Thread.__init__(self) 66 | self.conn = conn 67 | 68 | def run(self): 69 | try: 70 | # Read up to 1024 bytes from the client 71 | client_request = self.conn.recv(1024) 72 | print("Received from client:", client_request) 73 | 74 | # Return the product of the client's byte values 75 | product = 1 76 | for n in client_request: 77 | product *= n 78 | 79 | # You are responsible for converting any data into bytes strings 80 | self.conn.send(product.to_bytes(4, 'big')) 81 | except ssl.SSLError as e: 82 | print(e) 83 | except Exception as e: 84 | print(e) 85 | finally: 86 | self.conn.close() 87 | 88 | 89 | def main(): 90 | server = SSLServer() 91 | server.start_server() 92 | 93 | 94 | if __name__ == '__main__': 95 | main() 96 | -------------------------------------------------------------------------------- /ca/intermediate/private/intermediate.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: AES-256-CBC,6400FB0CC250010B57DA8470B3E61568 4 | 5 | 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 54 | -----END RSA PRIVATE KEY----- 55 | -------------------------------------------------------------------------------- /java/src/main/java/com/tlsexercises/exercise3/BankCustomer.java: -------------------------------------------------------------------------------- 1 | package com.tlsexercises.exercise3; 2 | 3 | import java.io.*; 4 | 5 | /** 6 | * Example class illustrating the use of serialization in transporting objects across SSL connections. 7 | * 8 | * This is purely an example - Banks should implement their own classes! 9 | * 10 | */ 11 | public class BankCustomer implements Serializable { 12 | 13 | private static final long serialVersionUID = 1001338395385763920L; 14 | 15 | private int id; 16 | private String name; 17 | private String emailAddress; 18 | private int accountNumber; 19 | private int sortCode; 20 | private String address1; 21 | private String address2; 22 | private String town; 23 | private String postCode; 24 | 25 | public BankCustomer(int id, String name, String email, int accn, int srtc, String add1, String add2, String town, String pc) { 26 | this.id = id; 27 | this.name = name; 28 | this.emailAddress = email; 29 | this.accountNumber = accn; 30 | this.sortCode = srtc; 31 | this.address1 = add1; 32 | this.address2 = add2; 33 | this.town = town; 34 | this.postCode = pc; 35 | } 36 | 37 | public int getId() { 38 | return id; 39 | } 40 | 41 | public String getName() { 42 | return name; 43 | } 44 | 45 | public String getEmailAddress() { 46 | return emailAddress; 47 | } 48 | 49 | public void setEmailAddress(String emailAddress) { 50 | this.emailAddress = emailAddress; 51 | } 52 | 53 | public int getAccountNumber() { 54 | return accountNumber; 55 | } 56 | 57 | public int getSortCode() { 58 | return sortCode; 59 | } 60 | 61 | public String getAddress1() { 62 | return address1; 63 | } 64 | 65 | public void setAddress1(String address1) { 66 | this.address1 = address1; 67 | } 68 | 69 | public String getAddress2() { 70 | return address2; 71 | } 72 | 73 | public void setAddress2(String address2) { 74 | this.address2 = address2; 75 | } 76 | 77 | public String getTown() { 78 | return town; 79 | } 80 | 81 | public void setTown(String town) { 82 | this.town = town; 83 | } 84 | 85 | public String getPostCode() { 86 | return postCode; 87 | } 88 | 89 | public void setPostCode(String postCode) { 90 | this.postCode = postCode; 91 | } 92 | 93 | @Override 94 | public boolean equals(Object o) { 95 | if (this == o) return true; 96 | if (o == null || getClass() != o.getClass()) return false; 97 | 98 | BankCustomer other = (BankCustomer) o; 99 | 100 | return this.id == other.id; 101 | } 102 | 103 | @Override 104 | public int hashCode() { 105 | return this.id; 106 | } 107 | 108 | @Override 109 | public String toString(){ 110 | StringBuilder srtString = new StringBuilder(); 111 | srtString.append(this.sortCode); 112 | srtString.insert(4, '-'); 113 | srtString.insert(2,'-'); 114 | return String.format("----------\n%d\n%s\nAccount: %d (%s)\n%s, %s, %s, %s\n----------\n", 115 | this.id, 116 | this.name, 117 | this.accountNumber, 118 | srtString.toString(), 119 | this.address1, this.address2, this.town, this.postCode); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /java/src/main/java/com/tlsexercises/exercise3/SSLServer.java: -------------------------------------------------------------------------------- 1 | package com.tlsexercises.exercise3; 2 | 3 | import javax.net.ServerSocketFactory; 4 | import javax.net.ssl.SSLServerSocket; 5 | import javax.net.ssl.SSLServerSocketFactory; 6 | import java.io.*; 7 | import java.net.Socket; 8 | 9 | /** 10 | * Exercise 3 "Official" Server 11 | */ 12 | public class SSLServer { 13 | 14 | private static final int LOCAL_PORT = 8484; 15 | private static final String KEYSTORE_LOCATION = SSLServer.class.getResource("/server/ServerKeyStore.jks").getPath(); 16 | private static final String KEYSTORE_PASSWORD = "experttls"; 17 | 18 | // Entry point 19 | public static void main(String argv[]) throws Exception { 20 | // You can also update properties as a command line parameter e.g. 21 | // -Djavax.net.ssl.keyStore="keystore_location" 22 | System.setProperty("javax.net.ssl.keyStore", KEYSTORE_LOCATION); 23 | System.setProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD); 24 | 25 | SSLServer server = new SSLServer(); 26 | server.startServer(); 27 | } 28 | 29 | // Start server 30 | public void startServer() { 31 | try { 32 | ServerSocketFactory ssf = SSLServerSocketFactory.getDefault(); 33 | SSLServerSocket socket = (SSLServerSocket) ssf.createServerSocket(LOCAL_PORT); 34 | 35 | System.out.println(String.format("Listening on port %d...", socket.getLocalPort())); 36 | 37 | while (true) { 38 | Socket client = socket.accept(); 39 | ClientHandler handler = new ClientHandler(client); 40 | handler.start(); 41 | } 42 | } catch (Exception e) { 43 | System.out.println("Exception:" + e.getMessage()); 44 | } 45 | } 46 | 47 | /** 48 | * This client handler sends and receives objects using Object streams. 49 | */ 50 | class ClientHandler extends Thread { 51 | 52 | Socket client; 53 | ObjectInputStream input; 54 | ObjectOutputStream output; 55 | 56 | public ClientHandler(Socket s) { // constructor 57 | client = s; 58 | 59 | try { 60 | output = new ObjectOutputStream(client.getOutputStream()); 61 | input = new ObjectInputStream(client.getInputStream()); 62 | } catch (IOException e) { 63 | System.err.println("Error creating streams: " + e.getMessage()); 64 | } 65 | } 66 | 67 | public void run() { 68 | try { 69 | // Obtain client message containing bank customer ID 70 | int idRequest = input.readInt(); 71 | System.out.println("Received from Client: " + idRequest); 72 | 73 | // Send back a customer matching this ID 74 | BankCustomer exampleCustomer = new BankCustomer( 75 | idRequest, 76 | "Matthew Jones", 77 | "matthew.jones@example.com", 78 | 84127843, 79 | 200265, 80 | "14 A Lane", 81 | "A District", 82 | "A Town", 83 | "NR1 ABC"); 84 | 85 | output.writeObject(exampleCustomer); 86 | output.flush(); 87 | 88 | // Close streams and socket 89 | output.close(); 90 | input.close(); 91 | client.close(); 92 | } catch (Exception e) { 93 | System.err.println("Exception: " + e.getMessage()); 94 | } 95 | } 96 | } 97 | } 98 | 99 | -------------------------------------------------------------------------------- /answers/python/exercise2/SSLServer.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import ssl 3 | import threading 4 | from pathlib import Path 5 | import select 6 | 7 | LOCAL_HOST = 'localhost' 8 | LOCAL_PORT = 8383 9 | RESOURCE_DIRECTORY = Path(__file__).resolve().parent.parent / 'resources' / 'server' 10 | SERVER_CERT_CHAIN = RESOURCE_DIRECTORY / 'server.intermediate.chain.pem' 11 | SERVER_KEY = RESOURCE_DIRECTORY / 'server.key.pem' 12 | CA_CERT = RESOURCE_DIRECTORY / 'ca.cert.pem' 13 | 14 | class SSLServer: 15 | """ 16 | Exercise 2 Server 17 | """ 18 | def __init__(self): 19 | """ 20 | Creates an SSLContext which provides parameters for any future SSL connections 21 | """ 22 | context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) 23 | context.load_cert_chain(certfile=SERVER_CERT_CHAIN, keyfile=SERVER_KEY) 24 | context.verify_mode = ssl.CERT_REQUIRED 25 | context.load_verify_locations(CA_CERT) 26 | self.context = context 27 | 28 | def start_server(self): 29 | """ 30 | Begins listening on a socket. Any connections that arrive are wrapped in an SSLSocket using the context 31 | created during initialisation. 32 | 33 | Makes use of the OS select function to perform basic non-blocking IO. Once a connection has established 34 | an instance of ClientHandler is created to serve the client 35 | """ 36 | server_socket = socket.socket() 37 | server_socket.bind((LOCAL_HOST, LOCAL_PORT)) 38 | server_socket.listen(5) 39 | read_list = [server_socket] 40 | 41 | print("Listening on port {0}...".format(LOCAL_PORT)) 42 | 43 | while True: 44 | readable, writable, errored = select.select(read_list, [], [], 2) 45 | for s in readable: 46 | if s is server_socket: 47 | client_socket, address = server_socket.accept() 48 | try: 49 | # Wrap the socket in an SSL connection (will perform a handshake) 50 | conn = self.context.wrap_socket(client_socket, server_side=True) 51 | ClientHandler(conn).start() 52 | except ssl.SSLError as e: 53 | print(e) 54 | 55 | 56 | class ClientHandler(threading.Thread): 57 | """ 58 | Thread handler leaves the main thread free to handle any other incoming connections 59 | """ 60 | def __init__(self, conn): 61 | threading.Thread.__init__(self) 62 | self.conn = conn 63 | 64 | def run(self): 65 | try: 66 | # Read up to 1024 bytes from the client 67 | client_request = self.conn.recv(1024) 68 | 69 | # This client and server are sending encoded UTF-8 strings 70 | print("Received from client:", client_request.decode("UTF-8").rstrip()) 71 | 72 | # Reply to the client's request with a small web page. 73 | self.conn.send("HTTP/1.0 200 OK\nContent-type: text/html\n" 74 | "\n" 75 | " \n" 76 | " Tiny Website\n" 77 | " \n" 78 | " \n" 79 | " A very small website!\n" 80 | " \n" 81 | "\n".encode("UTF-8")) 82 | 83 | except ssl.SSLError as e: 84 | print(e) 85 | except Exception as e: 86 | print(e) 87 | finally: 88 | self.conn.close() 89 | 90 | 91 | def main(): 92 | server = SSLServer() 93 | server.start_server() 94 | 95 | 96 | if __name__ == '__main__': 97 | main() 98 | -------------------------------------------------------------------------------- /java/src/main/java/com/tlsexercises/exercise3/SSLImposterServer.java: -------------------------------------------------------------------------------- 1 | package com.tlsexercises.exercise3; 2 | 3 | import javax.net.ServerSocketFactory; 4 | import javax.net.ssl.SSLServerSocket; 5 | import javax.net.ssl.SSLServerSocketFactory; 6 | import java.io.IOException; 7 | import java.io.ObjectInputStream; 8 | import java.io.ObjectOutputStream; 9 | import java.net.Socket; 10 | 11 | /** 12 | * Exercise 3 "Imposter" Server 13 | */ 14 | public class SSLImposterServer { 15 | 16 | private static final int LOCAL_PORT = 8484; 17 | private static final String KEYSTORE_LOCATION = SSLImposterServer.class.getResource("/server/ServerAltKeyStore.jks").getPath(); 18 | private static final String KEYSTORE_PASSWORD = "experttls"; 19 | 20 | // Entry point 21 | public static void main(String argv[]) throws Exception { 22 | // You can also update properties as a command line parameter e.g. 23 | // -Djavax.net.ssl.keyStore="keystore_location" 24 | System.setProperty("javax.net.ssl.keyStore", KEYSTORE_LOCATION); 25 | System.setProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD); 26 | 27 | SSLImposterServer server = new SSLImposterServer(); 28 | server.startServer(); 29 | } 30 | 31 | // Start server 32 | public void startServer() { 33 | try { 34 | ServerSocketFactory ssf = SSLServerSocketFactory.getDefault(); 35 | SSLServerSocket socket = (SSLServerSocket) ssf.createServerSocket(LOCAL_PORT); 36 | 37 | System.out.println(String.format("Listening on port %d...", socket.getLocalPort())); 38 | 39 | while (true) { 40 | Socket client = socket.accept(); 41 | ClientHandler handler = new ClientHandler(client); 42 | handler.start(); 43 | } 44 | } catch (Exception e) { 45 | System.out.println("Exception:" + e.getMessage()); 46 | } 47 | } 48 | 49 | /** 50 | * This client handler sends and receives objects using Object streams. 51 | */ 52 | class ClientHandler extends Thread { 53 | 54 | Socket client; 55 | ObjectInputStream input; 56 | ObjectOutputStream output; 57 | 58 | public ClientHandler(Socket s) { // constructor 59 | client = s; 60 | 61 | try { 62 | output = new ObjectOutputStream(client.getOutputStream()); 63 | input = new ObjectInputStream(client.getInputStream()); 64 | } catch (IOException e) { 65 | System.err.println("Error creating streams: " + e.getMessage()); 66 | } 67 | } 68 | 69 | public void run() { 70 | try { 71 | // Obtain client message containing bank customer ID 72 | int idRequest = input.readInt(); 73 | System.out.println("Received from Client: " + idRequest); 74 | 75 | // Send back a customer matching this ID 76 | BankCustomer exampleCustomer = new BankCustomer( 77 | idRequest, 78 | "Imposter data", 79 | "not.real@email.com", 80 | 123456789, 81 | 654321, 82 | "Nowhere", 83 | "", 84 | "", 85 | ""); 86 | 87 | output.writeObject(exampleCustomer); 88 | output.flush(); 89 | 90 | // Close streams and socket 91 | output.close(); 92 | input.close(); 93 | client.close(); 94 | } catch (Exception e) { 95 | System.err.println("Exception: " + e.getMessage()); 96 | } 97 | } 98 | } 99 | } 100 | 101 | -------------------------------------------------------------------------------- /python/exercise3/SSLImposterServer.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import ssl 3 | import threading 4 | from pathlib import Path 5 | import select 6 | from datatypes import BankCustomer 7 | import pickle 8 | 9 | LOCAL_HOST = 'localhost' 10 | LOCAL_PORT = 8484 11 | RESOURCE_DIRECTORY = Path(__file__).resolve().parent.parent / 'resources' / 'server' 12 | SERVER_CERT_CHAIN = RESOURCE_DIRECTORY / 'server.intermediate.alt.chain.pem' 13 | SERVER_KEY = RESOURCE_DIRECTORY / 'server.alt.key.pem' 14 | 15 | # Part 2: Server 16 | # In this exercise the server requires no additional code. 17 | # 18 | # When testing, you can alternate which set of certificates you use by running either this imposter 19 | # server, or the official one. 20 | # 21 | # For help check out: 22 | # https://github.com/mikepound/tls-exercises/blob/master/python/README.md 23 | 24 | class SSLServer: 25 | """ 26 | Exercise 3 "Imposter" Server 27 | """ 28 | def __init__(self): 29 | context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) 30 | context.load_cert_chain(certfile=SERVER_CERT_CHAIN, keyfile=SERVER_KEY) 31 | self.context = context 32 | 33 | def start_server(self): 34 | server_socket = socket.socket() 35 | server_socket.bind((LOCAL_HOST, LOCAL_PORT)) 36 | server_socket.listen(5) 37 | read_list = [server_socket] 38 | 39 | print("Listening on port {0}...".format(LOCAL_PORT)) 40 | 41 | while True: 42 | readable, writable, errored = select.select(read_list, [], [], 2) 43 | for s in readable: 44 | if s is server_socket: 45 | client_socket, address = server_socket.accept() 46 | try: 47 | # Wrap the socket in an SSL connection (will perform a handshake) 48 | conn = self.context.wrap_socket(client_socket, server_side=True) 49 | ClientHandler(conn).start() 50 | except ssl.SSLError as e: 51 | print(e) 52 | 53 | 54 | class ClientHandler(threading.Thread): 55 | """ 56 | Thread handler leaves the main thread free to handle any other incoming connections 57 | """ 58 | def __init__(self, conn): 59 | threading.Thread.__init__(self) 60 | self.conn = conn 61 | 62 | def run(self): 63 | try: 64 | # Read up to 1024 bytes from the client 65 | client_request = self.conn.recv(1024) 66 | 67 | # Parse an int containing a bank customer id 68 | requested_id = int.from_bytes(client_request, 'big') 69 | print("Received from client:", requested_id) 70 | 71 | # Send back a response - this is just another bank customer but theoretically 72 | # if receiving trusted data from an imposter, this could be malformed or malicous 73 | example_customer = BankCustomer(requested_id, 74 | "Imposter data", 75 | "not.real@email.com", 76 | 123456789, 77 | 654321, 78 | "Nowhere", 79 | "", 80 | "", 81 | "") 82 | 83 | # We need to send bytes, python's pickling makes this simple 84 | self.conn.send(pickle.dumps(example_customer)) 85 | 86 | except ssl.SSLError as e: 87 | print(e) 88 | except Exception as e: 89 | print(e) 90 | finally: 91 | self.conn.close() 92 | 93 | 94 | def main(): 95 | server = SSLServer() 96 | server.start_server() 97 | 98 | 99 | if __name__ == '__main__': 100 | main() 101 | -------------------------------------------------------------------------------- /python/exercise2/SSLServer.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import ssl 3 | import threading 4 | from pathlib import Path 5 | import select 6 | 7 | LOCAL_HOST = 'localhost' 8 | LOCAL_PORT = 8383 9 | RESOURCE_DIRECTORY = Path(__file__).resolve().parent.parent / 'resources' / 'server' 10 | SERVER_CERT_CHAIN = RESOURCE_DIRECTORY / 'server.intermediate.chain.pem' 11 | SERVER_KEY = RESOURCE_DIRECTORY / 'server.key.pem' 12 | 13 | class SSLServer: 14 | """ 15 | Exercise 2 Server 16 | """ 17 | def __init__(self): 18 | """ 19 | Creates an SSLContext which provides parameters for any future SSL connections 20 | """ 21 | context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) 22 | context.load_cert_chain(certfile=SERVER_CERT_CHAIN, keyfile=SERVER_KEY) 23 | 24 | # Part 1: Server 25 | # Add code here to request mutual authentication from the client. You'll also need to add a reference to the 26 | # CA cert above 27 | # 28 | # For help check out: 29 | # https://github.com/mikepound/tls-exercises/blob/master/python/README.md 30 | 31 | self.context = context 32 | 33 | def start_server(self): 34 | """ 35 | Begins listening on a socket. Any connections that arrive are wrapped in an SSLSocket using the context 36 | created during initialisation. 37 | 38 | Makes use of the OS select function to perform basic non-blocking IO. Once a connection has established 39 | an instance of ClientHandler is created to serve the client 40 | """ 41 | server_socket = socket.socket() 42 | server_socket.bind((LOCAL_HOST, LOCAL_PORT)) 43 | server_socket.listen(5) 44 | read_list = [server_socket] 45 | 46 | print("Listening on port {0}...".format(LOCAL_PORT)) 47 | 48 | while True: 49 | readable, writable, errored = select.select(read_list, [], [], 2) 50 | for s in readable: 51 | if s is server_socket: 52 | client_socket, address = server_socket.accept() 53 | try: 54 | # Wrap the socket in an SSL connection (will perform a handshake) 55 | conn = self.context.wrap_socket(client_socket, server_side=True) 56 | ClientHandler(conn).start() 57 | except ssl.SSLError as e: 58 | print(e) 59 | 60 | 61 | class ClientHandler(threading.Thread): 62 | """ 63 | Thread handler leaves the main thread free to handle any other incoming connections 64 | """ 65 | def __init__(self, conn): 66 | threading.Thread.__init__(self) 67 | self.conn = conn 68 | 69 | def run(self): 70 | try: 71 | # Read up to 1024 bytes from the client 72 | client_request = self.conn.recv(1024) 73 | 74 | # This client and server are sending encoded UTF-8 strings 75 | print("Received from client:", client_request.decode("UTF-8").rstrip()) 76 | 77 | # Reply to the client's request with a small web page. 78 | self.conn.send("HTTP/1.0 200 OK\nContent-type: text/html\n" 79 | "\n" 80 | " \n" 81 | " Tiny Website\n" 82 | " \n" 83 | " \n" 84 | " A very small website!\n" 85 | " \n" 86 | "\n".encode("UTF-8")) 87 | 88 | except ssl.SSLError as e: 89 | print(e) 90 | except Exception as e: 91 | print(e) 92 | finally: 93 | self.conn.close() 94 | 95 | 96 | def main(): 97 | server = SSLServer() 98 | server.start_server() 99 | 100 | 101 | if __name__ == '__main__': 102 | main() 103 | -------------------------------------------------------------------------------- /python/resources/client/client.intermediate.chain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFDjCCAvagAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwZjELMAkGA1UEBhMCR0Ix 3 | EDAOBgNVBAgMB0VuZ2xhbmQxEzARBgNVBAoMCkV4cGVydCBUTFMxFDASBgNVBAsM 4 | C0lUIFRyYWluaW5nMRowGAYDVQQDDBFFeHBlcnQgVExTIEludCBDQTAeFw0yNTA4 5 | MDYwOTUyNDFaFw0yNjA4MTYwOTUyNDFaMGYxCzAJBgNVBAYTAkdCMRAwDgYDVQQI 6 | DAdFbmdsYW5kMRMwEQYDVQQKDApFeHBlcnQgVExTMRQwEgYDVQQLDAtJVCBUcmFp 7 | bmluZzEaMBgGA1UEAwwRRXhwZXJ0IFRMUyBDbGllbnQwggEiMA0GCSqGSIb3DQEB 8 | AQUAA4IBDwAwggEKAoIBAQDQmbmQli4wlto8v7z2WUoZ1ioUb7DCKCkT5XLwRST0 9 | APXeAR234B8Qir8EgpYiYfNt2jLWE+brRkKQEjPb+lA0mlNyHVQNKseLyB23mPoM 10 | S+x01rjNE/aJnf/5cie4UrYtehWpNx2wBIZjIINaS5DVUjZJE+B7+1LVppxXnDJ+ 11 | cFJx2782l9TmVKUdjJlE/uxYdqlP7H1SdJn9cjkusdCBcROWBCgVtTl9NAbcqWNx 12 | ZnAsuwRXVlb6o4S3k2T+MMpSDOfbZK5cIW9f1NCxVX/RumzmpyKz8Wojr1PZdQ8T 13 | w6oFvmEJnxOAAli6w7nsSk5I9bPhkwiDQ3JeYILftzh1AgMBAAGjgcUwgcIwCQYD 14 | VR0TBAIwADARBglghkgBhvhCAQEEBAMCBaAwMwYJYIZIAYb4QgENBCYWJE9wZW5T 15 | U0wgR2VuZXJhdGVkIENsaWVudCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUg6W0GJgs 16 | Q5wBy0l2c97oMIuzA9EwHwYDVR0jBBgwFoAUCcQk3r9hhR0h2MkN3r3qiz4SYHIw 17 | DgYDVR0PAQH/BAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDAN 18 | BgkqhkiG9w0BAQsFAAOCAgEAD0yo6ZQea6b511sLmbozWvrs0aYmyHphE5Uqyxot 19 | tY8F+oU7pWEOdOTcVbDXj/0kObr+mAQ+b5X4pCTUPzYKMzbUnwb9mOUvjaBwbZsa 20 | XvFFwXGP7WlKxfWuLhwjXKgVNFDCeIR1VfH3EXXRqp2bFMItxhHizBZ3tQA2KqQp 21 | rLlC0uAv5vuIbuwcYbJjoVs6fzb/0YA5fYpFYRbMdwn3jpU6v8OCedPDKagdPr7x 22 | zs0cyw9xlFOfP+TlbVIbQJDANFiG2fh3LrYsLAtyvwciDLMGEsyk/491QGYWmMFJ 23 | h2YqIxQhd7DLBwqnzulUASY7J1ukdf7fIRzPYN3s8xIa4a/PrfFG8p18ZkZXfIUP 24 | e6nVBbs736hblnF1WsDMsdXkNNYUfxn273rIDuo3/QCwN4mu4QI+AiqzyL31cixv 25 | qETCFAAbgvxmjMpXAszk0jryfx2gcuYltY+u4WUx+24ut2c8WmOth6nT3YyP6SFS 26 | sndYLwpzpT5MmOS2FFsA5WsSzuXMNEQdENIPPZiQIC9doWatwjps732rN1fnZN0Q 27 | 1eY4YWMZ5wqE+PHER35Yyv7xJSYFzjTNVZ5NVH1sKtPctfyrhiWvabmowWWALy2T 28 | tpdpb8XHhVd7coa4BxaYjtZQHxv4Q9tD7cLM0yVhbitwYxJe2Q7kF8IrIwXeCueC 29 | NfY= 30 | -----END CERTIFICATE----- 31 | -----BEGIN CERTIFICATE----- 32 | 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 62 | pr5tpd5cz3O/xysCtjjxDn5Duw== 63 | -----END CERTIFICATE----- 64 | -------------------------------------------------------------------------------- /java/src/main/java/com/tlsexercises/exercise1/SSLServer.java: -------------------------------------------------------------------------------- 1 | package com.tlsexercises.exercise1; 2 | 3 | import java.io.*; 4 | import java.net.*; 5 | import java.util.Arrays; 6 | import javax.net.ServerSocketFactory; 7 | import javax.net.ssl.*; 8 | import java.nio.*; 9 | 10 | /** 11 | * Exercise 1 Server 12 | */ 13 | public class SSLServer { 14 | 15 | private static final int LOCAL_PORT = 8282; 16 | private static final String KEYSTORE_LOCATION = SSLServer.class.getResource("/server/ServerKeyStore.jks").getPath(); 17 | private static final String KEYSTORE_PASSWORD = "experttls"; 18 | 19 | // Entry point 20 | public static void main(String argv[]) throws Exception { 21 | // You can also update properties as a command line parameter e.g. 22 | // -Djavax.net.ssl.keyStore="keystore_location" 23 | System.setProperty("javax.net.ssl.keyStore", KEYSTORE_LOCATION); 24 | System.setProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD); 25 | 26 | SSLServer server = new SSLServer(); 27 | server.startServer(); 28 | } 29 | 30 | // Start server 31 | public void startServer() { 32 | try { 33 | ServerSocketFactory ssf = SSLServerSocketFactory.getDefault(); 34 | SSLServerSocket socket = (SSLServerSocket) ssf.createServerSocket(LOCAL_PORT); 35 | 36 | // Part 2 37 | // Add code here to disable older protocols and cipher suites. You can add similar restrictions 38 | // to the client code, too. 39 | // 40 | // For help check out: 41 | // https://github.com/mikepound/tls-exercises/blob/master/java/README.md 42 | 43 | System.out.println(String.format("Listening on port %d...", socket.getLocalPort())); 44 | 45 | while (true) { 46 | Socket client = socket.accept(); 47 | ClientHandler handler = new ClientHandler(client); 48 | handler.start(); 49 | } 50 | } catch (Exception e) { 51 | System.out.println("Exception:" + e.getMessage()); 52 | } 53 | } 54 | 55 | /** 56 | * This nested class handles any new clients that appear. This frees the main thread to continue 57 | * receiving new clients and performing handshakes. 58 | * 59 | * This particular handler sends and receives bytes via buffered input and output streams 60 | */ 61 | class ClientHandler extends Thread { 62 | 63 | Socket client; 64 | BufferedInputStream input; 65 | BufferedOutputStream output; 66 | 67 | public ClientHandler(Socket s) { // constructor 68 | client = s; 69 | 70 | try { 71 | input = new BufferedInputStream(client.getInputStream()); 72 | output = new BufferedOutputStream(client.getOutputStream()); 73 | } catch (IOException e) { 74 | System.err.println("Error creating streams: " + e.getMessage()); 75 | } 76 | } 77 | 78 | public void run() { 79 | try { 80 | // Obtain client message and use it 81 | byte[] clientMessage = new byte[64]; 82 | int len = input.read(clientMessage, 0, 64); 83 | int total = 1; 84 | for (int i = 0; i < len; i++) { 85 | total *= clientMessage[i]; 86 | } 87 | 88 | System.out.println("Received from Client: " + Arrays.toString(Arrays.copyOfRange(clientMessage, 0, len))); 89 | 90 | // Return product of client's byte values 91 | ByteBuffer buff = ByteBuffer.allocate(4).putInt(total); 92 | output.write(buff.array()); 93 | output.flush(); 94 | 95 | // Close streams and socket 96 | output.close(); 97 | input.close(); 98 | client.close(); 99 | } catch (Exception e) { 100 | System.err.println("Exception: " + e.getMessage()); 101 | } 102 | } 103 | } 104 | } 105 | 106 | -------------------------------------------------------------------------------- /python/resources/server/server.intermediate.chain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFejCCA2KgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwZjELMAkGA1UEBhMCR0Ix 3 | EDAOBgNVBAgMB0VuZ2xhbmQxEzARBgNVBAoMCkV4cGVydCBUTFMxFDASBgNVBAsM 4 | C0lUIFRyYWluaW5nMRowGAYDVQQDDBFFeHBlcnQgVExTIEludCBDQTAeFw0yNTA4 5 | MDYwOTUxNDZaFw0yNjA4MTYwOTUxNDZaMGYxCzAJBgNVBAYTAkdCMRAwDgYDVQQI 6 | DAdFbmdsYW5kMRMwEQYDVQQKDApFeHBlcnQgVExTMRQwEgYDVQQLDAtJVCBUcmFp 7 | bmluZzEaMBgGA1UEAwwRRXhwZXJ0IFRMUyBTZXJ2ZXIwggEiMA0GCSqGSIb3DQEB 8 | AQUAA4IBDwAwggEKAoIBAQDBN5SGiXfQNo3CNvRvRAnzT2z63vQAqWreH9Bgfgzn 9 | YSW/NWezAZ3vNGqGkJR0Zv1MSCNo0KJRbosK7Ass/91/5o7bvlr5NZ6psRYqik9Y 10 | wYidZhHHSBKVCKkoc7XkQn2CTOwW3FiOl/aQDoFZFRpUMlRPRkKh2uENKYcnrjWb 11 | EmtF4J+Bs8avfzW1N1APzbKERJqvuo4thuj0P36NX77U0+Z1uljdtlE2qIu501jb 12 | 7GO/sip73nfZFmOsOnSDRDKPlJ8U4BijbOy/LlGMVU2J/runxi1d4pLRa6NniItR 13 | cvFuAIVd60mgiYfOXvq4DAy81RmPIPz8KT66iyDuKZczAgMBAAGjggEwMIIBLDAJ 14 | BgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDAzBglghkgBhvhCAQ0EJhYkT3Bl 15 | blNTTCBHZW5lcmF0ZWQgU2VydmVyIENlcnRpZmljYXRlMB0GA1UdDgQWBBSlJOHi 16 | nu6rrNekNk/YuSKcAVlVbDCBkgYDVR0jBIGKMIGHgBQJxCTev2GFHSHYyQ3eveqL 17 | PhJgcqFrpGkwZzELMAkGA1UEBhMCR0IxEDAOBgNVBAgMB0VuZ2xhbmQxEzARBgNV 18 | BAoMCkV4cGVydCBUTFMxFDASBgNVBAsMC0lUIFRyYWluaW5nMRswGQYDVQQDDBJF 19 | eHBlcnQgVExTIFJvb3QgQ0GCAhAAMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAK 20 | BggrBgEFBQcDATANBgkqhkiG9w0BAQsFAAOCAgEAQIffIBC0K6EhA5F3p8hIJ314 21 | pcmZTCmoJiZ9Z7SKmP9xkQfd8d3vMLXmFGGv9tYSYzzG3b1brgn3bmLCYdtgz4lf 22 | +bhT2iqj1/qeCLF2dTjvsojutbxSF95op9Ks7xH83qxOJdRq0xpdQ8r2h2HrenHa 23 | GYzOrSlcNvUX6Cjs1zrUsFUjrATOelErg/4XLDqlxjOCx4rC/1Lm4RcyXNa4vKZL 24 | HDQmvxHmLI9PLoCPgoNO3xIik3/wa2oIubIhIBZcJ6eRNs5VtxfjGHwujdCVBXRr 25 | ZGzI4AAs/O7CfUVUP5647qPF7rTURv/BQPKNUUxStAD3/yZD3ZeGpR6Eb9XC2FT+ 26 | i7EWqB0lhc5viZV9rz1/H3DxOcemhikEU4nkZdL3IZNReGGC6FwW4hiZq1Cpc63r 27 | 6B5YouYyc9rfN52f9StrUtZbEmVSo6lLDDAPGHkxM21y4aOdfB6PDbxuzdJXT0xu 28 | BChnGu/tS5pGNUlXy1Sxoo0GNFlhFIOOrJaplhc3mQRcvgWGwWO0RL7ST6BuTaP0 29 | vkGhXPla0EbdmtnP4qYcgG0Oj0h5MgLvut0bhj4hQEZV9azZT8bNBjhauyh3p6ZV 30 | mWrUXrUZkJzgfTOzaVOcvv8UiFySdOLuNgw7qUh7342gpzqnzkJ5KQWCYRMeK1fk 31 | H9vS5e996cxVQZgalhc= 32 | -----END CERTIFICATE----- 33 | -----BEGIN CERTIFICATE----- 34 | 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 64 | pr5tpd5cz3O/xysCtjjxDn5Duw== 65 | -----END CERTIFICATE----- 66 | -------------------------------------------------------------------------------- /python/resources/server/server.intermediate.alt.chain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 31 | qe4zfsGG6g/zRunxBz19QA== 32 | -----END CERTIFICATE----- 33 | -----BEGIN CERTIFICATE----- 34 | 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 64 | pr5tpd5cz3O/xysCtjjxDn5Duw== 65 | -----END CERTIFICATE----- 66 | -------------------------------------------------------------------------------- /answers/java/exercise2/SSLServer.java: -------------------------------------------------------------------------------- 1 | package com.tlsexercises.exercise2; 2 | 3 | import javax.net.ServerSocketFactory; 4 | import javax.net.ssl.SSLServerSocket; 5 | import javax.net.ssl.SSLServerSocketFactory; 6 | import java.io.*; 7 | import java.net.Socket; 8 | import java.nio.ByteBuffer; 9 | import java.util.Arrays; 10 | 11 | /** 12 | * Exercise 2 Server\ 13 | */ 14 | public class SSLServer { 15 | 16 | private static final int LOCAL_PORT = 8383; 17 | private static final String KEYSTORE_LOCATION = SSLServer.class.getResource("/server/ServerKeyStore.jks").getPath(); 18 | private static final String KEYSTORE_PASSWORD = "experttls"; 19 | private static final String TRUSTSTORE_LOCATION = SSLServer.class.getResource("/server/ServerTrustStore.jks").getPath(); 20 | private static final String TRUSTSTORE_PASSWORD = "experttls"; // In a real situation these would have different passwords 21 | 22 | // Entry point 23 | public static void main(String argv[]) throws Exception { 24 | // You can also update properties as a command line parameter e.g. 25 | // -Djavax.net.ssl.keyStore="keystore_location" 26 | System.setProperty("javax.net.ssl.keyStore", KEYSTORE_LOCATION); 27 | System.setProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD); 28 | System.setProperty("javax.net.ssl.trustStore", TRUSTSTORE_LOCATION); 29 | System.setProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD); 30 | 31 | SSLServer server = new SSLServer(); 32 | server.startServer(); 33 | } 34 | 35 | // Start server 36 | public void startServer() { 37 | try { 38 | ServerSocketFactory ssf = SSLServerSocketFactory.getDefault(); 39 | SSLServerSocket socket = (SSLServerSocket) ssf.createServerSocket(LOCAL_PORT); 40 | 41 | // Require client authentication 42 | socket.setNeedClientAuth(true); 43 | 44 | System.out.println(String.format("Listening on port %d...", socket.getLocalPort())); 45 | 46 | while (true) { 47 | Socket client = socket.accept(); 48 | ClientHandler handler = new ClientHandler(client); 49 | handler.start(); 50 | } 51 | } catch (Exception e) { 52 | System.out.println("Exception:" + e.getMessage()); 53 | } 54 | } 55 | 56 | /** 57 | * This client handler sends and receives strings via BufferedReader and BufferedWriter 58 | */ 59 | class ClientHandler extends Thread { 60 | 61 | Socket client; 62 | BufferedReader input; 63 | BufferedWriter output; 64 | 65 | public ClientHandler(Socket s) { // constructor 66 | client = s; 67 | 68 | try { 69 | input = new BufferedReader(new InputStreamReader(client.getInputStream())); 70 | output = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 71 | } catch (IOException e) { 72 | System.err.println("Error creating streams: " + e.getMessage()); 73 | } 74 | } 75 | 76 | public void run() { 77 | try { 78 | // Obtain client message and use it 79 | String request = input.readLine(); 80 | System.out.println("Received from Client: " + request); 81 | 82 | output.write("HTTP/1.0 200 OK\nContent-type: text/html\n" + 83 | "\n" + 84 | " \n" + 85 | " Tiny Website\n" + 86 | " \n" + 87 | " \n" + 88 | " A very small website!\n" + 89 | " \n" + 90 | "\n"); 91 | output.flush(); 92 | 93 | // Close streams and socket 94 | output.close(); 95 | input.close(); 96 | client.close(); 97 | } catch (Exception e) { 98 | System.err.println("Exception: " + e.getMessage()); 99 | } 100 | } 101 | } 102 | } 103 | 104 | -------------------------------------------------------------------------------- /python/exercise3/SSLServer.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import ssl 3 | import threading 4 | from pathlib import Path 5 | import select 6 | from datatypes import BankCustomer 7 | import pickle 8 | 9 | LOCAL_HOST = 'localhost' 10 | LOCAL_PORT = 8484 11 | RESOURCE_DIRECTORY = Path(__file__).resolve().parent.parent / 'resources' / 'server' 12 | SERVER_CERT_CHAIN = RESOURCE_DIRECTORY / 'server.intermediate.chain.pem' 13 | SERVER_KEY = RESOURCE_DIRECTORY / 'server.key.pem' 14 | 15 | # Part 2: Server 16 | # In this exercise the server requires no additional code. 17 | # 18 | # When testing, you can alternate which set of certificates you use by running either this server 19 | # or the imposter. 20 | # 21 | # For help check out: 22 | # https://github.com/mikepound/tls-exercises/blob/master/python/README.md 23 | 24 | class SSLServer: 25 | """ 26 | Exercise 3 "Official" Server 27 | """ 28 | def __init__(self): 29 | """ 30 | Creates an SSLContext which provides parameters for any future SSL connections 31 | """ 32 | context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) 33 | context.load_cert_chain(certfile=SERVER_CERT_CHAIN, keyfile=SERVER_KEY) 34 | self.context = context 35 | 36 | def start_server(self): 37 | """ 38 | Begins listening on a socket. Any connections that arrive are wrapped in an SSLSocket using the context 39 | created during initialisation. 40 | 41 | Makes use of the OS select function to perform basic non-blocking IO. Once a connection has established 42 | an instance of ClientHandler is created to serve the client 43 | """ 44 | server_socket = socket.socket() 45 | server_socket.bind((LOCAL_HOST, LOCAL_PORT)) 46 | server_socket.listen(5) 47 | read_list = [server_socket] 48 | 49 | print("Listening on port {0}...".format(LOCAL_PORT)) 50 | 51 | while True: 52 | readable, writable, errored = select.select(read_list, [], [], 2) 53 | for s in readable: 54 | if s is server_socket: 55 | client_socket, address = server_socket.accept() 56 | try: 57 | # Wrap the socket in an SSL connection (will perform a handshake) 58 | conn = self.context.wrap_socket(client_socket, server_side=True) 59 | ClientHandler(conn).start() 60 | except ssl.SSLError as e: 61 | print(e) 62 | 63 | 64 | class ClientHandler(threading.Thread): 65 | """ 66 | Thread handler leaves the main thread free to handle any other incoming connections 67 | """ 68 | def __init__(self, conn): 69 | threading.Thread.__init__(self) 70 | self.conn = conn 71 | 72 | def run(self): 73 | try: 74 | # Read up to 1024 bytes from the client 75 | client_request = self.conn.recv(1024) 76 | 77 | # Parse an int containing a bank customer id 78 | requested_id = int.from_bytes(client_request, 'big') 79 | print("Received from client:", requested_id) 80 | 81 | # Send back a customer matching this id 82 | example_customer = BankCustomer(requested_id, 83 | "Matthew Jones", 84 | "matthew.jones@example.com", 85 | 84127843, 86 | 200265, 87 | "14 A Lane", 88 | "A District", 89 | "A Town", 90 | "NR1 ABC") 91 | 92 | # We need to send bytes, python's pickling makes this simple 93 | self.conn.send(pickle.dumps(example_customer)) 94 | 95 | except ssl.SSLError as e: 96 | print(e) 97 | except Exception as e: 98 | print(e) 99 | finally: 100 | self.conn.close() 101 | 102 | 103 | def main(): 104 | server = SSLServer() 105 | server.start_server() 106 | 107 | 108 | if __name__ == '__main__': 109 | main() 110 | -------------------------------------------------------------------------------- /answers/java/exercise1/SSLServer.java: -------------------------------------------------------------------------------- 1 | package com.tlsexercises.exercise1; 2 | 3 | import java.io.*; 4 | import java.net.*; 5 | import java.util.Arrays; 6 | import javax.net.ServerSocketFactory; 7 | import javax.net.ssl.*; 8 | import java.nio.*; 9 | 10 | /** 11 | * Exercise 1 Server 12 | */ 13 | public class SSLServer { 14 | 15 | private static final int LOCAL_PORT = 8282; 16 | private static final String KEYSTORE_LOCATION = SSLServer.class.getResource("/server/ServerKeyStore.jks").getPath(); 17 | private static final String KEYSTORE_PASSWORD = "experttls"; 18 | 19 | // Entry point 20 | public static void main(String argv[]) throws Exception { 21 | // You can also update properties as a command line parameter e.g. 22 | // -Djavax.net.ssl.keyStore="keystore_location" 23 | System.setProperty("javax.net.ssl.keyStore", KEYSTORE_LOCATION); 24 | System.setProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD); 25 | 26 | SSLServer server = new SSLServer(); 27 | server.startServer(); 28 | } 29 | 30 | // Start server 31 | public void startServer() { 32 | try { 33 | ServerSocketFactory ssf = SSLServerSocketFactory.getDefault(); 34 | SSLServerSocket socket = (SSLServerSocket) ssf.createServerSocket(LOCAL_PORT); 35 | 36 | // Part 2: You can add code here to limit the protocols and suites the server may use 37 | // Note: If the server and client don't share at least one cipher suite in common, 38 | // you can expect the handshake to fail. 39 | socket.setEnabledCipherSuites(new String[]{ "TLS_AES_128_GCM_SHA256", "TLS_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" }); 40 | socket.setEnabledProtocols(new String[]{ "TLSv1.3", "TLSv1.2" }); 41 | 42 | System.out.println(String.format("Listening on port %d...", socket.getLocalPort())); 43 | 44 | while (true) { 45 | Socket client = socket.accept(); 46 | ClientHandler handler = new ClientHandler(client); 47 | handler.start(); 48 | } 49 | } catch (Exception e) { 50 | System.out.println("Exception:" + e.getMessage()); 51 | } 52 | } 53 | 54 | /** 55 | * This nested class handles any new clients that appear. This frees the main thread to continue 56 | * receiving new clients and performing handshakes. 57 | * 58 | * This particular handler sends and receives bytes via buffered input and output streams 59 | */ 60 | class ClientHandler extends Thread { 61 | 62 | Socket client; 63 | BufferedInputStream input; 64 | BufferedOutputStream output; 65 | 66 | public ClientHandler(Socket s) { // constructor 67 | client = s; 68 | 69 | try { 70 | input = new BufferedInputStream(client.getInputStream()); 71 | output = new BufferedOutputStream(client.getOutputStream()); 72 | } catch (IOException e) { 73 | System.err.println("Error creating streams: " + e.getMessage()); 74 | } 75 | } 76 | 77 | public void run() { 78 | try { 79 | // Obtain client message and use it 80 | byte[] clientMessage = new byte[64]; 81 | int len = input.read(clientMessage, 0, 64); 82 | int total = 1; 83 | for (int i = 0; i < len; i++) { 84 | total *= clientMessage[i]; 85 | } 86 | 87 | System.out.println("Received from Client: " + Arrays.toString(Arrays.copyOfRange(clientMessage, 0, len))); 88 | 89 | // Return product of client's byte values 90 | ByteBuffer buff = ByteBuffer.allocate(4).putInt(total); 91 | output.write(buff.array()); 92 | output.flush(); 93 | 94 | // Close streams and socket 95 | output.close(); 96 | input.close(); 97 | client.close(); 98 | } catch (Exception e) { 99 | System.err.println("Exception: " + e.getMessage()); 100 | } 101 | } 102 | } 103 | } 104 | 105 | -------------------------------------------------------------------------------- /java/src/main/java/com/tlsexercises/exercise2/SSLServer.java: -------------------------------------------------------------------------------- 1 | package com.tlsexercises.exercise2; 2 | 3 | import javax.net.ServerSocketFactory; 4 | import javax.net.ssl.SSLServerSocket; 5 | import javax.net.ssl.SSLServerSocketFactory; 6 | import java.io.*; 7 | import java.net.Socket; 8 | import java.nio.ByteBuffer; 9 | import java.util.Arrays; 10 | 11 | /** 12 | * Exercise 2 Server 13 | */ 14 | public class SSLServer { 15 | 16 | private static final int LOCAL_PORT = 8383; 17 | private static final String KEYSTORE_LOCATION = SSLServer.class.getResource("/server/ServerKeyStore.jks").getPath(); 18 | private static final String KEYSTORE_PASSWORD = "experttls"; 19 | 20 | // Entry point 21 | public static void main(String argv[]) throws Exception { 22 | // You can also update properties as a command line parameter e.g. 23 | // -Djavax.net.ssl.keyStore="keystore_location" 24 | System.setProperty("javax.net.ssl.keyStore", KEYSTORE_LOCATION); 25 | System.setProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD); 26 | 27 | // Part 1 28 | // In order to verify the client, this server requires a trust store. Use setProperty commands to 29 | // load a trustStore. You'll also need some static variables above as with the keystore implementation. 30 | // 31 | // For help check out: 32 | // https://github.com/mikepound/tls-exercises/blob/master/java/README.md 33 | 34 | SSLServer server = new SSLServer(); 35 | server.startServer(); 36 | } 37 | 38 | // Start server 39 | public void startServer() { 40 | try { 41 | ServerSocketFactory ssf = SSLServerSocketFactory.getDefault(); 42 | SSLServerSocket socket = (SSLServerSocket) ssf.createServerSocket(LOCAL_PORT); 43 | 44 | // Part 1 45 | // Add code here to enable client-side authentication. The server will then request the client 46 | // certificate during the handshake 47 | // 48 | // For help check out: 49 | // https://github.com/mikepound/tls-exercises/blob/master/java/README.md 50 | 51 | System.out.println(String.format("Listening on port %d...", socket.getLocalPort())); 52 | 53 | while (true) { 54 | Socket client = socket.accept(); 55 | ClientHandler handler = new ClientHandler(client); 56 | handler.start(); 57 | } 58 | } catch (Exception e) { 59 | System.out.println("Exception:" + e.getMessage()); 60 | } 61 | } 62 | 63 | /** 64 | * This client handler sends and receives strings via BufferedReader and BufferedWriter 65 | */ 66 | class ClientHandler extends Thread { 67 | 68 | Socket client; 69 | BufferedReader input; 70 | BufferedWriter output; 71 | 72 | public ClientHandler(Socket s) { // constructor 73 | client = s; 74 | 75 | try { 76 | input = new BufferedReader(new InputStreamReader(client.getInputStream())); 77 | output = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 78 | } catch (IOException e) { 79 | System.err.println("Error creating streams: " + e.getMessage()); 80 | } 81 | } 82 | 83 | public void run() { 84 | try { 85 | // Obtain client message and use it 86 | String request = input.readLine(); 87 | System.out.println("Received from Client: " + request); 88 | 89 | output.write("HTTP/1.0 200 OK\nContent-type: text/html\n" + 90 | "\n" + 91 | " \n" + 92 | " Tiny Website\n" + 93 | " \n" + 94 | " \n" + 95 | " A very small website!\n" + 96 | " \n" + 97 | "\n"); 98 | output.flush(); 99 | 100 | // Close streams and socket 101 | output.close(); 102 | input.close(); 103 | client.close(); 104 | } catch (Exception e) { 105 | System.err.println("Exception: " + e.getMessage()); 106 | } 107 | } 108 | } 109 | } 110 | 111 | -------------------------------------------------------------------------------- /ca/openssl.cfg: -------------------------------------------------------------------------------- 1 | # OpenSSL root CA configuration file. 2 | # Copy to `/root/ca/openssl.cnf`. 3 | 4 | [ ca ] 5 | # `man ca` 6 | default_ca = CA_default 7 | 8 | [ CA_default ] 9 | # Directory and file locations. 10 | dir = . 11 | certs = $dir/certs 12 | crl_dir = $dir/crl 13 | new_certs_dir = $dir/newcerts 14 | database = $dir/index.txt 15 | serial = $dir/serial 16 | RANDFILE = $dir/private/.rand 17 | 18 | # The root key and root certificate. 19 | private_key = $dir/private/ca.key.pem 20 | certificate = $dir/certs/ca.cert.pem 21 | 22 | # For certificate revocation lists. 23 | crlnumber = $dir/crlnumber 24 | crl = $dir/crl/ca.crl.pem 25 | crl_extensions = crl_ext 26 | default_crl_days = 30 27 | 28 | # SHA-1 is deprecated, so use SHA-2 instead. 29 | default_md = sha256 30 | 31 | name_opt = ca_default 32 | cert_opt = ca_default 33 | default_days = 375 34 | preserve = no 35 | policy = policy_strict 36 | 37 | [ policy_strict ] 38 | # The root CA should only sign intermediate certificates that match. 39 | # See the POLICY FORMAT section of `man ca`. 40 | countryName = match 41 | stateOrProvinceName = match 42 | organizationName = match 43 | organizationalUnitName = optional 44 | commonName = supplied 45 | emailAddress = optional 46 | 47 | [ policy_loose ] 48 | # Allow the intermediate CA to sign a more diverse range of certificates. 49 | # See the POLICY FORMAT section of the `ca` man page. 50 | countryName = optional 51 | stateOrProvinceName = optional 52 | localityName = optional 53 | organizationName = optional 54 | organizationalUnitName = optional 55 | commonName = supplied 56 | emailAddress = optional 57 | 58 | [ req ] 59 | # Options for the `req` tool (`man req`). 60 | default_bits = 2048 61 | distinguished_name = req_distinguished_name 62 | string_mask = utf8only 63 | 64 | # SHA-1 is deprecated, so use SHA-2 instead. 65 | default_md = sha256 66 | 67 | # Extension to add when the -x509 option is used. 68 | x509_extensions = v3_ca 69 | 70 | [ req_distinguished_name ] 71 | # See . 72 | countryName = Country Name (2 letter code) 73 | stateOrProvinceName = State or Province Name 74 | localityName = Locality Name 75 | 0.organizationName = Organization Name 76 | organizationalUnitName = Organizational Unit Name 77 | commonName = Common Name 78 | emailAddress = Email Address 79 | 80 | # Optionally, specify some defaults. 81 | countryName_default = GB 82 | stateOrProvinceName_default = England 83 | localityName_default = 84 | 0.organizationName_default = Expert TLS 85 | organizationalUnitName_default = IT Training 86 | emailAddress_default = 87 | 88 | [ v3_ca ] 89 | # Extensions for a typical CA (`man x509v3_config`). 90 | subjectKeyIdentifier = hash 91 | authorityKeyIdentifier = keyid:always,issuer 92 | basicConstraints = critical, CA:true 93 | keyUsage = critical, digitalSignature, cRLSign, keyCertSign 94 | 95 | [ v3_intermediate_ca ] 96 | # Extensions for a typical intermediate CA (`man x509v3_config`). 97 | subjectKeyIdentifier = hash 98 | authorityKeyIdentifier = keyid:always,issuer 99 | basicConstraints = critical, CA:true, pathlen:0 100 | keyUsage = critical, digitalSignature, cRLSign, keyCertSign 101 | 102 | [ usr_cert ] 103 | # Extensions for client certificates (`man x509v3_config`). 104 | basicConstraints = CA:FALSE 105 | nsCertType = client, email 106 | nsComment = "OpenSSL Generated Client Certificate" 107 | subjectKeyIdentifier = hash 108 | authorityKeyIdentifier = keyid,issuer 109 | keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment 110 | extendedKeyUsage = clientAuth, emailProtection 111 | 112 | [ server_cert ] 113 | # Extensions for server certificates (`man x509v3_config`). 114 | basicConstraints = CA:FALSE 115 | nsCertType = server 116 | nsComment = "OpenSSL Generated Server Certificate" 117 | subjectKeyIdentifier = hash 118 | authorityKeyIdentifier = keyid,issuer:always 119 | keyUsage = critical, digitalSignature, keyEncipherment 120 | extendedKeyUsage = serverAuth 121 | 122 | [ crl_ext ] 123 | # Extension for CRLs (`man x509v3_config`). 124 | authorityKeyIdentifier=keyid:always 125 | 126 | [ ocsp ] 127 | # Extension for OCSP signing certificates (`man ocsp`). 128 | basicConstraints = CA:FALSE 129 | subjectKeyIdentifier = hash 130 | authorityKeyIdentifier = keyid,issuer 131 | keyUsage = critical, digitalSignature 132 | extendedKeyUsage = critical, OCSPSigning -------------------------------------------------------------------------------- /ca/intermediate/openssl.cfg: -------------------------------------------------------------------------------- 1 | # OpenSSL intermediate CA configuration file. 2 | # Copy to `/root/ca/intermediate/openssl.cnf`. 3 | 4 | [ ca ] 5 | # `man ca` 6 | default_ca = CA_default 7 | 8 | [ CA_default ] 9 | # Directory and file locations. 10 | dir = ./intermediate 11 | certs = $dir/certs 12 | crl_dir = $dir/crl 13 | new_certs_dir = $dir/newcerts 14 | database = $dir/index.txt 15 | serial = $dir/serial 16 | RANDFILE = $dir/private/.rand 17 | 18 | # The root key and root certificate. 19 | private_key = $dir/private/intermediate.key.pem 20 | certificate = $dir/certs/intermediate.cert.pem 21 | 22 | # For certificate revocation lists. 23 | crlnumber = $dir/crlnumber 24 | crl = $dir/crl/intermediate.crl.pem 25 | crl_extensions = crl_ext 26 | default_crl_days = 30 27 | 28 | # SHA-1 is deprecated, so use SHA-2 instead. 29 | default_md = sha256 30 | 31 | name_opt = ca_default 32 | cert_opt = ca_default 33 | default_days = 375 34 | preserve = no 35 | policy = policy_loose 36 | 37 | [ policy_strict ] 38 | # The root CA should only sign intermediate certificates that match. 39 | # See the POLICY FORMAT section of `man ca`. 40 | countryName = match 41 | stateOrProvinceName = match 42 | organizationName = match 43 | organizationalUnitName = optional 44 | commonName = supplied 45 | emailAddress = optional 46 | 47 | [ policy_loose ] 48 | # Allow the intermediate CA to sign a more diverse range of certificates. 49 | # See the POLICY FORMAT section of the `ca` man page. 50 | countryName = optional 51 | stateOrProvinceName = optional 52 | localityName = optional 53 | organizationName = optional 54 | organizationalUnitName = optional 55 | commonName = supplied 56 | emailAddress = optional 57 | 58 | [ req ] 59 | # Options for the `req` tool (`man req`). 60 | default_bits = 2048 61 | distinguished_name = req_distinguished_name 62 | string_mask = utf8only 63 | 64 | # SHA-1 is deprecated, so use SHA-2 instead. 65 | default_md = sha256 66 | 67 | # Extension to add when the -x509 option is used. 68 | x509_extensions = v3_ca 69 | 70 | [ req_distinguished_name ] 71 | # See . 72 | countryName = Country Name (2 letter code) 73 | stateOrProvinceName = State or Province Name 74 | localityName = Locality Name 75 | 0.organizationName = Organization Name 76 | organizationalUnitName = Organizational Unit Name 77 | commonName = Common Name 78 | emailAddress = Email Address 79 | 80 | # Optionally, specify some defaults. 81 | countryName_default = GB 82 | stateOrProvinceName_default = England 83 | localityName_default = 84 | 0.organizationName_default = Expert TLS 85 | organizationalUnitName_default = IT Training 86 | emailAddress_default = 87 | 88 | [ v3_ca ] 89 | # Extensions for a typical CA (`man x509v3_config`). 90 | subjectKeyIdentifier = hash 91 | authorityKeyIdentifier = keyid:always,issuer 92 | basicConstraints = critical, CA:true 93 | keyUsage = critical, digitalSignature, cRLSign, keyCertSign 94 | 95 | [ v3_intermediate_ca ] 96 | # Extensions for a typical intermediate CA (`man x509v3_config`). 97 | subjectKeyIdentifier = hash 98 | authorityKeyIdentifier = keyid:always,issuer 99 | basicConstraints = critical, CA:true, pathlen:0 100 | keyUsage = critical, digitalSignature, cRLSign, keyCertSign 101 | 102 | [ usr_cert ] 103 | # Extensions for client certificates (`man x509v3_config`). 104 | basicConstraints = CA:FALSE 105 | nsCertType = client, email 106 | nsComment = "OpenSSL Generated Client Certificate" 107 | subjectKeyIdentifier = hash 108 | authorityKeyIdentifier = keyid,issuer 109 | keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment 110 | extendedKeyUsage = clientAuth, emailProtection 111 | 112 | [ server_cert ] 113 | # Extensions for server certificates (`man x509v3_config`). 114 | basicConstraints = CA:FALSE 115 | nsCertType = server 116 | nsComment = "OpenSSL Generated Server Certificate" 117 | subjectKeyIdentifier = hash 118 | authorityKeyIdentifier = keyid,issuer:always 119 | keyUsage = critical, digitalSignature, keyEncipherment 120 | extendedKeyUsage = serverAuth 121 | 122 | [ crl_ext ] 123 | # Extension for CRLs (`man x509v3_config`). 124 | authorityKeyIdentifier=keyid:always 125 | 126 | [ ocsp ] 127 | # Extension for OCSP signing certificates (`man ocsp`). 128 | basicConstraints = CA:FALSE 129 | subjectKeyIdentifier = hash 130 | authorityKeyIdentifier = keyid,issuer 131 | keyUsage = critical, digitalSignature 132 | extendedKeyUsage = critical, OCSPSigning -------------------------------------------------------------------------------- /java/src/main/java/com/tlsexercises/exercise3/SSLClient.java: -------------------------------------------------------------------------------- 1 | package com.tlsexercises.exercise3; 2 | 3 | import javax.net.ssl.*; 4 | import java.io.*; 5 | import java.security.*; 6 | import java.security.cert.X509Certificate; 7 | import java.security.cert.CertificateException; 8 | import java.util.Arrays; 9 | 10 | /** 11 | * Exercise 3 Client 12 | */ 13 | public class SSLClient { 14 | 15 | private static final String REMOTE_HOST = "localhost"; 16 | private static final int REMOTE_PORT = 8484; 17 | private static final String TRUSTSTORE_LOCATION = SSLClient.class.getResource("/client/ClientTrustStore.jks").getPath(); 18 | private static final String TRUSTSTORE_PASSWORD = "experttls"; 19 | 20 | private static final byte[] SERVER_PINNED_HASH; 21 | static { 22 | SERVER_PINNED_HASH = new byte[32]; 23 | try { 24 | SSLClient.class.getResourceAsStream("/client/pinned.hash").read(SERVER_PINNED_HASH,0,32); 25 | } catch (Exception e) { 26 | throw new ExceptionInInitializerError("Unable to load server pinset."); 27 | } 28 | } 29 | 30 | // Entry point 31 | public static void main(String[] args) { 32 | // You can also update properties as a command line parameter e.g. 33 | // -Djavax.net.ssl.keyStore="keystore_location" 34 | System.setProperty("javax.net.ssl.trustStore", TRUSTSTORE_LOCATION); 35 | System.setProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD); 36 | 37 | TrustManagerFactory tmf = null; 38 | 39 | try { 40 | // Default is likely to be PKIX, but could be SunX509 on some systems 41 | String def = TrustManagerFactory.getDefaultAlgorithm(); 42 | tmf = TrustManagerFactory.getInstance(def); 43 | 44 | // Using null here initialises the default trust store, which in this case is loaded from the above properties 45 | tmf.init((KeyStore) null); 46 | } catch (KeyStoreException e) { 47 | System.err.println("Keystore Exception: " + e.getMessage()); 48 | } catch (NoSuchAlgorithmException e) { 49 | System.err.println("Unable to obtain a trust manager: " + e.getMessage()); 50 | } 51 | 52 | // Get hold of the default trust manager - will only return one as we only specified one algorithm above. 53 | X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0]; 54 | 55 | // Wrap it in your own class. 56 | X509TrustManager pinningX509TrustManager = new X509TrustManager() { 57 | 58 | @Override 59 | public X509Certificate[] getAcceptedIssuers() { 60 | // Pass through 61 | return defaultTrustManager.getAcceptedIssuers(); 62 | } 63 | 64 | @Override 65 | public void checkServerTrusted(X509Certificate[] chain, 66 | String authType) throws CertificateException { 67 | // Use default trust manager to verify certificate chain 68 | defaultTrustManager.checkServerTrusted(chain, authType); 69 | 70 | // Part 1: Client 71 | // Here you need to add hashing validation against the received 72 | // certificate, comparing it to the hash you have on file in 'pinned.hash'. 73 | 74 | // For help check out: 75 | // https://github.com/mikepound/tls-exercises/blob/master/java/README.md 76 | 77 | } 78 | 79 | @Override 80 | public void checkClientTrusted(X509Certificate[] chain, 81 | String authType) throws CertificateException { 82 | // We could validate client certs here, but it is out of scope for what we want to do 83 | throw new CertificateException("This trust manager does not verify client certificates"); 84 | } 85 | }; 86 | 87 | // Obtain the default socket factory 88 | SSLContext context = null; 89 | SSLSocketFactory f = null; 90 | try { 91 | context = SSLContext.getInstance("TLS"); 92 | context.init(null, new TrustManager[] { pinningX509TrustManager }, null); 93 | f = context.getSocketFactory(); 94 | } catch (Exception e) { 95 | System.err.println("Error establishing SSL context and factory"); 96 | System.err.println(e.toString()); 97 | System.exit(-1); 98 | } 99 | 100 | try { 101 | // Create a socket - will not connect yet 102 | SSLSocket socket = (SSLSocket) f.createSocket(REMOTE_HOST, REMOTE_PORT); 103 | 104 | // Handshake to create a session 105 | socket.startHandshake(); 106 | 107 | // What parameters were established? 108 | System.out.println(String.format("Negotiated Session: %s", socket.getSession().getProtocol())); 109 | System.out.println(String.format("Cipher Suite: %s", socket.getSession().getCipherSuite())); 110 | 111 | // We're reading and writing objects this time 112 | ObjectInputStream input = new ObjectInputStream(socket.getInputStream()); 113 | ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream()); 114 | 115 | // Obtain bank customer from DB 116 | output.writeInt(100124796); 117 | output.flush(); 118 | 119 | // Read the BankCustomer returned by the server. 120 | System.out.println("Server Response:"); 121 | BankCustomer customer = (BankCustomer) input.readObject(); 122 | 123 | System.out.println(customer); 124 | 125 | input.close(); 126 | output.close(); 127 | socket.close(); 128 | } catch (Exception e) { 129 | System.err.println("Exception: " + e.toString()); 130 | } 131 | } 132 | } -------------------------------------------------------------------------------- /answers/java/exercise3/SSLClient.java: -------------------------------------------------------------------------------- 1 | package com.tlsexercises.exercise3; 2 | 3 | import javax.net.ssl.*; 4 | import java.io.*; 5 | import java.security.*; 6 | import java.security.cert.X509Certificate; 7 | import java.security.cert.CertificateException; 8 | import java.util.Arrays; 9 | 10 | /** 11 | * Exercise 3 Client 12 | */ 13 | public class SSLClient { 14 | 15 | private static final String REMOTE_HOST = "localhost"; 16 | private static final int REMOTE_PORT = 8484; 17 | private static final String TRUSTSTORE_LOCATION = SSLClient.class.getResource("/client/ClientTrustStore.jks").getPath(); 18 | private static final String TRUSTSTORE_PASSWORD = "experttls"; 19 | 20 | private static final byte[] SERVER_PINNED_HASH; 21 | static { 22 | SERVER_PINNED_HASH = new byte[32]; 23 | try { 24 | SSLClient.class.getResourceAsStream("/client/pinned.hash").read(SERVER_PINNED_HASH,0,32); 25 | } catch (Exception e) { 26 | throw new ExceptionInInitializerError("Unable to load server pinset."); 27 | } 28 | } 29 | 30 | // Entry point 31 | public static void main(String[] args) { 32 | // You can also update properties as a command line parameter e.g. 33 | // -Djavax.net.ssl.keyStore="keystore_location" 34 | System.setProperty("javax.net.ssl.trustStore", TRUSTSTORE_LOCATION); 35 | System.setProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD); 36 | 37 | TrustManagerFactory tmf = null; 38 | 39 | try { 40 | // Default is likely to be PKIX, but could be SunX509 on some systems 41 | String def = TrustManagerFactory.getDefaultAlgorithm(); 42 | tmf = TrustManagerFactory.getInstance(def); 43 | 44 | // Using null here initialises the default trust store, which in this case is loaded from the above properties 45 | tmf.init((KeyStore) null); 46 | } catch (KeyStoreException e) { 47 | System.err.println("Keystore Exception: " + e.getMessage()); 48 | } catch (NoSuchAlgorithmException e) { 49 | System.err.println("Unable to obtain a trust manager: " + e.getMessage()); 50 | } 51 | 52 | // Get hold of the default trust manager - will only return one as we only specified one algorithm above. 53 | X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0]; 54 | 55 | // Wrap it in your own class. 56 | X509TrustManager pinningX509TrustManager = new X509TrustManager() { 57 | 58 | @Override 59 | public X509Certificate[] getAcceptedIssuers() { 60 | // Pass through 61 | return defaultTrustManager.getAcceptedIssuers(); 62 | } 63 | 64 | @Override 65 | public void checkServerTrusted(X509Certificate[] chain, 66 | String authType) throws CertificateException { 67 | // Use default trust manager to verify certificate chain 68 | defaultTrustManager.checkServerTrusted(chain, authType); 69 | 70 | // The first certificate in the chain 71 | X509Certificate serverCert = chain[0]; 72 | 73 | // .getEncoded returns a DER encoding of the certificate, which should match our pinned hash 74 | byte[] certBytes = serverCert.getEncoded(); 75 | 76 | // Hash the certificate 77 | byte[] serverHash = null; 78 | MessageDigest digest = null; 79 | try { 80 | digest = MessageDigest.getInstance("SHA-256"); 81 | serverHash = digest.digest(certBytes); 82 | } catch (NoSuchAlgorithmException e) { 83 | throw new CertificateException("Unable to load SHA-256 digest and verify pinned certificate"); 84 | } 85 | 86 | // Verify against pinned certificate hash 87 | if (!Arrays.equals(SERVER_PINNED_HASH, serverHash)) { 88 | throw new CertificateException("The host's certificate has not been pinned by this application"); 89 | } 90 | } 91 | 92 | @Override 93 | public void checkClientTrusted(X509Certificate[] chain, 94 | String authType) throws CertificateException { 95 | // We could validate client certs here, but it is out of scope for what we want to do 96 | throw new CertificateException("This trust manager does not verify client certificates"); 97 | } 98 | }; 99 | 100 | // Obtain the default socket factory 101 | SSLContext context = null; 102 | SSLSocketFactory f = null; 103 | try { 104 | context = SSLContext.getInstance("TLS"); 105 | context.init(null, new TrustManager[] { pinningX509TrustManager }, null); 106 | f = context.getSocketFactory(); 107 | } catch (Exception e) { 108 | System.err.println("Error establishing SSL context and factory"); 109 | System.err.println(e.toString()); 110 | System.exit(-1); 111 | } 112 | 113 | try { 114 | // Create a socket - will not connect yet 115 | SSLSocket socket = (SSLSocket) f.createSocket(REMOTE_HOST, REMOTE_PORT); 116 | 117 | // Handshake to create a session 118 | socket.startHandshake(); 119 | 120 | // What parameters were established? 121 | System.out.println(String.format("Negotiated Session: %s", socket.getSession().getProtocol())); 122 | System.out.println(String.format("Cipher Suite: %s", socket.getSession().getCipherSuite())); 123 | 124 | // We're reading and writing objects this time 125 | ObjectInputStream input = new ObjectInputStream(socket.getInputStream()); 126 | ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream()); 127 | 128 | // Obtain bank customer from DB 129 | output.writeInt(100124796); 130 | output.flush(); 131 | 132 | // Read the BankCustomer returned by the server. 133 | System.out.println("Server Response:"); 134 | BankCustomer customer = (BankCustomer) input.readObject(); 135 | 136 | System.out.println(customer); 137 | 138 | input.close(); 139 | output.close(); 140 | socket.close(); 141 | } catch (Exception e) { 142 | System.err.println("Exception: " + e.toString()); 143 | } 144 | } 145 | } -------------------------------------------------------------------------------- /python/README.md: -------------------------------------------------------------------------------- 1 | # Python Exercises 2 | These exercises have been written and tested in Python 3.6 and 3.7. Support for TLS differs between versions of Python, I would recommend using the most recent version you can. If you need reliable TLS connections in an older version of python, you might consider the [pyOpenSSL](https://github.com/pyca/pyopenssl) project for TLS, and [Cryptography](https://github.com/pyca/cryptography) for X509 certificate management. These exercises can be run from the command line, but I used [PyCharm](https://www.jetbrains.com/pycharm/). 3 | 4 | ## Exercise 1: Setting up a TLS Connection 5 | In this exercise you have a completely working server. It will negotiate TLS sessions and the communicate with clients. Once set up, the server simply recieves lists of bytes, and then returns the product of all of the numbers received. E.g. [2,5,6] -> 60. 6 | 7 | The client is less complete, at the start of the exercise it has code missing, so it won't connect to a server, and without an available socket, it will simply exit. 8 | 9 | #### Part 1: Connecting with the client 10 | The client doesn't have a working socket implementation. To begin you need to create a new `socket.socket`, create an `SSLContext` with appropriate configuration, and then use this to wrap the socket into an `SSLSocket`. 11 | 12 | While you work, it'd be useful to have the [socket](https://docs.python.org/3.6/library/socket.html) and [ssl](https://docs.python.org/3.6/library/ssl.html) documentation to hand. You can now either get stuck in using the existing code and documentation, or follow along below for a little more advice. 13 | 14 | 1) Begin by creating a new socket using the `socket.socket()` function. Make sure it's of the `AF_INET` type. 15 | 2) Obtain the default ssl context via the `ssl.create_default_context()` function. The purpose for this one is to authenticate servers: `ssl.Purpose.SERVER_AUTH`. 16 | 3) Continuing with the context, load the CA certificate via the `context.load_verify_locations()` function. This ensures that the client knows which root certificate to validate against. 17 | 4) Now we need a connection. Wrap the original socket into an SSLSocket using `context.wrap_socket()` (see [documentation](https://docs.python.org/3.6/library/ssl.html#ssl.SSLContext.wrap_socket)). We're calling this socket `conn`. Note: You'll need to set the `server_hostname` parameter, which must match the incoming certificate hostname of "Expert TLS Server" 18 | 5) Inside the try-catch block, make use of the sockets `connect()` function, which will expect a tuple containing the hostname and port defined at the top of the file. 19 | 20 | Don't forget to start the server, too! With any luck, this should now connect nicely. 21 | 22 | #### Part 2: Specifying protocols and cipher suites 23 | TLS works by ordering available cipher suites by preference. You can control what ciphers are used simply by putting the weaker ones at the end. Given you have full control over both the client and server implementations, it's actually easier and safer simply to disable all but the strongest ciphers and protocols. 24 | 25 | 1) Specify `context.options` to disable everything except TLS 1.3 and 1.2 (see [documentation](https://docs.python.org/3.6/library/ssl.html#ssl.SSLContext.options)). Depending on your build and python version, TLS 1.3 may not be available for you, so be sure to leave 1.2 enabled. 26 | 2) Use the `context.set_ciphers()` function to list ciphers you are happy to use. This requires a string in the [OpenSSL cipher list format](https://www.openssl.org/docs/manmaster/man1/ciphers.html). This interface is extremely unintuitive! By way of example: 27 | `'ALL:!DSS:!DHE:!aNULL:!eNull'` will enable all ciphers except those that use the digital signature scheme, non EC diffie-hellman, and any that don't provide encryption or authentication. If you have TLS1.3 enabled, you will find you can't disable these ciphers. 28 | 29 | You can make these changes to both the client and the server. 30 | 31 | #### Extra credit! 32 | Have a play around with the different cipher suites. You'll find it's quite easy to break your TLS connection when the server and client don't have at least one valid protocol (e.g. TLS1.2) and one cipher suite between them. The client will usually not provide an informative error message, but check the server's console output. 33 | 34 | ## Exercise 2: Mutual Authentication 35 | In this exercise both the client and server already work, but we are only authenticating the server. You need to add code to both in order to achieve a mutually authenticated session. The client and server here sent a simple HTTP GET request, and an HTML response. 36 | 37 | #### Part 1: The Server 38 | The server needs to request a certificate from the client. Make use of the [documentation](https://docs.python.org/3.6/library/ssl.html#ssl.SSLContext). 39 | 40 | 1) Within the server `__init__` the context is configured. Add code to set the `verify_mode` to `ssl.CERT_REQUIRED`. 41 | 2) Provide the server with the root CA certificate to be able to validate the client certificate when it arrives. It's already in the resource folder for the server. Define it as a resource at the top, then use the `load_verify_locations()` function to provide it. 42 | 43 | If you run the server and client now, you'll find the server should reject the client as it doesn't provide a certificate. 44 | 45 | #### Part 2: The Client 46 | 47 | Setting up the client to provide a certificate is the same code the server already contains to provide its own. 48 | 49 | 1) The certificates and keys are in the client resource directory. Define `CLIENT_KEY` and `CLIENT_CERT_CHAIN`. 50 | 2) Call `context.load_cert_chain()` and provide the new key file and certificate chain. 51 | 52 | #### Extra Credit! 53 | 54 | If you have extra time, check out the client or servers certificates and keys within the resources directory. If you have OpenSSL installed and available from the command line, try these: 55 | ``` 56 | openssl rsa -in client.key.pem -noout -text 57 | 58 | openssl x509 -in client.intermediate.chain.pem -noout -text 59 | ``` 60 | 61 | ## Exercise 3: Certificate Pinning 62 | In this exercise there are two possible servers, one acting as an imposter. Both servers have valid certificates - perhaps a private key got leaked - but in any case we want to configure the client to only accept a single certificate. This is called pinning. The client and servers use this connection to send a fictitious banking record. The pickle module allows us to serialise objects as bytes for transmission over a network. *Note:* We've disabled hostname checking for this one; the imposter server has a different common name for clarity, normally any attacker who forged a certificate would use the original host name. 63 | 64 | #### The Client 65 | In this part you might like to use the python `hashlib` [documentation](https://docs.python.org/3/library/hashlib.html#hash-algorithms) if you're not familiar with it. As before the ssl documentation is [here](https://docs.python.org/3.6/library/ssl.html). If you look at the top you'll see I've defined `PINNED_FILE` which is a 32 byte binary file containing a hash of the servers certificate that was calculated ahead of time. We're going to compare these bytes with a hash of the incoming server certificate. 66 | 67 | Python's `ssl` library doesn't let us hook into the TLS validation function, so we'll perform validation immediately after connection, before we send any data. 68 | 69 | 1) Load the pinned hash of the server's real certificate into a bytes array. This is a standard file `open` in `rb` mode. 70 | 2) After `connect()`, use `getpeercert()` to obtain the server's cerificate. Ensure the parameter `binary_form` is true, as this returns a DER encoded certficate, which is what was pinned. 71 | 3) Hash the binary certificate using SHA256 and compare this to the hash you loaded. If they don't match, raise an `ssl.CertificateError`! 72 | 73 | You'll now find that the imposter server is rejected, but the original server works fine. 74 | 75 | #### Extra Credit! 76 | 77 | It's quite common to apply a "Trust on First Use" policy for clients. You could do this by pinning the first hash you encounter the first time. Try adapting the client to save a pinned hash the first time a server connects, and then rejecting any different ones after this. You might be familiar with this process from when you pin public keys for servers in SSH. 78 | -------------------------------------------------------------------------------- /ca/README.md: -------------------------------------------------------------------------------- 1 | # OpenSSL Certificate Authority Example 2 | 3 | This is an example CA set up to serve certificates to the servers and clients in use within these exercises. There is currently one root certificate, one intermediate certificate, and then a handful of end entity certificates. 4 | 5 | ## Introduction 6 | #### Directory Structure 7 | The root directory of the CA contains a number of directories: 8 | 9 | | Directory | Description | 10 | | ---------------- | --------------------------------------------- | 11 | | ca/certs/ | Any signed certificates with requested names | 12 | | ca/newcerts/ | Signed certificates named by serial number | 13 | | ca/private/ | Private key files | 14 | | ca/intermediate/ | The intermediate CA and its files | 15 | 16 | The `ca/private/` directory contains the most important part of the CA, the root certificates private key. Real CAs take extreme measures to protect this key! 17 | 18 | Within the CA directory are a number of files associated with the CA. A config file `openssl.cfg` provides configuration for OpenSSL. This includes default values, and extension information for things like key usages. `index.txt` and `serial` hold a list of previously signed keys, which are stored in `ca/newcerts`. 19 | 20 | The intermediate CA has a similar structure: 21 | 22 | | Directory | Description | 23 | | ------------------------- | --------------------------------------------- | 24 | | ca/intermediate/certs/ | Any signed certificates with requested names | 25 | | ca/intermediate/newcerts/ | Signed certificates named by serial number | 26 | | ca/intermediate/private/ | Private key files | 27 | | ca/intermediate/csr/ | Certificate signing requests for this int CA | 28 | 29 | #### The Signing Process 30 | 31 | Whenever a new certificate needs to be signed, there is a process: 32 | 33 | 1) Generate a new public key / private key pair and an associated certificate (usually stored as .pem files) 34 | 2) Generate a certificate signing request (CSR) 35 | 3) Provide the CA with the above, at which point they will sign the certificate with their private key 36 | 37 | #### Root and Intermediate Certificates 38 | All CAs have at least one root key pair. The private keys of these are so protected that they are used rarely, often stored on machine without a network connection, in a secured room. Typically `root certificates` have a long lifespan, and are used to sign a handful of `intermediate certificates`. These are used to perform actual day to day signing activities, usually through automated systems. Using intermediate certificates allows us to revoke them if they are compromised. It's simply a form of delegation, and means the highly protected root keys can be kept safe unused. 39 | 40 | ## Setting up the CA 41 | #### The Root Certificate 42 | The first task is to generate the root key pair: 43 | 44 | ``` 45 | openssl genrsa -aes256 -out private/ca.key.pem 4096 46 | 47 | Enter pass phrase for ca.key.pem: experttls 48 | Verifying - Enter pass phrase for ca.key.pem: experttls 49 | ``` 50 | 51 | We then create a root certificate, signed using the certificates own private key. All root certificates are signed this way, also note that a CSR isn't required for the root certificate. 52 | 53 | ``` 54 | openssl req -config openssl.cfg -key private/ca.key.pem 55 | -new -x509 -days 7300 -sha256 -extensions v3_ca -out certs/ca.cert.pem 56 | 57 | Enter pass phrase for ca.key.pem: experttls 58 | 59 | ... 60 | 61 | Country Name (2 letter code) [GB]: 62 | State or Province Name [England]: 63 | Locality Name []: 64 | Organization Name [Expert TLS]: 65 | Organizational Unit Name [IT Training]: 66 | Common Name []:Expert TLS Root CA 67 | Email Address []: 68 | ``` 69 | #### The Intermediate Certificate 70 | We begin by creating an intermediate key pair within the `ca/intermediate/` directory: 71 | 72 | ``` 73 | openssl genrsa -aes256 -out intermediate/private/intermediate.key.pem 4096 74 | 75 | Enter pass phrase for intermediate.key.pem: experttls 76 | Verifying - Enter pass phrase for intermediate.key.pem: experttls 77 | ``` 78 | 79 | The certificate for this key pair will need to be signed by the root certificate. To do this we generate a certificate signing request using the `openssl req` command: 80 | 81 | ``` 82 | openssl req -config intermediate/openssl.cfg -new -sha256 83 | -key intermediate/private/intermediate.key.pem -out intermediate/csr/intermediate.csr.pem 84 | 85 | Enter pass phrase for intermediate.key.pem: experttls 86 | 87 | ... 88 | 89 | Country Name (2 letter code) [GB]: 90 | State or Province Name [England]: 91 | Locality Name []: 92 | Organization Name [Expert TLS]: 93 | Organizational Unit Name [IT Training]: 94 | Common Name []:Expert TLS Int CA 95 | Email Address []: 96 | ``` 97 | 98 | This creates the certificate, which we sign with the root CA key using the `openssl ca` command: 99 | 100 | ``` 101 | openssl ca -config openssl.cnf -extensions v3_intermediate_ca -days 3650 -notext -md sha256 102 | -in intermediate/csr/intermediate.csr.pem 103 | -out intermediate/certs/intermediate.cert.pem 104 | 105 | Enter pass phrase for ca.key.pem: experttls 106 | Sign the certificate? [y/n]: y 107 | ``` 108 | 109 | This creates a certificate with the a serial from `serial` and adds a record into `index.txt`. Now the CA is ready to go! You would generally now use this intermediate certificate, or another one, to sign any other end entity certificates. 110 | 111 | ## Using the CA 112 | Signing incoming CSRs is similar to the process above. In this case since we're generating our own certificates for use in TLS sessions, we'll generate another private key for our TLS server. For standard TLS servers, 2048 bit RSA is adequate, and also a little faster than 4096 bits when performing handshakes. 113 | 114 | #### Generate the key 115 | 116 | ``` 117 | openssl genrsa -aes256 -out intermediate/private/server.key.pem 2048 118 | 119 | Enter pass phrase for server.key.pem: experttls 120 | Verifying - Enter pass phrase for server.key.pem: experttls 121 | ``` 122 | It perhaps goes without saying you should use different passwords for all of these keys! Next we generate the CSR: 123 | 124 | ``` 125 | openssl req -config intermediate/openssl.cfg 126 | -key intermediate/private/server.key.pem 127 | -new -sha256 -out intermediate/csr/server.csr.pem 128 | 129 | Enter pass phrase for server.key.pem: experttls 130 | 131 | ... 132 | 133 | Country Name (2 letter code) [GB]: 134 | State or Province Name [England]: 135 | Locality Name []: 136 | Organization Name [Expert TLS]: 137 | Organizational Unit Name [IT Training]: 138 | Common Name []:Expert TLS Server 139 | Email Address []: 140 | ``` 141 | 142 | If you were hosting a website, it's important that your common name (CN) matches the domain name you'll be using. Browsers and other clients typically check against the hostname when verifying certificates. In this case, we're using these certificates internally, so I've chosen to use more semantically meaningful common names. 143 | 144 | Finally, we can sign using the intermediate certificate (not the root!): 145 | ``` 146 | openssl ca -config intermediate/openssl.cfg -extensions server_cert -days 375 -notext 147 | -md sha256 -in intermediate/csr/server.csr.pem 148 | -out intermediate/certs/server.cert.pem 149 | ``` 150 | 151 | ## Other Useful Commands 152 | OpenSSL has a great many features, here are some useful ones: 153 | 154 | Examine a certificate 155 | 156 | ``` 157 | openssl x509 -noout -text -in server.cert.pem 158 | ``` 159 | 160 | Copy a certificate to a different format (e.g. DER) 161 | ``` 162 | openssl x509 -in server.cert.pem -out server.cert.cer 163 | ``` 164 | 165 | Copy a certificate and key into a pkcs12 file. Useful for a few things, notably importing into a java keystore 166 | ``` 167 | openssl pkcs12 -export -in server.cert.pem -inkey server.key.pem 168 | -name "server" -out server.p12 169 | ``` 170 | 171 | Verify a certificate chain 172 | ``` 173 | openssl verify -CAfile ca-chain.cert.pem server.cert.pem 174 | 175 | server.cert.pem: OK 176 | ``` 177 | 178 | Note that the ca-chain file will contain both the root and intermediate keys. Or any keys necessary to complete the chain. This can help you verify the chain is valid between the server certificate and those certificates in the rest of the chain. If you have a trusted root certificate, you can use this command to verify a chain: 179 | 180 | ``` 181 | openssl verify -CAfile ca.cert.pem -untrusted int.cert.pem server.cert.pem 182 | ``` 183 | 184 | ## Ed25519 Certificates 185 | Edward's curve certificates use a form of elliptic-curve cryptography. Signatures based on them are modern, efficient, and secure. There is one Ed25519 server certificate signed in the repository. It's not used during the exercises, it's purely here as an example. They make a good option as long as the connecting clients support them. These are the commands I used to generate the certificate: 186 | 187 | Generate a key pair 188 | ``` 189 | openssl genpkey -algorithm ed25519 -aes256 190 | -out intermediate/private/server.ed25519.key.pem 191 | ``` 192 | 193 | Create a CSR 194 | ``` 195 | openssl req -config intermediate/openssl.cfg 196 | -key intermediate/private/server.ed25519.key.pem 197 | -new -sha256 -out intermediate/csr/server.ed25519.csr.pem 198 | ``` 199 | 200 | Sign using the intermediate CA 201 | ``` 202 | openssl ca -config intermediate/openssl.cfg -extensions server_cert -days 375 203 | -notext -md sha256 -in intermediate/csr/server.ed25519.csr.pem 204 | -out intermediate/certs/server.ed25519.cert.pem 205 | ``` 206 | 207 | Create a DER encoded version of the certificate too 208 | ``` 209 | openssl x509 -in intermediate\certs\server.ed25519.cert.pem 210 | -out intermediate\certs\server.ed25519.cert.der 211 | ``` 212 | 213 | ## Testing a Server Handshake 214 | It can be tricky to work out what's going wrong in a handshake, whether it's a certificate problem or a problem with your server or client setup. OpenSSL has a test client that is really useful in this case. The `openssl s_client` command lets us connect to a server and view detailed debugging information. 215 | ``` 216 | openssl s_client -CAfile ca.cert.pem localhost:8282 217 | ``` 218 | This command will connect to a server using a root certificate, and verify a successful handshake. Once connected, you can send and receive data from the command line. 219 | 220 | ``` 221 | openssl s_client -debug -CAfile ca.cert.pem localhost:8282 222 | ``` 223 | The `-debug` flag produces significantly more output information. 224 | 225 | ``` 226 | openssl s_client -tls1_3 -CAfile ca.cert.pem localhost:8282 227 | ``` 228 | You can add additional parameters such as `-tls1_3` for negotiate specific protocols and ciphers, for testing. 229 | 230 | ``` 231 | openssl s_client -tlsextdebug –state -CAfile ca.cert.pem localhost:8282 232 | ``` 233 | The `-tlsextdebug` flag produces more information on extensions in use. 234 | -------------------------------------------------------------------------------- /java/README.md: -------------------------------------------------------------------------------- 1 | # Java Exercises 2 | These exercises have been written and tested in Java 8, although in general I would recommend using the most recent version of Java you have available. These exercises can be compiled and run from the command line, but I used [IntelliJ](https://www.jetbrains.com/idea/) with Maven. 3 | 4 | ## Exercise 1: Setting up a TLS Connection 5 | In this exercise you have a completely working server. It will negotiate TLS sessions and the communicate with clients. Once set up, the server simply recieves lists of bytes, and then returns the product of all of the numbers received. E.g. [2,5,6] -> 60. 6 | 7 | The client is less complete, at the start of the exercise it has code missing, so it won't connect to a server, and without an available socket, it will simply return. 8 | 9 | #### Part 1: Connecting with the client 10 | The client doesn't have a working socket implementation. To begin you need to create a new `SSLSocketFactory`, then use it to create an `SSLSocket` with an appropriate configuration. 11 | 12 | While you work, it'd be useful to have the [SSLSocket](https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/SSLSocket.html) and [SSLSocketFactory](https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/SSLSocketFactory.html) documentation to hand. You can now either get stuck in using the existing code and documentation, or follow along below for a little more advice. 13 | 14 | 1) Begin by creating a new socket SSLSocketFactory by calling the `getDefault()` static method. 15 | 2) You can then call `.createSocket()` on this new factory, passing a port and hostname, which are stored as static variables. 16 | 3) You'll need to cast them back to (SSLSocketFactory) and (SSLSocket). 17 | 4) On the socket, `.startHandshake()` will negotiated a TLS session with the server. 18 | 19 | Test it out, and don't forget to start the server! With any luck, this should now connect nicely. 20 | 21 | #### Part 2: Specifying protocols and cipher suites 22 | TLS works by ordering available cipher suites by preference. You can control what ciphers are used simply by putting the weaker ones at the end. Given you have full control over both the client and server implementations, it's actually easier and safer simply to disable all but the strongest ciphers and protocols. 23 | 24 | 1) The functions your interested in should be run prior to calling `startHandshake()`. First try polling the socket to see what protocols and ciphers are available by default. Use `socket.getEnabledProtocols()` and `.getEnabledCipherSuites()` to see lists of what are enabled. 25 | 2) Use `socket.setEnabledProtocols(String[])` to enable only TLS 1.3 and 1.2. 26 | 3) Use `socket.setEnabledCipherSuites(String[])` to enable only certain ciphers. For example `TLS_AES_256_GCM_SHA384 or TLS_CHACHA20_POLY1305_SHA256. 27 | 28 | You can make these changes to both the client and the server. The server uses an `SSLServerSocket`, but the interface in this case is the same. 29 | 30 | #### Extra credit! 31 | Have a play around with the different cipher suites. You'll find it's quite easy to break your TLS connection when the server and client don't have at least one valid protocol (e.g. TLS1.2) and one cipher suite between them. 32 | 33 | ## Exercise 2: Mutual Authentication 34 | In this exercise both the client and server already work, but we are only authenticating the server. You need to add code to both in order to achieve a mutually authenticated session. The client and server here sent a simple HTTP GET request, and an HTML response. 35 | 36 | #### Part 1: The Server 37 | The server needs to request a certificate from the client. Make use of the [documentation](https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/SSLServerSocket.html). 38 | 39 | 1) Begin by defining two new static variables `TRUSTSTORE_LOCATION` and `TRUSTSTORE_PASSWORD`, the trust store is in the resource directory, so you can use the `class.getResource` method as with the keystore. 40 | 2) Within the main method, add the relevant properties for `trustStore` and `trustStorePassword` to ensure that the JVM knows which trust store to use. 41 | 3) In the server itself, before the call to accept, use the `socket.setNeedClientAuth()` to request a client certificate. 42 | 43 | #### Part 2: The Client 44 | 45 | Setting up the client to provide a certificate is the same code the server already contains to provide its own. 46 | 47 | 1) Set up static variables for `KEYSTORE_LOCATION` and `KEYSTORE_PASSWORD` 48 | 2) Add properties for `keystore` and `keystorePassword` within the main method. 49 | 50 | #### Extra Credit! 51 | 52 | If you have extra time, have a look inside the trust and key stores using `keytool`. Try these: 53 | ``` 54 | keytool -list -keystore ClientKeyStore.jks 55 | 56 | keytool -list -v keystore ClientTrustStore.jks 57 | ``` 58 | 59 | Notice that the trust store only contains the root certificate, while the key store contains the chain up to the root. 60 | 61 | ## Exercise 3: Certificate Pinning 62 | In this exercise there are two possible servers, one acting as an imposter. Both servers have valid certificates - perhaps a private key got leaked - but in any case we want to configure the client to only accept a single certificate. This is called pinning. The client and servers use this connection to send a fictitious banking record. This is implemented using a serialisable class, and Object streams. 63 | 64 | #### The Client 65 | In this part you might like to use the `java.security.MessageDigest` [documentation](https://docs.oracle.com/javase/8/docs/api/java/security/MessageDigest.html) which also shows a short example. In this exercise we'll also make use of an `SSLContext` ([documentation](https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/SSLContext.html)). Begin by taking a look carefully through the client code. Notice we have loaded a pinned hash from a resource as a static variable. We're also using the `SSLContext` class to supply our own `X509TrustManager` ([documentation](https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/X509TrustManager.html)). We do this so we can create an anonymous class that overrides key parts of the certificate verification process. Find the `checkServerTrusted` function. We're calling `defaultTrustManager.checkServerTrusted()` so the default implementation simply examines the certificate chain as normal. Your task is to add a hash check against the pinned hash. 66 | 67 | 68 | 1) The method is passed the server's certificate chain. Obtain the first entry at `[0]`, which is the server's certificate. 69 | 2) Obtain a DER encoded version of this certificate via the .getEncoded() method. Check out the [documentation](https://docs.oracle.com/javase/8/docs/api/java/security/cert/X509Certificate.html). 70 | 3) Hash this encoding using a `MessageDigest` using SHA256. 71 | 4) Compare this hash to the pinned one, if they do not match, throw a `CertificateException`! You'll likely need to handle the MessageDigest's `NoSuchAlgorithmException` in which case you can also raise a certificate exception. 72 | 73 | You'll now find that the imposter server is rejected, but the original server works fine. 74 | 75 | #### Extra Credit! 76 | 77 | It's quite common to apply a "Trust on First Use" policy for clients. You could do this by pinning the first hash you encounter the first time. Try adapting the client to save a pinned hash the first time a server connects, and then rejecting any different ones after this. You might be familiar with this process from when you pin public keys for servers in SSH. 78 | 79 | # Java Keystores 80 | This section is not required for the exercises, but it is helpful to know a few of the java keytool commands, for using and manipulating keystores. A keystore is a java object that holds any number of certificates and/or private keys. In the exercises they are used on both the client and server sides, to store the certificates and keys required. 81 | 82 | You can create keystores using the `keytool` command, and you can also inspect and manipulate the contents of the main java keystore that is shipped with the JRE. 83 | 84 | ## Listing keystore contents 85 | The following command will list the contents of a keystore: 86 | 87 | ``` 88 | keytool -list -keystore ClientKeyStore.jks 89 | 90 | Enter Keystore Password: experttls 91 | 92 | Your keystore contains 2 entries 93 | 94 | client, 16 May 2019, PrivateKeyEntry, 95 | Certificate fingerprint (SHA-256): 4B:23:44:D2:4E:26:FE:D8:AC:D5:22:77:D0:B2:3A:3F:BA:91:C3:0F:C7:3B:BA:24:65:C6:15:31:78:AE:79:3C 96 | intca, 24 Oct 2019, trustedCertEntry, 97 | Certificate fingerprint (SHA-256): C8:A7:B4:76:CD:52:F0:DB:16:00:E2:EA:3B:49:33:93:07:69:2F:0E:6B:B8:BF:FE:E3:11:8E:CE:27:3B:B1:97 98 | ``` 99 | In this case we're examining the client key store, which is found in the resources directory of the exercises. It contains two things, the client certificate / key (a PrivateKeyEntry), and the int ca certificate (a trustedCertEntry). These are supplied when the client authenticates during Exercise 2. The client trust store only contains the root ca certificate. 100 | 101 | ## Adding into an existing keystore 102 | You can import an existing certificate into a keystore like this: 103 | ``` 104 | keytool -importcert -keystore ClientTrustStore.jks -alias rootca -file ca.cert.cer 105 | 106 | Enter keystore password: experttls 107 | 108 | Owner: CN=Expert TLS Root CA, OU=IT Training, O=Expert TLS, ST=England, C=GB 109 | Issuer: CN=Expert TLS Root CA, OU=IT Training, O=Expert TLS, ST=England, C=GB 110 | Serial number: 31cc7897c7cb8518c59592400ae69c2e41fc8dd5 111 | Valid from: Sat Apr 27 18:32:21 BST 2019 until: Mon Sep 03 18:32:21 BST 2040 112 | Certificate fingerprints: 113 | SHA1: 3B:55:2D:54:68:02:AC:61:83:4C:02:29:A4:90:C9:00:5D:6E:F7:BF 114 | SHA256: 13:EC:ED:75:D7:AB:A9:EE:8C:B8:AC:E8:56:40:9B:86:01:7E:83:47:4A:DB:2A:37:7A:3D:10:ED:26:EA:16:CA 115 | Signature algorithm name: SHA256withRSA 116 | Subject Public Key Algorithm: 4096-bit RSA key 117 | Version: 3 118 | 119 | Extensions: 120 | 121 | ... 122 | 123 | Trust this certificate? [no]: yes 124 | Certificate was added to keystore 125 | ``` 126 | If a certificate you are adding is signed by a trusted certificate in the keystore, it will be automatically added. If not, you will need to type yes to confirm you trust this certificate. 127 | 128 | ### Importing an OpenSSL Certificate and Private Key 129 | This is surprisingly difficult! In some cases you would generate a key pair within the keystore itself using `keytool -genkeypair`, then you can generate a certificate signing request using `keytool -gencert`. This allows you to then have OpenSSL or some CA sign a certificate, which can then be imported. 130 | 131 | During these exercises, all key pairs and certificates were generated using OpenSSL. Keytool doesn't accept pem files, we have to convert via a pkcs12 file. First, convert the certificate and key into pkcs12 format: 132 | ``` 133 | openssl pkcs12 -export -in server.cert.pem -inkey server.key.pem 134 | -name "server" -out server.p12 135 | 136 | Enter pass phrase for server.key.pem: experttls 137 | Enter Export Password: newpassword 138 | Verifying - Enter Export Password: newpassword 139 | ``` 140 | You absolutely must set a password here, even if you intend to delete this file. A bug means keytool won't accept pkcs12 files that are not password protected. Next, create a keystore based on this file: 141 | ``` 142 | keytool -importkeystore -deststorepass experttls -destkeypass experttls 143 | -destkeystore ServerKeyStore.keystore -srckeystore server.p12 144 | -srcstoretype PKCS12 -srcstorepass newpassword -alias servercert 145 | ``` 146 | This will create a new key store that contains both the server's certificate, and its private key. 147 | -------------------------------------------------------------------------------- /glossary.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | 3 | 4 | \usepackage[margin=2cm]{geometry} 5 | \usepackage[nonumberlist,seeautonumberlist]{glossaries} 6 | 7 | % Glossary definitions 8 | \newglossary*{crypto}{Cryptography} 9 | \newglossary*{pki}{Public Key Infrastructure} 10 | \newglossary*{tls}{Transport Layer Security} 11 | 12 | % Generate glossaries 13 | \makeglossaries 14 | 15 | \title{Glossary} 16 | 17 | \begin{document} 18 | 19 | \section*{\Huge Glossary} 20 | 21 | % Cryptography 22 | \newglossaryentry{c:aead}{type=crypto, name={AEAD}, description={Authenticated Encryption with Associated Data. A modern mode of encryption that provides in-built authenticity, usually via the computation of a MAC that is computed over the message or ciphertext, and additional data that requires protection. Modern algorithms that support this are AES-GCM and ChaCha20}} 23 | \newglossaryentry{c:aes}{type=crypto, name={AES}, description={The Advanced Encryption Standard. The most commonly used block cipher. The Rijndael algorithm was developed by researchers in Belgium as a response to a NIST call for replacements for DES}} 24 | \newglossaryentry{c:asym}{type=crypto, name={Asymmetric Encryption}, description={Encryption that uses two keys, one for encryption and one for decryption. Traditionally only one of the keys is kept private}} 25 | \newglossaryentry{c:chacha}{type=crypto, name={ChaCha20}, description={A modern stream cipher, often paired with the Poly1305 MAC. Uses only basic CPU operations, and as such is extremely fast on modern devices, particularly phones. Used as standard on Android phones when connecting to Google servers. It is also an available cipher suite in TLS}} 26 | \newglossaryentry{c:gcm}{type=crypto, name={Galois Counter Mode}, description={A modern mode of operation often seen used with AES. GCM is similar to counter mode, but also computes a message authentication code or GMAC over the data, ensuring message authenticity}} 27 | \newglossaryentry{c:hash}{type=crypto, name={Hash Function}, description={A function that takes a message of any length, and returns a message of a fixed size. Used frequently in message authentication codes and digital signatures. Also sometimes used to secure passwords, and to derive keys from shared secrets like Diffie-Hellman output}} 28 | \newglossaryentry{c:kdf}{type=crypto, name={KDF}, description={Key derivation function. Any (normally hash-based) algorithm for converting a pre-master secret into an actual key}} 29 | \newglossaryentry{c:hmac}{type=crypto, name={HMAC}, description={An improved structure for a MAC, using two derived keys and two applications of a hash function. Used as part of the KDF in TLS}} 30 | \newglossaryentry{c:iv}{type=crypto, name={IV}, description={Initialisation Vector. A random string that is not secret, and used to provide randomness. Usually it is required that IVs may repeat (at random), but should be strongly random and as such, unpredictable}} 31 | \newglossaryentry{c:key}{type=crypto, name={Key}, description={The secret component of most ciphers. A string of bytes that are used to alter the output of a cipher, such that it cannot be reversed without possessing those same bytes}} 32 | \newglossaryentry{c:kex}{type=crypto, name={Key Exchange}, description={A protocol that allows two parties to generate or share a secret key over an insecure channel}} 33 | \newglossaryentry{c:mac}{type=crypto, name={Message Authentication Code (MAC)}, description={A tag appended to a message that provides authenticity. A shared secret is combined with the message and hashed, to provide a tag that is able to verify whether a message has been changed}} 34 | \newglossaryentry{c:mode}{type=crypto, name={Mode of Operation}, description={A protocol within which a block cipher is used, in order to facilitate the encryption of messages of arbitrary lengths. Modern modes of operation often provide useful features beyond the core block cipher, such as message authentication}} 35 | \newglossaryentry{c:nonce}{type=crypto, name={Nonce}, description={A "number used once". A string of bytes that are used once in combination with a key, to provide different permutations (e.g. a random keystream) as required. Seen in TLS in any counter mode, including modern AEAD ciphers}} 36 | \newglossaryentry{c:pad}{type=crypto, name={Padding}, description={Additional bytes added to a message as required to bring the message to the required size of a block cipher or hash function}} 37 | \newglossaryentry{c:poly}{type=crypto, name={Poly1305}, description={A modern MAC that is often used with ChaCha20. It's name is derived from the polynomial function used within it, $2^{130}-5$}} 38 | \newglossaryentry{c:pk}{type=crypto, name={Public-key Cryptography}, description={Another term that is commonly used to refer to asymmetric encryption, but also encompases key exchange mechanisms such as Diffie-Hellman}} 39 | \newglossaryentry{c:ecdsa}{type=crypto, name={ECDSA}, description={Elliptic curve variant of DSA. Much more efficient and secure, likely to see increased use as it offers more security than RSA for shorter key lengths}} 40 | \newglossaryentry{c:dsa}{type=crypto, name={DSA}, description={Digital Signature Algorithm. An alternative to RSA based on different mathematics. Support for this has waned, and usually only allows for the use of 1024 bit keys, which is not enough. The elliptic curve variant ECDSA is much preferred}} 41 | \newglossaryentry{c:rsa}{type=crypto, name={RSA}, description={The most commonly used public-key cryptographic system. Provides a public and private key pair, either of which can be used for encryption, with the other reversing this process. RSA is used for encryption and for signing. RSA is based around the difficulty of solving the integer factorisation problem}} 42 | \newglossaryentry{c:sha1}{type=crypto, name={SHA-1}, description={A hash function with a 160-bit block size. Still secure within structures like HMAC, but a collision has been found, so security advice is to move toward SHA-2 at this point}} 43 | \newglossaryentry{c:sha2}{type=crypto, name={SHA-2}, description={Very similar to SHA-1, but with a 256 or 512-bit block size. This increased block size makes collisions much more difficult, and this function is currently considered secure}} 44 | \newglossaryentry{c:sha3}{type=crypto, name={SHA-3}, description={An alternative to SHA-2, should a serious vulnerability with SHA-2 be found. Offers similar hash lengths, but the function itself is very different to SHA-1 and SHA-2}} 45 | \newglossaryentry{c:ed448}{type=crypto, name={Ed448}, description={A new elliptic-curve based signature algorithm offering 224 bits of security. A specific instance of ECDSA}} 46 | \newglossaryentry{c:ed25519}{type=crypto, name={Ed25519}, description={A new elliptic-curve based signature algorithm offering 128 bits of security. Fast and secure, it is seeing increased use. A specific instance of ECDSA}} 47 | \newglossaryentry{c:sigs}{type=crypto, name={Digital Signature}, description={A message signed (encrypted by) the private key of a key pair. This key is usually associated with a public key certificate}} 48 | \newglossaryentry{c:sym}{type=crypto, name={Symmetric Encryption}, description={Encryption that uses a single key for both encryption and decryption}} 49 | 50 | % Public Key Infrastructure 51 | \newglossaryentry{p:baseline}{type=pki, name={Baseline Requirements}, description={A set of technical and policy requirements that Cas must adhere to. Most root store programs enfore these in order for a CAs root certificate to be trusted}} 52 | \newglossaryentry{p:ca}{type=pki, name={Certification Authority}, description={Commonly called a Certificate Authority (CA). An organisation that issues signed certificates}} 53 | \newglossaryentry{p:cert}{type=pki, name={Certificate}, description={A file in a standard format that contains, among other things, a public key and identifying information about the owner}} 54 | \newglossaryentry{p:ext}{type=pki, name={Certificate Extension}, description={An optional extension to the standard certificate format. Usually used to add functionality at a later date}} 55 | \newglossaryentry{p:chain}{type=pki, name={Certificate Chain}, description={A chain of intermediate certificates leading from an end entity (leaf certificats to a trusted root certificate}} 56 | \newglossaryentry{p:crit}{type=pki, name={Critical Extension}, description={A certificate extension, but marked such that failure to parse should be grounds to reject this certificate. For example, if a client does not understand this extension}} 57 | \newglossaryentry{p:crl}{type=pki, name={Certificate Revocation List (CRL)}, description={A list of revoked certificates distributed by a CA}} 58 | \newglossaryentry{p:csr}{type=pki, name={Certificate Signing Request (CSR)}, description={A signed file in a standard format that incudes data required by a CA to issue a certificate. Typically, a public key and subject identifying information. Other information on the resulting certificate will be generated by the CA}} 59 | \newglossaryentry{p:store}{type=pki, name={Certificate Store / Trust Store}, description={A list of trusted root certificates. Operating systems manage these trust stores, along with Mozilla, and some browsers. Many other browsers and programs rely on the OS trust stores}} 60 | \newglossaryentry{p:cn}{type=pki, name={Common Name (CN)}, description={The name of the subject of this certificate. For end entity certificates this will usually be a domain name. For intermediate and root certificates this will be a human readable name}} 61 | \newglossaryentry{p:dv}{type=pki, name={Domain Validated (DV) Certificates}, description={Certificates for which the subject has demonstrated control over the domain in the CN field. This is verified by the CA}} 62 | \newglossaryentry{p:ev}{type=pki, name={Extended Validation (EV) Certificates}, description={Similar to an OV certificate, but with more stringent checks on the validation of the organisation}} 63 | \newglossaryentry{p:int}{type=pki, name={Intermediate Certificate}, description={A certificate that signs end entity certificates or other intermediate certificates. These are used to prevent the root keys being required regularly}} 64 | \newglossaryentry{p:issuer}{type=pki, name={Issuer}, description={A field on a certificate indicating the name of the certificate that signed it}} 65 | \newglossaryentry{p:ocsp}{type=pki, name={OCSP}, description={A response signed by a CA indicating that a specific certificate is valid. May be used by a client to verify a certificate has not been revoked}} 66 | \newglossaryentry{p:stapling}{type=pki, name={OCSP Stapling}, description={The process of a server sending an OCSP response with its certificate, such that the client does not have to perform this task themselves. Uses the TLS Certificate Status Request extension}} 67 | \newglossaryentry{p:ov}{type=pki, name={Organisation Validation (OV) certificates}, description={Certificates where the identification of the organisation in the subject has been verified by the CA}} 68 | \newglossaryentry{p:pem}{type=pki, name={PEM}, description={An ASCII base 64 encoded file used for storing certificates and private keys}} 69 | \newglossaryentry{p:der}{type=pki, name={DER}, description={A binary encoding used for, among other things, certificates and keys. Stands for Distinguished Encoding Rules for ASN.1}} 70 | \newglossaryentry{p:pin}{type=pki, name={Pinning}, description={The process of validating a certificate against a known public key or certificate stored in ahead of time. Allows clients to provide additional assurances as to the validity of a certificate, as generally any certificate signed by any CA is valid}} 71 | \newglossaryentry{p:pinset}{type=pki, name={Pinset}, description={A set of pins for multiple end entity, intermediate and root certificates}} 72 | \newglossaryentry{p:root}{type=pki, name={Root Certificate}, description={A certificate stored in a trust store, representing the end of a chain. These are usually self-signed, unless signed by another CA}} 73 | \newglossaryentry{p:san}{type=pki, name={Subject Alternative Name}, description={An X.509 extension used to hold alternative host names valid for a certificate. Useful for virtual servers and subdomains}} 74 | \newglossaryentry{p:selfsigned}{type=pki, name={Self-signed Certificate}, description={A certificate whose signature has been generated by using its own private key}} 75 | \newglossaryentry{p:x509}{type=pki, name={X.509}, description={A standard certificate format widely supported in PKI}} 76 | \newglossaryentry{p:pki}{type=pki, name={Public Key Infrastructure}, description={(PKI) is a standardised set of policies and file formats for the management and use of public key certificate.}} 77 | 78 | % Transport Layer Security 79 | \newglossaryentry{t:ssl}{type=tls, name={Secure Socket Layer}, description={(SSL) is a protocol that was a predecessor to TLS. Developed starting in 1994 by Netscape, only SSL3 bears resemblance to modern TLS. It is common for the acronyms TLS and SSL to be used interchangeably, but strictly speaking SSL is deprecated}} 80 | \newglossaryentry{t:tls}{type=tls, name={Transport Layer Security}, description={(TLS) is a modern version of the SSL3 protocol, that has now undergone significate revisions and improvements. Currently on version 1.3}} 81 | \newglossaryentry{t:hshk}{type=tls, name={Handshake}, description={A series of defined messages in TLS that establish the security parameters of a session between two parties. Contain, among others, the ClientHello, ServerHello, Certificate, and Finished messages}} 82 | \newglossaryentry{t:rec}{type=tls, name={Record}, description={The common data structure for transport of any TLS message. Contains a header holding the type of the message, the version number, and the length of the payload. The payload itself is treaded as opaque, with the record unchanged regardless of the contents. Record contents may or may not be encrypted. }} 83 | \newglossaryentry{t:alert}{type=tls, name={Alert}, description={A TLS subprotocol (21). Indicates a notification or fatal error. Contains a byte for the message type, and a byte for the description index}} 84 | \newglossaryentry{t:hshkm}{type=tls, name={Handshake (Message)}, description={A TLS subprotocol (22). A handshake message that contains its own sub header indicating the type of message. Examples are ClientHello, ServerHello, Certificate, Finished}} 85 | \newglossaryentry{t:ccs}{type=tls, name={ChangeCipherSpec}, description={A TLS subprotocol (20). Indicates a party is to begin encrypting under a new set of keys and parameters. Used as part of a TLS 1.2 handshake, but not used in TLS1.3}} 86 | \newglossaryentry{t:ver}{type=tls, name={Version}, description={Two bytes indicating the major and minor TLS version numbers. TLS was seen as SSL3.1, thus TLS 1.0 had version number 3\_1. The later versions are 3\_2 (TLS 1.1), 3\_3 (TLS 1.2) and 3\_4 (TLS 1.3)}} 87 | \newglossaryentry{t:suite}{type=tls, name={Cipher Suite}, description={A string representing the selected ciphers and other algorithms used during an encrypted session. An example would be TLS\_ECDHE\_RSA\_WITH\_AES\_128\_GCM\_SHA256. From TLS 1.3, key exchange and authentication suites are separated and passed as extensions}} 88 | \newglossaryentry{t:premaster}{type=tls, name={Pre-master Secret}, description={The shared secret derived from the client and server key exchange messages}} 89 | \newglossaryentry{t:master}{type=tls, name={Master Secret}, description={A shared master secret derived from the combination of the pre-master secret, the client and server random values (nonces). These bytes are used to derive all key material required for a session}} 90 | \newglossaryentry{t:nonce}{type=tls, name={Client / Server Nonce}, description={Random values passed during the client and server hello messages. They are used to prevent replay attacks, where messages are re-sent later}} 91 | \newglossaryentry{t:ext}{type=tls, name={Extensions}, description={Optional additional data that may be sent within a TLS message. Originally extensions were optional, but some have become inbuilt into the protocol, particularly in TLS 1.3}} 92 | \newglossaryentry{t:fin}{type=tls, name={Finished}, description={A handshake message indicating the end of the handshake protocol. Contains a MAC of all previous handshake messages, ensuring both the client and server have seen the same set of messages}} 93 | \newglossaryentry{t:openssl}{type=tls, name={OpenSSL}, description={A widely used implementation of SSL/TLS. It forms the backend for many packages that offer TLS, and also provides CA, X509 and other related PKI functionality}} 94 | \newglossaryentry{t:reneg}{type=tls, name={Renegotiation}, description={Reestablishment of session parameters such as keys during a session. All TLS sessions will renegotiate from time to time to provide forward secrecy. Renegotiation can also be used to request a client certificate that wasn’t required before. In TLS 1.3 renegotiation isn’t supported in this way via ClientHello messages. Instead KeyUpdate and CertificateRequest messages}} 95 | \newglossaryentry{t:appdata}{type=tls, name={Application Data}, description={A TLS subprotocol (23). Used to send any standard application data under whatever current encryption has been arranged}} 96 | \newglossaryentry{t:https}{type=tls, name={HTTPS}, description={A common use case for TLS, encrypted web connections using HTTP are known as HTTPS connections. Although this is the primary use case for TLS, it is by no means the only one}} 97 | \newglossaryentry{t:0rtt}{type=tls, name={0-RTT}, description={A handshake protocol supported in TLS 1.3. If a pre-shared key is available, the client can send this during the handshake, and immediately begin sending encrypted application data. Note: This doesn't protect against replay attacks, so should be used for read operations from the server only.}} 98 | 99 | 100 | \glsaddall 101 | 102 | % Print the glossaries 103 | \printglossary[type=crypto, style=altlist] 104 | \printglossary[type=pki, style=altlist] 105 | \printglossary[type=tls, style=altlist] 106 | \printglossary 107 | 108 | \end{document} --------------------------------------------------------------------------------