├── 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 | 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
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 | 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
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 | 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
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}
--------------------------------------------------------------------------------