2-cent Certification Authority
This program is meant to replace the easy-rsa scripts found in default installations for OpenVPN.
Two independent versions are provided here:
- Python version (2cca.py) based on pyopenssl
- A single-file C version based on OpenSSL
The Python version is placed in the Public Domain. It was used as a proof-of-concept to demonstrate everything could be done directly with OpenSSL without involving the command-line tools. It is completely usable to generate root, server, and client certificates.
The C version is MIT-licensed. See LICENSE.
Use 'make'. You can also compile with:
cc -o 2cca 2cca.c -lcrypto
- ArchLinux on Raspberry Pi -- openssl 1.0.2.e-1
- Debian on x64 -- openssl 1.0.2.e-1
On OSX you cannot use the system openssl libraries but you can substitue them by libressl, available from brew. I got it to compile with:
export LIBRE=/usr/local/opt/libressl cc -I$(LIBRE)/include -L$(LIBRE)/lib -o 2cca 2cca.c -lcrypto
Brew says I am using version 2.3.1 of libressl.
What it does
2cca can generate certificates and keys for various roles. Supported roles are:
- Root CA: a self-signed Certification Authority
- Sub CA: a Certification Authority, signed by another CA
- OpenVPN server
- OpenVPN client
- Web server
Specify which kind of certificate you want to create and indicate which fields and properties are needed. A certificate file and key will be created in the local directory in PEM format.
Creating certificates follows the same syntax for all types of certificates:
2cca TYPE [properties] TYPE Description ---- ----------- root Create a (self-signed) root CA certificate sub Create a Subordinate CA certificate server Create an OpenVPN server certificate client Create an OpenVPN client certificate www Create a Web server certificate
Certificate fields and properties are specified on the command line by specifying a list of key=value blocks. If the value contains blanks, surround the whole block with double or simple quotes. Supported keys and their meaning are:
Key Meaning Example Default --- ------- ------- ------- O Organisation "O=ACME Inc" O=Home or root C Country 2-letter code C=UK none CN Common Name CN=MyServer same as TYPE L Locality or City L=Munich none ST State ST=Bavaria none email Email firstname.lastname@example.org none ca Signing CA ca=Sub ca=root days Duration days=15 days=365 dns Host name dns=www.example.com none The O field (Organization) defaults to O=Home for root and is always inherited from the issuer. The OU field (Organizational Unit) is automatically set by certificate type: Type OU ---- -- root OU=Root sub OU=Sub server OU=Server client OU=Client www OU=Server
Certificate and key are saved in the current directory as CN.crt and CN.key, where CN is the requested Common Name. For client identities, a password-less P12 is also generated.
The default signing CA is named CN=root. If you change the root name (CN=xx) or want to use a specific CA for signature, use ca=NAME, where NAME is the CN for the CA you want to use. Example:
# Generate a root called MyROOT: 2cca root CN=MyROOT C=UK -> Generates MyROOT.crt and MyROOT.key # Generate a Sub CA called MySUB and sign it with MyROOT: 2cca sub ca=MyROOT CN=MySUB C=UK -> Generates MySUB.crt and MySUB.key, signed by MyROOT # Generate a client certificate for 'joe' and sign it with MySUB: 2cca client ca=MySUB CN=joe C=UK -> Generates joe.crt, joe.key, joe.p12, signed by MySUB # If you want to verify the chain with openssl: cat MyROOT.crt MySUB.crt > bundle openssl verify -CAfile bundle joe.crt -> joe.crt: OK
Change certificate duration using days=xx where xx is in days from today. Default certificate duration is 3650 days. Example:
# Generate a client certificate for 15 days: 2cca client days=15 ca=MyROOT
You can generate RSA keys by specifying a key size with rsa=xx Example:
Generate a root certificate with a 4096 RSA key: 2cca root rsa=4096
You can also generate elliptic-curve keys for clients and servers. Use ec=curve, where curve is one of the named curves supported by openssl. You can get a list of elliptic curves supported on your system by running:
openssl ecparam -list_curves
# Generate a client cert with an ECC key with curve prime256v1 2cca client ec=prime256v1
The default hash function is sha256. There is currently no way to change this from the command-line.
Certificate Revocation Lists
Primitive CRL management is also offered. The two associated commands are:
2cca revoke NAME ca=xx 2cca crl ca=xx
You revoke a certificate by name, i.e. by CN, which also happens to be the base file name. To revoke joe's certificate issued by MySUB:
# Revoke joe issued by MySUB 2cca revoke joe ca=MySUB
You can review the CRL for a CA like this:
# See CRL for ca=MySUB 2cca crl ca=MySUB -- Revoked certificates found in CRL serial: 2CCA95D9A9F95BEE6C44564E0A514B45 date: Jan 19 22:04:51 2016 GMT # Display the CRL using openssl openssl crl -in MySUB.crl -text
You can also generate Diffie-Hellmann parameters. Useful for OpenVPN setups.
# Generate DH-2048 parameters 2cca dh Generating DH parameters (2048 bits) -- this can take long done
It takes ages to generate these, and the command does not display any progress. You probably want to do it with OpenSSL. I just coded it for convenience when the openssl command is not present.
Starting from scratch, you want to first create a root (self-signed) CA. It will be named 'MyRoot', for a duration of 1000 days, have a 1024-bit RSA key, and be based in the UK.
2cca root CN=MyRoot days=1000 rsa=1024 C=UK
Check that you now have MyRoot.crt and MyRoot.key in the current directory.
You want two Sub-CAs then: one to handle OpenVPN servers and clients, and another one to handle WWW server certificates. Both are children of the root you just created.
# Generate the OpenVPN CA named 'VPNCA' for 900 days, 1024-bit RSA: 2cca sub CN=VPNCA days=900 rsa=1024 ca=MyRoot C=UK # Generate the www server CA named 'WWWCA' for 500 days, 1024-bit RSA: 2cca sub CN=WWWCA days=500 rsa=1024 ca=MyRoot C=UK
You now have VPNCA.[crt|key] and WWWCA.[crt|key] in the current directory.
Let us now issue client and server certificates for OpenVPN with the appropriate CA. We will use 512-bit RSA keys and set a validity period of one year for the server, and two weeks for the client.
# Generate a cert for server named 'vpn-server' for 365 days, 512-bit RSA: 2cca server ca=VPNCA days=365 CN=vpn-server rsa=512 C=UK # Generate a cert for a client named 'joe' for 15 days, 512-bit RSA: 2cca client ca=VPNCA days=15 CN=joe rsa=512 C=UK
You can now install vpn-server.[crt|key] in the appropriate places and send the client credentials to Joe: either send joe.[crt|key] or joe.p12
Let us issue a web server certificate for a server named 'www.example.com' for a duration of one year, with a 2048-bit RSA key:
# Generate a web server certificate 2cca www ca=WWWCA days=365 rsa=2048 CN=www.example.com dns=www.example.com
Check that you have files called www.example.com.[crt|key] in the current directory.
You can also issue certificates that arte valid for multiple domains or joker certificates by issuing several dns= properties on the command-line. Example:
# Generate a certificate for *.dom1.abc and *.dom2.abc 2cca www ca=WWWCA "dns=*.dom1.abc" "dns=*.dom2.abc"
There is no database of issued certificates to maintain because they use 128-bit serial numbers, thus are already unique without having to remember an increasing index.
There is absolutely no key protection whatsoever. You are in charge of protecting the .key files as you need. For personal VPNs this is not really an issue, but for something in need of security you probably want to import keys into smart cards. This is meant to replace easy-rsa, not a full-fledged PKI.
-- nicolas314 - 2016-January