Self-signed certificates: shell script to generate
Tags: certificate, tls, security, script
Published: 2021-05-22 06:38:38

<small>\* The cover image is originally by [OpenClipart-Vectors](https://pixabay.com/users/openclipart-vectors-30363/) and edited with great appreciation.</small>

---

I created Bash script to generate self-signed certificates. It was maybe when I tried some tests on MariaDB or PostgreSQL connection.
Running the script below after setting "global paramters" generates those of server/client/ca (certificate authority).

```sh
#!/bin/sh

# [ global parameters ]
# certificate configuration
readonly CERT_DAYS=36500
readonly RSA_STR_LEN=4096
readonly PREFIX=xxx-
readonly CERT_DIR=./ssl
readonly KEY_DIR=./ssl/private
# certificate content definition
readonly ADDRESS_COUNTRY_CODE=XX
readonly ADDRESS_PREFECTURE=XXXX
readonly ADDRESS_CITY=XXXX
readonly COMPANY_NAME=XXXXXXXX
readonly COMPANY_SECTION=XXXXXXXX
readonly CERT_PASSWORD= # no password
# - ca
readonly CA_DOMAIN=x.domain
readonly CA_EMAIL=ca@email.address
# - server
readonly SERVER_DOMAIN=y.domain
readonly SERVER_EMAIL=server@email.address
# - client
readonly CLIENT_DOMAIN=z.domain
readonly CLIENT_EMAIL=client@email.address

# [ functions ]
echo_cert_params() {
    local company_domain="$1"
    local company_email="$2"

    echo $ADDRESS_COUNTRY_CODE
    echo $ADDRESS_PREFECTURE
    echo $ADDRESS_CITY
    echo $COMPANY_NAME
    echo $COMPANY_SECTION
    echo $company_domain
    echo $company_email
    echo $CERT_PASSWORD     # password
    echo $CERT_PASSWORD     # password (again)
}
echo_ca_cert_params() {
    echo_cert_params "$CA_DOMAIN" "$CA_EMAIL"
}
echo_server_cert_params() {
    echo_cert_params "$SERVER_DOMAIN" "$SERVER_EMAIL"
}
echo_client_cert_params() {
    echo_cert_params "$CLIENT_DOMAIN" "$CLIENT_EMAIL"
}

# [ main ]
# generate certificates
# - ca
openssl genrsa $RSA_STR_LEN > $KEY_DIR/${PREFIX}ca-key.pem
echo_ca_cert_params | \
	openssl req -new -x509 -nodes -days $CERT_DAYS -key $KEY_DIR/${PREFIX}ca-key.pem -out $CERT_DIR/${PREFIX}ca-cert.pem
# - server
echo_server_cert_params | \
	openssl req -newkey rsa:$RSA_STR_LEN -days $CERT_DAYS -nodes -keyout $KEY_DIR/${PREFIX}server-key.pem -out $CERT_DIR/${PREFIX}server-req.pem
openssl rsa -in $KEY_DIR/${PREFIX}server-key.pem -out $KEY_DIR/${PREFIX}server-key.pem
openssl x509 -req -in $CERT_DIR/${PREFIX}server-req.pem -days $CERT_DAYS -CA $CERT_DIR/${PREFIX}ca-cert.pem -CAkey $KEY_DIR/${PREFIX}ca-key.pem -set_serial 01 -out $CERT_DIR/${PREFIX}server-cert.pem
# - client
echo_client_cert_params | \
	openssl req -newkey rsa:$RSA_STR_LEN -days $CERT_DAYS -nodes -keyout $KEY_DIR/${PREFIX}client-key.pem -out $CERT_DIR/${PREFIX}client-req.pem
openssl rsa -in $KEY_DIR/${PREFIX}client-key.pem -out $KEY_DIR/${PREFIX}client-key.pem
openssl x509 -req -in $CERT_DIR/${PREFIX}client-req.pem -days $CERT_DAYS -CA $CERT_DIR/${PREFIX}ca-cert.pem -CAkey $KEY_DIR/${PREFIX}ca-key.pem -set_serial 01 -out $CERT_DIR/${PREFIX}client-cert.pem

# clean up (before permission changed)
rm $KEY_DIR/${PREFIX}ca-key.pem
rm $CERT_DIR/${PREFIX}server-req.pem
rm $CERT_DIR/${PREFIX}client-req.pem

# validate permission
chmod 400 $KEY_DIR/${PREFIX}server-key.pem
chmod 400 $KEY_DIR/${PREFIX}client-key.pem

# verify relationship among certificates
openssl verify -CAfile $CERT_DIR/${PREFIX}ca-cert.pem $CERT_DIR/${PREFIX}server-cert.pem $CERT_DIR/${PREFIX}client-cert.pem
```

Here is the output:

```console
$ bash <the-script-above>.bash
Generating RSA private key, 4096 bit long modulus
................++++
........................................................++++
e is 65537 (0x10001)
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:State or Province Name (full name) []:Locality Name (eg, city) []:Organization Name (eg, company) []:Organizational Unit Name (eg, section) []:Common Name (eg, fully qualified host name) []:Email Address []:Generating a 4096 bit RSA private key
...................................................................................................++++
.......................................................................................++++
writing new private key to './ssl/private/xxx-server-key.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:State or Province Name (full name) []:Locality Name (eg, city) []:Organization Name (eg, company) []:Organizational Unit Name (eg, section) []:Common Name (eg, fully qualified host name) []:Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:writing RSA key
Signature ok
subject=/C=XX/ST=XXXX/L=XXXX/O=XXXXXXXX/OU=XXXXXXXX/CN=y.domain/emailAddress=server@email.address
Getting CA Private Key
Generating a 4096 bit RSA private key
...........................................................................++++
...........................................................++++
writing new private key to './ssl/private/xxx-client-key.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:State or Province Name (full name) []:Locality Name (eg, city) []:Organization Name (eg, company) []:Organizational Unit Name (eg, section) []:Common Name (eg, fully qualified host name) []:Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:writing RSA key
Signature ok
subject=/C=XX/ST=XXXX/L=XXXX/O=XXXXXXXX/OU=XXXXXXXX/CN=z.domain/emailAddress=client@email.address
Getting CA Private Key
./ssl/xxx-server-cert.pem: OK
./ssl/xxx-client-cert.pem: OK
```

And the result:

```console
$ ls -l ssl/*
-rw-r--r--  1 <running-user>  <running-user>  1980 May 22 15:17 ssl/xxx-ca-cert.pem
-rw-r--r--  1 <running-user>  <running-user>  1976 May 22 15:17 ssl/xxx-client-cert.pem
-rw-r--r--  1 <running-user>  <running-user>  1976 May 22 15:17 ssl/xxx-server-cert.pem

ssl/private:
total 16
-r--------  1 <running-user>  <running-user>  3243 May 22 15:17 xxx-client-key.pem
-r--------  1 <running-user>  <running-user>  3243 May 22 15:17 xxx-server-key.pem
```