Your own CA is a self signed certificate that you create and trust in your devices. You can use a single CA or a Root certificate that signs your CA. We will be using OpenSSL
This is the certificate you have to import into all the certificate storages (Windows certmgr, Firefox, Thunderbird, Linux trust store) The private key is needed only when new intermediate CA certificate are signed.
Prepare the project
cd /root/
mkdir -p ROOT/{certs,crl,csr,newcerts,private}
chmod 700 ROOT/private
touch ROOT/index.txt
serial=$(( $RANDOM % 102400 ))
echo $serial > ROOT/serial
echo $serial > ROOT/crlnumber
cat <<EOL > /root/ROOT/openssl.cnf
[ ca ]
default_ca = ROOT_default
[ ROOT_default ]
dir = /root/ROOT
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
private_key = $dir/private/root.key
certificate = $dir/certs/root.pem
crl = $dir/crl/root.crl
crlnumber = $dir/crlnumber
default_days = 375
default_crl_days = 30
default_md = sha256
preserve = no
policy = policy_loose
[ policy_loose ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
string_mask = utf8only
default_md = sha256
x509_extensions = v3_intermediate_ca
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
organizationName = Organization Name
commonName = Common Name
[ v3_intermediate_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:1
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
EOL
Generate the Root certificate
openssl genrsa -out /root/ROOT/private/root.key 4096
openssl req -new -x509 -nodes -days 5475 -key /root/ROOT/private/root.key -out /root/ROOT/certs/root.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) [AU]:RO
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:230RO
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:Root 230RO
Email Address []:
Convert PEM to CER
openssl x509 -inform PEM -in /root/ROOT/certs/root.pem -outform DER -out /root/ROOT/certs/root.cer
This certificate will sign all your certificates
Prepare the project
cd /root/
mkdir -p CA/{certs,crl,csr,newcerts,private}
chmod 700 CA/private
touch CA/index.txt
serial=$(( $RANDOM % 102400 ))
echo $serial > CA/serial
echo $serial > CA/crlnumber
cat <<EOL > /root/CA/openssl.cnf
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = /root/CA
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
private_key = $dir/private/ca.key
certificate = $dir/certs/ca.pem
crl = $dir/crl/ca.crl
crlnumber = $dir/crlnumber
default_days = 375
default_crl_days = 30
default_md = sha256
preserve = no
policy = policy_loose
[ policy_loose ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
string_mask = utf8only
default_md = sha256
x509_extensions = v3_intermediate_ca
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
organizationName = Organization Name
commonName = Common Name
[ v3_intermediate_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
EOL
The pathlen:0 constraint prevents this intermediate from signing other CAs — remove or increase it if you need a deeper chain.
Generate the CA certificate request
cd /root/CA
openssl req -config /root/CA/openssl.cnf -nodes -new -sha256 -keyout private/ca.key -out csr/ca.csr
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) []:RO
State or Province Name []:
Locality Name []:
Organization Name []:230RO
Common Name []:230RO
Sign the CA certificate with the Root certificate
cd /root/CA
openssl ca -config /root/ROOT/openssl.cnf -extensions v3_intermediate_ca -days 3650 -notext -md sha256 -in csr/ca.csr -out certs/ca.pem
Using configuration from /root/ROOT/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName :PRINTABLE:'RO'
organizationName :ASN.1 12:'230RO'
commonName :ASN.1 12:'230RO'
Certificate is to be certified until May 31 14:47:36 2036 GMT (3650 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Database updated