Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate both server and client certificates under root CA

So, I've been trying to set up an SSL connection between a python client and python server in which both have separate certificates to validate each-other, and both certificates are signed by one CA (which also happens to be the root CA). This should make them both valid to each-other, correct?

My methodology thus far has been to create a bash script that does it all:

  1. It generates the private key for the Root CA
  2. It generates the Root CA cert using the Root CA private key
  3. It generates the private key for the server
  4. It generates the CSR for the server
  5. It generates the server Cert using the server CSR and Root CA cert
  6. It generates the private key for the client
  7. It generates the CSR for the client
  8. It generates the client Cert using the client CSR and Root CA cert
#!/bin/bash

BOLD=$(tput bold)
CLEAR=$(tput sgr0)

echo -e "${BOLD}Generating RSA AES-256 Private Key for Root Certificate Authority${CLEAR}"
openssl genrsa -aes256 -out Root.CA.example.llc.key 4096

echo -e "${BOLD}Generating Certificate for Root Certificate Authority${CLEAR}"
openssl req -x509 -new -nodes -key Root.CA.example.llc.key -sha256 -days 1825 -out Root.CA.example.llc.pem

echo -e "${BOLD}Generating RSA Private Key for Server Certificate${CLEAR}"
openssl genrsa -out server/example.llc.server.key 4096

echo -e "${BOLD}Generating Certificate Signing Request for Server Certificate${CLEAR}"
openssl req -new -key server/example.llc.server.key -out server/example.llc.server.csr

echo -e "${BOLD}Generating Certificate for Server Certificate${CLEAR}"
openssl x509 -req -in server/example.llc.server.csr -CA Root.CA.example.llc.pem -CAkey Root.CA.example.llc.key -CAcreateserial -out server/example.llc.server.crt -days 1825 -sha256 -extfile server/example.llc.server.ext

echo -e "${BOLD}Generating RSA Private Key for Client Certificate${CLEAR}"
openssl genrsa -out client/example.llc.client.key 4096

echo -e "${BOLD}Generating Certificate Signing Request for Client Certificate${CLEAR}"
openssl req -new -key client/example.llc.client.key -out client/example.llc.client.csr

echo -e "${BOLD}Generating Certificate for Client Certificate${CLEAR}"
openssl x509 -req -days 1825 -in client/example.llc.client.csr -CA Root.CA.example.llc.pem -CAkey Root.CA.example.llc.key -set_serial 01 -out client/example.llc.client.crt

echo "Done!"

The server loads these credentials:

cntx = SSL.Context(...)
# ...
cntx.use_privatekey_file('example.llc.server.key')
cntx.use_certificate_file('example.llc.server.cert')
cntx.load_verify_locations('../Root.CA.example.llc.pem')

The client loads these credentials:

cntx = SSL.Context(...)
# ...
cntx.use_privatekey_file('example.llc.client.key')
cntx.use_certificate_file('example.llc.client.cert')
cntx.load_verify_locations('../Root.CA.example.llc.pem')

The server launches like a rocket

server = SSL.Connection(cntx, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
server.bind(('localhost', 44000))
server.listen(1)
server.setblocking(1)
cli, addr = server.accept()

and the client attempts to connect with

SSL.Connection(cntx, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
sock.connect(('localhost', 44000))

then I get hit with this madness:

OpenSSL.SSL.Error: [('SSL routines', 'ssl3_read_bytes', 'tlsv1 alert unknown ca')]

At this point, I'm not sure if the client and server certs should be signed by the root CA, if the client cert should be signed by the server cert, or if I'm going insane with all this certificate trust chain SSL/TLS magic wizard voodoo craziness. Please help.

like image 273
acpluspluscoder Avatar asked Feb 02 '19 09:02

acpluspluscoder


People also ask

Can a certificate be both server and client?

It's technically possible for a TLS certificate to be used as both a server certificate and a client certificate. The TLS certificate for this very site has its key usage set that way, for instance. But the server which requires a client certificate does so to authenticate the client.

How do I combine root intermediate and server certificates?

To combine them, simply copy the contents inside of the root certificate and paste it into a new line at the bottom of the intermediate certificate file. Once this is done, click File -> Save As and save this new bundle file and ensure to add '. crt' without the quotes at the end of the new filename.


1 Answers

And that's all she wrote!

Steve E. pointed out that the certs needed to be verified and so the culprit was found to be the self-signed client cert.

openssl verify -verbose -CAfile Root.CA.example.llc.pem server/example.llc.server.crt
openssl verify -verbose -CAfile Root.CA.example.llc.pem client/example.llc.client.crt

Here's the new autogen code:

#!/bin/bash

BOLD=$(tput bold)
CLEAR=$(tput sgr0)

iterate=(server/ client/)
for dir in "${iterate[@]}"; do
  [[ ! -d "$dir" ]] && mkdir -p "$dir" \
  && echo -e "${BOLD}directory '$dir' was created ${CLEAR}"
done

echo -e "${BOLD}Generating RSA AES-256 Private Key for Root Certificate Authority${CLEAR}"
openssl genrsa -aes256 -out Root.CA.example.llc.key 4096

echo -e "${BOLD}Generating Certificate for Root Certificate Authority${CLEAR}"
openssl req -x509 -new -nodes -key Root.CA.example.llc.key -sha256 -days 1825 -out Root.CA.example.llc.pem

echo -e "${BOLD}Generating RSA Private Key for Server Certificate${CLEAR}"
openssl genrsa -out server/example.llc.server.key 4096

echo -e "${BOLD}Generating Certificate Signing Request for Server Certificate${CLEAR}"
openssl req -new -key server/example.llc.server.key -out server/example.llc.server.csr

echo -e "${BOLD}Generating Certificate for Server Certificate${CLEAR}"
openssl x509 -req -in server/example.llc.server.csr -CA Root.CA.example.llc.pem -CAkey Root.CA.example.llc.key -CAcreateserial -out server/example.llc.server.crt -days 1825 -sha256 -extfile server/example.llc.server.ext

echo -e "${BOLD}Generating RSA Private Key for Client Certificate${CLEAR}"
openssl genrsa -out client/example.llc.client.key 4096

echo -e "${BOLD}Generating Certificate Signing Request for Client Certificate${CLEAR}"
openssl req -new -key client/example.llc.client.key -out client/example.llc.client.csr

echo -e "${BOLD}Generating Certificate for Client Certificate${CLEAR}"
openssl x509 -req -in client/example.llc.client.csr -CA Root.CA.example.llc.pem -CAkey Root.CA.example.llc.key -CAcreateserial -out client/example.llc.client.crt -days 1825 -sha256

echo "Done!"

Good luck and godspeed to anyone who is trying to create a self-signed root CA with double-sided authentication for client/server systems!

like image 77
acpluspluscoder Avatar answered Sep 21 '22 13:09

acpluspluscoder