SYNOPSYS
I need a PKI to setup a VPN.
It’s based on my analysis of what easy-rsa does.
DOCUMENTATION
Simple PKI subjectAltName = DNS:example.com, DNS:www.example.com, DNS: app.example.com
How to create your own PKI with openssl -extensions server_cert
Creating a PKI infrastructure with OpenSSL
PROCEDURE
Create the basic infrastructure
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
base=$(pwd)/pki
conf=$base/openssl.conf
key_pass=$base/key_pass
serial=$base/serial
ca_key=$base/private/ca.key
ca_crt=$base/ca.crt
server_key=$base/server.key
server_req=$base/reqs/server.req
server_crt=$base/issued/server.crt
client_key=$base/client.key
client_req=$base/reqs/client.req
client_crt=$base/issued/client.crt
rm -fr pki && mkdir -p pki/{issued,private,reqs,issued,certs_by_serial}
touch pki/index.txt
echo "my_private_key_passwd" > $key_pass
|
Create the openssl configuration file ( see /etc/ssl/openssl.cnf )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
cat <<EOF > $conf
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = MY_DIR
certificate = \$dir/ca.crt # the CA certificate
private_key = \$dir/private/ca.key # The private key
serial = \$dir/serial # the current serial number
database = \$dir/index.txt # database index file
certs = \$dir/certs # where the issued certs are kept
new_certs_dir = \$dir/certs_by_serial # default place for new certs
x509_extensions = sub_ca_cert
policy = policy_anything
# Extensions to add when Root CA creates an Subordinate Certificate CA (Public Key)
[ sub_ca_cert ]
basicConstraints = CA:true
keyUsage = critical, cRLSign, keyCertSign
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid, issuer
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
serialNumber = optional
[req]
default_bits = 2048
prompt = yes
distinguished_name = cn_only
x509_extensions = req_exts
[ cn_only ]
commonName = Common Name (eg: your user, host, or server name)
commonName_max = 64
commonName_default = AsYnK
[ req_exts ]
basicConstraints = CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
keyUsage = cRLSign, keyCertSign
[ server_exts ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
extendedKeyUsage = serverAuth
keyUsage = digitalSignature,keyEncipherment
subjectAltName = DNS:openvpn
[ client_exts ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
extendedKeyUsage = clientAuth
keyUsage = digitalSignature
EOF
sed -i "s#MY_DIR#$base#" $conf
export OPENSSL_CONF=$conf
|
Generate the CA private key
1
2
|
openssl genpkey -algorithm ed25519 -out $ca_key -aes256 -pass file:$key_pass
openssl pkey -in $ca_key -passin file:$key_pass -text
|
Generate the CA certificate
1
2
|
openssl req -utf8 -new -x509 -days 3650 -sha256 -key $ca_key -passin file:$key_pass -out $ca_crt
openssl x509 -in $ca_crt -text -noout
|
Generate the server private key and certificate signing request
1
2
3
|
openssl req -utf8 -new -newkey ed25519 -keyout $server_key -out $server_req -noenc
openssl pkey -in $server_key -text -noout
openssl req -in $server_req -text -noout
|
Generate the client private key and certificate signing request
1
2
3
|
openssl req -utf8 -new -newkey ed25519 -keyout $client_key -out $client_req -noenc
openssl pkey -in $client_key -text -noout
openssl req -in $client_req -text -noout
|
Show the CN of each request
1
2
|
openssl req -in $server_req -noout -subject -nameopt utf8,sep_multiline,space_eq,lname,align
openssl req -in $client_req -noout -subject -nameopt utf8,sep_multiline,space_eq,lname,align
|
Generate a random serial and sign the server certificate with the CA
1
2
3
|
openssl rand -hex 16 > $serial
openssl ca -utf8 -batch -days 825 -in $server_req -out $server_crt -extensions server_exts -passin file:$key_pass
openssl x509 -in $server_crt -text -noout
|
Generate a random serial and sign the client certificate with the CA
1
2
3
|
openssl rand -hex 16 > $serial
openssl ca -utf8 -batch -days 825 -in $client_req -out $client_crt -extensions client_exts -passin file:$key_pass
openssl x509 -in $client_crt -text -noout
|