I'm using the following script to create certificates using my own internal CA(Work in progress):
#!/bin/bash
while [[ "$#" < 1 ]];do
echo "Usage: cert-admin.sh [COMMAND] [OPTIONS]\n"
echo " Commands:"
echo " newpair - Creates a key and signed certificate"
echo " revoke - Revokes a certificate and re-creates the intermediate CRL"
echo " newcrl - Re-creates the intermediate CRL"
echo ""
echo " Examples: cert-admin.sh newpair server example.mysite.com"
echo " cert-admin.sh revoke example.mysite.com"
echo ""
echo " Types: server"
exit 1
done
command=$1
function newCRL {
cd /root/ca
rm -f intermediate/crl/intermediate.crl.pem
openssl ca -config intermediate/openssl.cnf \
-gencrl -out intermediate/crl/intermediate.crl.pem
openssl crl -in intermediate/crl/intermediate.crl.pem -noout -text
}
while [[ $command == 'newpair' ]];do
type=$2
fqdn=$3
while [[ $type == 'server' ]];do
cd /root/ca
openssl genrsa -out intermediate/private/$fqdn.key.pem 2048
openssl req -reqexts SAN \
-config <(cat intermediate/openssl.cnf \
<(printf "\n[SAN]\nsubjectAltName=DNS:$fqdn\n\n")) \
-key intermediate/private/$fqdn.key.pem \
-new -sha256 -out intermediate/csr/$fqdn.csr.pem
openssl ca -config intermediate/openssl.cnf \
-extensions server_cert -days 375 -notext -md sha256 \
-in intermediate/csr/$fqdn.csr.pem \
-out intermediate/certs/$fqdn.cert.pem
chmod 444 intermediate/private/$fqdn.key.pem
chmod 444 intermediate/certs/$fqdn.cert.pem
openssl x509 -noout -text \
-in intermediate/certs/$fqdn.cert.pem
openssl verify -CAfile intermediate/certs/ca-chain.cert.pem \
intermediate/certs/$fqdn.cert.pem
echo "ca-chain: /root/ca/intermediate/certs/ca-chain.cert.pem"
echo "key: /root/ca/intermediate/private/$fqdn.key.pem"
echo "cert: /root/ca/intermediate/certs/$fqdn.cert.pem"
break;
done
break;
done
while [[ $command == 'revoke' ]];do
cert=$2
cd /root/ca
openssl ca -config intermediate/openssl.cnf \
-revoke intermediate/certs/$cert.cert.pem
newCRL
break;
done
while [[ $command == 'newcrl' ]];do
newCRL
while [[ $2 != 'cron' ]];do
echo "CRL should be re-created by cron every 30 days. Example:"
echo "30 12 2 * * /root/ca/cert-admin.sh newcrl cron"
break;
done
break;
done
intermediate/openssl.cnf
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = /root/ca/intermediate
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.pem
certificate = $dir/certs/intermediate.cert.pem
crlnumber = $dir/crlnumber
crl = $dir/crl/intermediate.crl.pem
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 = 4096
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
countryName_default = US
stateOrProvinceName_default = Denial
localityName_default = Springfield
0.organizationName_default = MyOrg
organizationalUnitName_default = Research
emailAddress_default = mail@example.com
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ]
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
[ server_cert ]
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[ crl_ext ]
authorityKeyIdentifier=keyid:always
[ ocsp ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning
With the intermediate CA trusted in Arch Linux, the certificate doesn't throw any errors.
However, on Android I get errors. I think it has something to do with SAN
as the Bitwarden Android app shows subjectAltNames[]
and Kiwi browser(Chrome Desktop for Android) shows ERR_CERT_COMMON_NAME_INVALID
.
Using -addext "subjectAltName = DNS:www.example.com"
with -config intermediate/openssl.cnf
doesn't work either.
Creating a self signed cert using:
openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \
-addext "subjectAltName = DNS:www.example.com" \
-subj "/C=US/ST=Denial/L=Springfield/O=MyOrg/CN=www.example.com" \
-keyout web.key -out web.crt
works fine.
EDIT: Common Name
is set to the FQDN when prompted.
EDIT2: To clarify, this is after installing the CA chain cert on the Android device. Running Android 10.
EDIT3: I've narrowed the issue down to SAN not being added due to -config <(cat intermediate/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:$fqdn\n\n"))
not working. Is there another way to include SAN while specifying openssl.cnf
? It's not working for me...