You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
4.6 KiB
129 lines
4.6 KiB
---
|
|
title: "Creating and Using a CA Certificate"
|
|
description: ""
|
|
date: "2023-01-27"
|
|
tags:
|
|
- SSL
|
|
draft: false
|
|
---
|
|
|
|
Even though there are plenty of options available for obtaining an SSL certificate, you may want to issue your certificates
|
|
and check their validity using your own CA. This is useful for internal domains or doing mTLS for services in your networks.
|
|
|
|
Below is how to create a CA certificate and issue certs with it, and how to verify that a certificate was issued with
|
|
the CA you generated.
|
|
|
|
All examples here use the [OpenSSL command-line tool](https://www.openssl.org/docs/man1.1.1/man1/).
|
|
|
|
## Creating the Certificate Authority Certificate and Keys
|
|
|
|
First generate the private key and Root CA certificate that we will use to issue certs.
|
|
|
|
1. Generate a private key for the CA:
|
|
```sh {linenos=false}
|
|
openssl genrsa 4096 > ca-key.pem
|
|
```
|
|
|
|
2. Generate the X509 CA certificate. Note that if you exclude `-subj` you will get an interactive prompt instead:
|
|
```sh {linenos=false}
|
|
openssl req -new -x509 -nodes -days 3650 -sha256 \
|
|
-subj "/C=US/O=My Org, Inc./OU=R&D/CN=MyOrgCA" \
|
|
-key ca-key.pem \
|
|
-out ca-cert.pem
|
|
```
|
|
|
|
If you want to pass more options to `-subj` the following are the available attribute strings - from [RFC4514 Page 6](https://www.rfc-editor.org/rfc/rfc4514):
|
|
```text {linenos=false}
|
|
String X.500 AttributeType
|
|
------ --------------------------------------------
|
|
CN commonName (2.5.4.3)
|
|
L localityName (2.5.4.7)
|
|
ST stateOrProvinceName (2.5.4.8)
|
|
O organizationName (2.5.4.10)
|
|
OU organizationalUnitName (2.5.4.11)
|
|
C countryName (2.5.4.6)
|
|
STREET streetAddress (2.5.4.9)
|
|
DC domainComponent (0.9.2342.19200300.100.1.25)
|
|
UID userId (0.9.2342.19200300.100.1.1)
|
|
```
|
|
|
|
At this point you can view the CA certificate in a pretty format:
|
|
```sh {linenos=false}
|
|
$ openssl x509 -in mydomain.com.crt -text -noout
|
|
Certificate:
|
|
Data:
|
|
Version: 3 (0x2)
|
|
Serial Number:
|
|
25:28:31:d4:81:a4:1e:74:36:9c:50:e2:3e:dd:d0:a5:be:c9:d3:25
|
|
Signature Algorithm: sha256WithRSAEncryption
|
|
Issuer: C = US, O = "My Org, Inc.", OU = R&D, CN = MyOrgCA
|
|
Validity
|
|
Not Before: Jan 29 02:06:59 2023 GMT
|
|
Not After : Jan 26 02:06:59 2033 GMT
|
|
Subject: C = US, O = "My Org, Inc.", OU = R&D, CN = MyOrgCA
|
|
Subject Public Key Info:
|
|
Public Key Algorithm: rsaEncryption
|
|
Public-Key: (4096 bit)
|
|
Modulus:
|
|
...
|
|
```
|
|
|
|
|
|
## Creating the Server's Certificate and Keys
|
|
|
|
Now that we have our Root CA certificate we can issue certs for our servers to use. To do this you must first generate a
|
|
certificate request, and then sign it with your Root CA cert to generate the final certificate.
|
|
|
|
1. Generate the private key and certificate request:
|
|
```sh {linenos=false}
|
|
openssl req -newkey rsa:4096 -nodes -sha256 \
|
|
-subj "/CN=mysite.myorg.internal" \
|
|
-keyout server-key.pem \
|
|
-out server-req.pem
|
|
```
|
|
|
|
If you want to add Subject Alternative Names (SANs) to make your cert valid for multiple DNS names, you can use the encantation below:
|
|
```sh {linenos=false}
|
|
openssl req -newkey rsa:4096 -nodes -days 3650 -sha256 \
|
|
-subj "/CN=mydomain.com" \
|
|
-reqexts SAN \
|
|
-config <(cat /etc/ssl/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:site1.myorg.internal,DNS:site2.myorg.internal")) \
|
|
-key server-key.pem \
|
|
-out server-req.pem
|
|
```
|
|
|
|
2. Generate the X509 certificate for the server:
|
|
|
|
When setting `-days`, the validity time can be no longer than *398 days (13 months)* or you might see errors. This is for security reasons,
|
|
read up on the history behind it [here at global sign](https://www.globalsign.com/en/blog/maximum-ssltls-certificate-validity-now-one-year).
|
|
|
|
The flag `-set_serial` is like an ID number for each cert issued by your CA. It must be a positive integer and unique to each cert issued.
|
|
Below I'm just using `date +%s` to get a unix timestamp for a simple serial number.
|
|
|
|
For further reading see [RFC 5280](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.2).
|
|
|
|
```sh {linenos=false}
|
|
openssl x509 -req -days 398 -set_serial $(date +%s) -sha256 \
|
|
-in server-req.pem \
|
|
-out server-cert.pem \
|
|
-CA ca-cert.pem \
|
|
-CAkey ca-key.pem
|
|
|
|
|
|
# Or once again, if you need to specify SANs
|
|
openssl x509 -req -days 398 -set_serial $(date +%s) -sha256 \
|
|
-extfile <(printf "subjectAltName=DNS:site1.myorg.internal,DNS:site2.myorg.internal") \
|
|
-in server-req.pem \
|
|
-out server-cert.pem \
|
|
-CA ca-cert.pem \
|
|
-CAkey ca-key.pem
|
|
```
|
|
|
|
## Verifying the Certificate
|
|
|
|
1. To verify the server certificate:
|
|
|
|
```sh {linenos=false}
|
|
$ openssl verify -CAfile ca-cert.pem server-cert.pem
|
|
```
|