Compare commits
3 Commits
Author | SHA1 | Date |
---|---|---|
|
ae186ff197 | 8 months ago |
|
9beca1b180 | 8 months ago |
|
e1e36aa07d | 8 months ago |
@ -0,0 +1,128 @@
|
||||
---
|
||||
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
|
||||
```
|
Loading…
Reference in new issue