Skip to content

Instantly share code, notes, and snippets.

@nordineb
Last active July 31, 2023 20:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save nordineb/4e8f9122f6962c33e56f02d0d5794b3d to your computer and use it in GitHub Desktop.
Save nordineb/4e8f9122f6962c33e56f02d0d5794b3d to your computer and use it in GitHub Desktop.
Custom certificate authority with OpenSSL

tl;dr

  • A CA certificate must include the basicConstraints value with the CA field set to TRUE
  • The pathlen parameter indicates the maximum number of CAs that can appear below this one in a chain. So if you have a CA with a pathlen of zero it can only be used to sign end user certificates and not further CAs.
  • -addext option was introduced in OpenSSL 1.1.1 and it can be used instead of -extensions and -config. It is convenient for CSR, but there isn't the equivalent flag on the x509 command, so we still need to use -extfile

docker

docker run -it --rm -v c:/:/export alpine:edge 
apk upgrade --update-cache --available && apk add openssl

Scripts

create a self signed root CA

openssl req -nodes -new -x509 -subj "/CN=rootCA" -keyout rootCA.key -out root-ca.cert.pem
openssl x509 -in ./root-ca.cert.pem -noout -text -certopt no_version,no_pubkey,no_sigdump -nameopt multiline

create an intermediate certificate and sign it with the root CA

openssl req -nodes -new -subj "/CN=intermediateCA" -keyout intermediate-ca.key  -out intermediate-ca.csr 
openssl x509 -req -extfile config.txt  -extensions intermediate_ca_ext -in intermediate-ca.csr -CA root-ca.cert.pem -CAkey rootCA.key -CAcreateserial -out intermediate-ca.cert.pem
openssl x509 -in ./intermediate-ca.cert.pem -noout -text -certopt no_version,no_pubkey,no_sigdump -nameopt multiline

create and sign end user certificates

openssl req -nodes -new -subj "/CN=clientcert" -keyout clientcert.key  -out clientcert.csr 
openssl x509 -req -extfile config.txt  -extensions user_ext -in clientcert.csr -CA intermediate-ca.cert.pem -CAkey intermediate-ca.key -out clientcert.cert.pem -CAcreateserial -days 30
openssl x509 -in ./clientcert.cert.pem -noout -text -certopt no_version,no_pubkey,no_sigdump -nameopt multiline
cat intermediate-ca.cert.pem root-ca.cert.pem  > chain.pem
openssl pkcs12 -export -out cert.pfx -inkey clientcert.key -in clientcert.cert.pem -certfile chain.pem -passout pass:```

references

[ intermediate_ca_ext ]
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, cRLSign, digitalSignature, keyCertSign
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
[ server_ext ]
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = critical, serverAuth, clientAuth
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
[ client_ext ]
basicConstraints = CA:FALSE
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = critical, clientAuth, emailProtection
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
[ user_ext ]
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, clientAuth, emailProtection
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
[ v3_vpn_server ]
basicConstraints = critical, CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment, keyAgreement
extendedKeyUsage = critical, serverAuth
[ v3_vpn_client ]
basicConstraints = critical, CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = critical, clientAuth
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment