initial commit

This commit is contained in:
2025-11-07 03:44:26 +00:00
commit 5d688e1ba7
8 changed files with 434 additions and 0 deletions

5
tls_docs/ca/README.md Normal file
View File

@@ -0,0 +1,5 @@
# Create a Certificate Authority (CA)
- [Create the Root CA](./root_ca_config.md)
- [Create the Intermediate CA](./intermediate_ca_config.md)
- [Sign certificates](certificate_signing.md)

View File

@@ -0,0 +1,61 @@
# Signing certificates for users and servers
Certificate Signing Requests (CSR) can for servers/user can be provided by the system owners or the users. This retains the privacy of the private key. The steps to create key, CSR, and certificate on the CA will be outlined here. If a CSR is provided, skip to the `Inspect the CSR` section. ***THE CSR MUST BE VERIFIED PRIOR TO SIGNING THE CERTIFICATE***.
### Generate the key (the -aes256 can be omitted to not require a password)
```
cd intermediate_ca
openssl genrsa -out private/server.key 2048
chmod 400 private/server.key
```
### Generate the CSR
```
openssl req -config intermediate.cnf -key private/server.crt -new -sha256 -out csr/server.csr
```
### Sign the certificate using the proper extension for the CSR to be signed, using the intermediate.cnf configuration. The example below uses the `server_cert` extension.
```
openssl ca -config intermediate.cnf -extensions server_cert -days 375 -notext -md sha256 -in csr/server.csr -out certs/server.crt
chmod 444 certs/server.crt
```
Alternatively, and recommended, certificate can be created with one or more, usually more, Subject Alternative Names (SAN) as other means of identifying a server. This useful when you want to refer to a server by different names, such as its hostname and FQDN and IP address or the server is part of a load balanced cluster so there is a need to refer to the load balancer IP or FQDN
### Generating the CSR with SAN(s) depending on the where the csr is being created, sudo su -c with the command in ' ' may be required.
Edit the *-subj* and *[SAN]* sections as necessary
```
openssl req -new -sha256 \
-key domain.key \
-subj "/C=2LetterCountry/ST=YourStateorProvince/L=YourCityOrLocality/O=YourOrg/OU=YourOU/CN=example.com" \
-reqexts SAN \
-config <(cat /etc/ssl/openssl.cnf \
<(printf "\n[SAN]\nsubjectAltName=DNS:example.com,DNS:www.example.com,IP:192.168.1.1")) \
-out domain.csr # provide this to the CA for signing
```
### Inspect the CSR
```
openssl req -in csr/siging-request.csr -noout -text
```
### Sign the certificate
```
openssl x509 -req -in csr/server.csr -CA certs/intermediate-ca.crt -CAkey private/intermediate-ca.key -CAcreateserial -out certs/server.crt -days 370 -copy_extensions copy
```
The *-CAcreateserial* will create a serial file to track each created certificate. The *-copy_extensions copy* option will copy the SANs that were specified in the CSR. Some applications require the use of a SAN over the Common Name (CN)
### Verify the certificate and trust chain
```
openssl x509 -noout -text -in certs/server.crt
openssl verify -CAfile certs/ca-bundle.crt certs/server.crt # certs/server.crt
```
The `verify` command should return OK, verifying the trust chain.
### Create the certificate archive bundle and transfer to the server/user if the CSR is is provided, a key will not be bundled, as it will reside with the server or the user. Use the desired transfer method to move the TLS bundle to the desired location
```
tar cvzf bundles/server-or-user.tar.gz certs/server-or-user (private/server-or-user.key added if key was created by the CA).
```

View File

@@ -0,0 +1,125 @@
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = /path/to/intermediate_ca
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
RANDFILE = $dir/private/.rand
private_key = $dir/private/intermediate.key
certificate = $dir/certs/intermediate.crt
crlnumber = $dir/crlnumber
crl = $dir/crl/intermediate.crl
crl_extensions = crl_ext
default_crl_days = 30
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 375
preserve = no
policy = policy_loose
[ policy_strict ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_loose ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
string_mask = utf8only
default_md = sha256
x509_extensions = server_cert
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address
countryName_default = XX
stateOrProvinceName_default = StateOrProvince
localityName_default = City/Locality
0.organizationName_default = OU
organizationalUnitName_default =
emailAddress_default =
[ v3_ca ]
# may not need this extension as this is to sign user/server certificates
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ]
# may not need this extension as this is to sign user/server certificates
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ usr_cert ]
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
copy_extensions = copy
[ server_cert ]
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
copy_extensions = copy # using this to copy alternative names
[ crl_ext ]
authorityKeyIdentifier=keyid:always
[ ocsp ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning

View File

@@ -0,0 +1,59 @@
# Create the Intermediate CA(s)
Now that there's a Root CA established, one or more Intermediate CA can be created. These CAs will be signing certificates on behalf of the Root CA, but ***WILL NOT*** create new CAs.
### Create and edit the intermediate CA configuration
Copy the [root.cnf](./root.cnf) to the Intermediate CA and change the name to *intermediate.cnf* (or whatever name desired to distinguish it from the root CA) on the Intermediate CA and change the policy section under the [CA_default] from `policy_strict` to `policy_loose` since the Intermediate CA isn't signing certificates for other CAs, it can have a less strict policy.
### Create the Intermediate CA key (on Root CA)
```
openssl genrsa -aes256 -out private/intermediate-ca.key
chmod 400 private/intermediate-ca.key
```
### Create the certificate signing request (CSR) for the Intermediate CA using the intermediate.cnf configuration (on the Root CA)
```
openssl req -config intermediate.cnf -new -sha256 -key private/intermediate-ca.key -out csr/intermediate-ca.csr
```
### Sign the certificate using the root.cnf using the `v3_intermediate_ca` extension the paths are defined in the root.cnf so do not need to be explicitly defined in the command (on the Root CA)
```
openssl ca -config root.cnf -extensions v3_intermediate_ca -days 3650 -notext -md sha256 -in csr/intermediate-ca.csr -out certs/intermidate-ca.crt
chmod 444 certs/intermediate-ca.crt
```
### Verify the certificate information and verify the trust chain (on the Root CA)
```
openssl x509 -noout -text -in certs/intermediate-ca.crt
openssl verify -CAfile certs/root-ca.crt certs/intermediate-ca.crt # should return certs/intermediate-ca.crt: OK
```
### Create the ca-bundle.crt (on the Root CA)
```
cat certs/root-ca.crt certs/intermediate-ca.crt > certs/ca-bundle.crt
```
### Create an archive of the ca-bundle.crt intermediate-ca.crt, and intermediate-ca.crt transport to the Intermediate CA using your preferred transport method
```
tar cvzf intermediate-ca.tar.gz certs/ca-bundle.crt certs/intermediate-ca.crt private/intermediate-ca.key
```
### Create dirs, serial, and index for Intermediate CA on Intermediate CA (same dirs as the root but with a bundles dir)
```
mkdir -p /path/to/intermediate_ca/{bundles,certs,csr,crl,newcerts,private}
cd /path/to/intermediate_ca
chmod 700 private
```
### Create a CRL number on Intermediate CA (creating this for later use)
```
echo 1000 > /path/to/intermediate_ca/crlnumber
```
### Extract archive and move the ca-bundle.crt, intermediate-ca.crt, and intermediate-ca.key to their respective dirs (it may ask to override previous permissions. You can accept using y and reapply the permissions)
tar xvf intermediate-ca.tar.gz --strip-components 1
mv {ca-bundle-crt,intermediate.crt} certs/
mv intermediate-ca.key private/
Edit your *intermediate.cnf* to reflect the locations of your *intermediate.crt* and *intermediate.key* and the `dir` option just as was done for the Root CA earlier. The *intermediate.cnf* should look similar to [this](./intermediate.cnf)

108
tls_docs/ca/root.cnf Normal file
View File

@@ -0,0 +1,108 @@
[ ca ]
# `man ca`
default_ca = CA_default
[ CA_default ]
# Default directory locations (make sure to properly set the dir option as it dictates the rest of the other options)
dir = /path/to/root_ca
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
RANDFILE = $dir/private/.rand
# The root key and root certificate.
private_key = $dir/private/root.key
certificate = $dir/certs/root.crt
# For certificate revocation lists.
crlnumber = $dir/crlnumber
crl = $dir/crl/ca.crl
crl_extensions = crl_ext
default_crl_days = 30
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 375
preserve = no
policy = policy_strict
[ policy_strict ]
# policy_strict sets the root CA to sign certificates for intermediate CAs
# POLICY FORMAT section of "man ca" has more info
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates
# See the POLICY FORMAT section of the "man ca"
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
# `req` options. See "man req" for more info
default_bits = 2048
distinguished_name = req_distinguished_name
string_mask = utf8only
default_md = sha256
x509_extensions = v3_ca
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address
# Defaults
countryName_default = US
stateOrProvinceName_default = State/Province
localityName_default = City
0.organizationName_default = Your Org
organizationalUnitName_default = Your OU
emailAddress_default =
[ v3_ca ]
# Normal CA extensions. "man x509v3_config" has more info.
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA "man x509v3_config"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ crl_ext ]
# CRL extensions if needed. See "man x509v3_config" for more info
authorityKeyIdentifier=keyid:always
[ ocsp ]
# If OCSP is needed. See "man ocsp" for more info.
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning

View File

@@ -0,0 +1,39 @@
# Create the Root CA
The Root CA is the *root* of the trust tree. This will be used to create other Intermediate CAs ***ONLY***
### Create directories, serial file, and index file for the Root CA
```
mkdir -p /path/to/root_ca/{bundles,certs,csr,crl,newcerts,private}
chmod 700 private
touch index.txt
echo 1000 > serial
```
### Create the configuration for signing
Copy the [root.cnf](./root.cnf) set the location of the root-ca.key and root-ca.crt for the private_key and certificate options and the `dir` option. This will make it where you don't have to specify the certificate and key when signing certificates
### Create Root CA key
```
cd root_ca
openssl genrsa -aes256 -out private/root-ca.key 4096
chmod 400 private/root-ca.key
```
### Signing Root CA certificate
```
openssl req -config root.cnf -key private/root-ca.key -new -x509 -days 7300 -extensions v3_ca -out certs/root-ca.crt
chmod 444 certs/root-ca.crt
```
### Verify root cert (cert will be encoded so the below command is necessary)
```
openssl x509 -noout -text -in certs/root-ca.crt
```
***THE ONLY CERTIFICATES TO BE SIGNED WITH THE ROOT CA ARE CERTIFICATES FOR INTERMEDIATE CAs***. Now the [Intermediate CA](./intermediate_ca_config.md) (or any number of Intermediate CAs) can be created.