GNU/LinuxOpenSSL

OpenSSL Certificates

2024/03/16

OpenSSL CA Configuration

Before creating my self signed certificate, I create a folder to store everything and configuration file

Create a folder with:

mkdir ggallCA
cd ggallCA 

Then create an openssl.cnf file to configure OpenSSL.

####################################
[ ca ]
default_ca                      = CA_default     # Go to default CA section

[ CA_default ]
dir             = /mnt/d/ggallCA                 # Where everything is kept
certificate     = $dir/CA/cacert.pem             # The CA certificate
database        = $dir/CA/index.txt              # The database
new_certs_dir   = $dir/CA/certs                  # default place for new certs.
private_key     = $dir/CA/privkey.pem            # The CA private key
serial          = $dir/CA/serial.txt             # The current serial number for certificates

policy          = policy_default
x509_extensions = certificate_extensions


# defaults for CA
default_days    = 90                    # how long to certify for
default_crl_days= 30                    # how long before next CRL
default_md      = sha512                # use public key default MD
preserve        = no                    # keep passed DN ordering


[ policy_default]
countryName             = optional
stateOrProvinceName     = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ certificate_extensions ]
basicConstraints = CA:false


####################################
[ req ]
default_bits            = 2048
default_keyfile         = privkey.pem
distinguished_name      = req_dn
x509_extensions         = v3_ext
attributes              = req_attributes

# extensions to add to certificate request
[ req_dn ]
countryName                     = Country Name (2 letter code)
countryName_default             = US
countryName_min                 = 2
countryName_max                 = 2

stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default     = Iowa

localityName                    = Locality Name (eg, city)
localityName_default            = Iowa CIty

0.organizationName              = Organization Name (eg, company)
0.organizationName_default      = Greg Gallardo

organizationalUnitName          = Organizational Unit Name (eg, section)

commonName                      = Common Name (e.g. server FQDN or YOUR name)
commonName_max                  = 64

emailAddress                    = greg@greggallardo.com
emailAddress_max                = 64

# request attributes
[ req_attributes ]
challengePassword               = A challenge password
challengePassword_min           = 4
challengePassword_max           = 20

[ v3_ext ]
basicConstraints = critical,CA:true
keyUsage = critical,digitalSignature, cRLSign, keyCertSign

[ v3_client ]
basicConstraints = CA:false
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth

CA Certs

Now that a base directory and configuration file exist, the next thing we need is the CA certificates for signing our client and server certificates.

Create a new folder to store the CA certificate files.

mkdir CA
cd CA

Next we create the folders files specified in openssl.cnf

touch index.txt
echo "01" > serial.txt
mkdir certs private

Run the following command to create the CA certificate and private key

openssl req -x509 -config ../openssl.cnf -newkey rsa:2048 -days 365 -out cacert.pem -outform PEM -subj /CN=GGAwsCA/ -nodes

-days means this one lasts a year

Certificate Creation

One your CA files exist you can use them to self-sign certificates. ## Server Certificate Creation Make a folder for your server certificates

cd /mnt/d/ggallCA
mkdir server
cd server

Next use openssl to make a signing request:

openssl genrsa -out serverkey.pem 2048
openssl req -new -key serverkey.pem   -out req.pem -outform PEM -subj /CN=test.myfakeserver.local/ -nodes -config ../openssl.cnf

Then sign the request with your CA files.

cd ../CA
openssl ca -config ../openssl.cnf  -in ../server/req.pem  -out ../server/servercert.pem -notext  

If all went well openssl will ask you if you want to sign the cert (just say yes) and commit (also say yes)

Using configuration from ../openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'testserver'
Certificate is to be certified until May 13 21:51:26 2023 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

This will create new server certificate files. One in the CA/certs folder and one named serversert.pem in the server folder.

PKCS12

The server certificates are PEM files. You might need other formats. I often work with Microsoft Windows, so I sometimes need to convert PEM files to PKCS12 files. This can be done with OpenSSL.

openssl pkcs12 -export -out servercert.p12 -in servercert.pem  -inkey serverkey.pem  -passout pass:somepassword
Validity Period

When signing a request, you can use the -days flag to set the validity period of the request you’re signing.

openssl genrsa -out serverkey_2.pem 2048
openssl req -new -key serverkey_2.pem   -out serverreq_2.pem -outform PEM -subj /CN=test.myfakeserver.local/ -nodes -config ../openssl.cnf

Then sign the request with your CA files.

cd ../CA
openssl ca -config ../openssl.cnf  -in ../server/serverreq_2.pem  -out ../server/servercert_2.pem -notext  -days 10

Client Certificate Creation

Make a folder for your client certificates

cd /mnt/d/ggallCA
mkdir client
cd client

Make client certificate signing requests with OpenSSL:

openssl genrsa -out clientkey.pem 2048
openssl req -new -key clientkey.pem -out req.pem -outform PEM -subj /CN=www.greggallardo.com/O=client/OU=test -nodes -config ../openssl.cnf 

Then sign the client request with your CA files.

cd ../CA
openssl ca -config ../openssl.cnf -in ../client/req.pem -out ../client/clientcert.pem -notext -batch -extensions v3_client

You will get copies of the certificate files in the CA/certs folder and clients folder

Password Protection

Adding -des3 to the command will add a password to the key.

openssl genrsa -des3 -out clientkey_pw.pem 2048
openssl req -new -key clientkey_pw.pem -out clientreq_pw.pem -outform PEM -subj /CN=www.greggallardo.com/O=client/OU=testpw -config ../openssl.cnf 

Then sign the client request with your CA files.

cd ../CA
openssl ca -config ../openssl.cnf -in ../client/clientreq_pw.pem -out ../client/clientcert_pw.pem -notext -batch -extensions v3_client
PKCS12 Format

If you want PKCS12 files, you can convert your PEM files with:

openssl pkcs12 -export -out clientcert.p12 -in clientcert.pem  -inkey clientkey.pem  -passout pass:clientpassword

Certificate Testing

You can look at the contents of your certificates with openssl x509

 openssl x509 -in <PEM FILE> -text

For example, dumping the client lets me verify the dates and Subject fields I specified.

$ openssl x509 -in ./client/clientcert.pem -text | head
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 2 (0x2)
        Signature Algorithm: sha512WithRSAEncryption
        Issuer: CN = GGAwsCA
        Validity
            Not Before: Mar 13 15:15:06 2023 GMT
            Not After : Jun 11 15:15:06 2023 GMT
        Subject: O = client, OU = test, CN = www.greggallardo.com

Testing Server Certificates

The following python script can be used to test out the server certificate

from http.server import HTTPServer, SimpleHTTPRequestHandler
import ssl

class SecureHTTPRequestHandler(SimpleHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        self.wfile.write(b'Hello, secure world!')

server_address = ('172.19.120.67', 8443)  # Replace with your own IP and Port values
httpd = HTTPServer(server_address, SecureHTTPRequestHandler)

# Set up the SSL context:
httpd.socket = ssl.wrap_socket(
    httpd.socket,
    server_side=True,
    certfile='/path/to/servercert.pem',    # Replace this with the path to your server certificate
    keyfile='/path/to/serverkey.pem',      # Replace this with the path to your private key
    ssl_version=ssl.PROTOCOL_TLS,
    ca_certs="/path/to/cacert.pem", # Replace this with the path to your CA certificate
    # cert_reqs=ssl.CERT_REQUIRED  # Enable this to test client certificates
)

print('Serving HTTPS on port', server_address[1])
httpd.serve_forever()

You can use --resolve with curl to test against the server.

 curl --cacert ./cacert.pem --resolve test.myfakeserver.local:8443:172.1ps://test.myfakeserver.local:8443

adding -v to the command will give you more information

> curl --cacert ./cacert.pem --resolve test.myfakeserver.local:8443:172.19.120.67 https://test.myfakeserver.local:8443  -v
* Added test.myfakeserver.local:8443:172.19.120.67 to DNS cache
* Hostname test.myfakeserver.local was found in DNS cache
*   Trying 172.19.120.67:8443...
* Connected to test.myfakeserver.local (172.19.120.67) port 8443 (#0)
* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
*  CAfile: ./cacert.pem
*  CApath: none
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN: server did not agree on a protocol. Uses default.
* Server certificate:
*  subject: CN=test.myfakeserver.local
*  start date: Mar 13 14:49:51 2023 GMT
*  expire date: Jun 11 14:49:51 2023 GMT
*  common name: test.myfakeserver.local (matched)
*  issuer: CN=GGAwsCA
*  SSL certificate verify ok.
* using HTTP/1.x
> GET / HTTP/1.1
> Host: test.myfakeserver.local:8443
> User-Agent: curl/8.0.1
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: SimpleHTTP/0.6 Python/3.10.12
< Date: Thu, 16 Mar 2023 15:46:45 GMT
< Content-type: text/html
<
* Closing connection 0
* TLSv1.3 (OUT), TLS alert, close notify (256):

Hello world!

If the common name for the certificate were wrong, you’d get a warning like this:

 curl --cert ./client/clientcert.pem  --key ./client/clientkey.pem --cacert ./CA/cacert.pem --resolve test.myfake.local:8443:172.19.120.67 https://test.myfake.local:8443
curl: (60) SSL: certificate subject name 'test.myfakeserver.local' does not match target host name 'test.myfake.local'
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

Testing Client Certificates

To test if the client certificate is valid, enable the ssl.CERT_REQUIRED option in the python server script

Then sign the client request with your CA files.
```bash
cd ../CA
openssl ca -config ../openssl.cnf -in ../client/req.pem -out ../client/clientcert.pem -notext -batch -extensions v3_client
cert_reqs=ssl.CERT_REQUIRED  # Enable this to test client certificates
You can specify the client key and certificate with the `--key` and `--cert` options.
```bash
curl --cert ./client/clientcert.pem  --key ./client/clientkey.pem --cacert ./CA/cacert.pem --resolve test.myfakeserver.local:8443:172.19.120.67 https://test.myfakeserver.local:8443

Hello world!

About Me

Greg Gallardo

I'm a software developer and sys-admin in Iowa. I use C++, C#, Java, Swift, Python, JavaScript and TypeScript in various projects. I also maintain Windows and Linux systems on-premise and in the cloud ( Linode, AWS, and Azure )

Github

Mastodon

YouTube

About you

IP Address: 18.189.31.109

User Agent: Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)

Language:

Latest Posts

Iowa City Weather

Today

-- ˚F / 61 ˚F

Sunday

71 ˚F / 54 ˚F

Monday

64 ˚F / 46 ˚F

Tuesday

76 ˚F / 54 ˚F

Wednesday

76 ˚F / 56 ˚F

Thursday

72 ˚F / 51 ˚F

Friday

67 ˚F / 47 ˚F