generate self-signed (TOFU) ECC certs for TLS
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
Robey 4570e74281 explain why 8 months ago
lib fix display of private key for ed25519 8 months ago
stubs ayyyy generate an ed25519 key & cert that openssl will read! 8 months ago
tests can now regurgitate an ed25519 cert 8 months ago
.gitignore checkpoint: read and do a tiny bit of validation on a cert 8 months ago
LICENSE.txt add some docs 8 months ago
Makefile split x509 from asn, put both in lib/, add support for reading/writing x509 ECDSA certs of a specific type (nist p256 r1), and add a test proving that 8 months ago
README.md explain why 8 months ago
certified.py i guess "-tls1_3" is only on linux and libreSSL isn't complete yet 8 months ago
cheat-sheet.md add some docs 8 months ago
echo.py i guess "-tls1_3" is only on linux and libreSSL isn't complete yet 8 months ago
mypy.ini checkpoint: got it to parse and save a private key file 8 months ago
poetry.lock add nacl to deps, for curve 25519 8 months ago
pyproject.toml formatting 8 months ago

README.md

Certified

Certified is a small CLI tool for generating a TLS self-signed ("TOFU") ECC certificate and private key, suitable for using in small distributed networks, like gemini.

Two ECC formats are supported:

  • Ed25519 aka Curve25519
    • using PyNaCl, recommended and generally (as of 2021) considered the most trustworthy algorithm
  • ECDSA using secp256r1 (aka nist256p1 aka prime256v1)
    • using the python ecdsa library, subject to side channel attacks, and primarily for toy use

Why?

It's possible to use the openssl toolchain to create self-signed ECC certificates using curve 25519: check out the first reference link for a great explanation and example. But I think these tools are written for people who live, breathe, and swim in the world of X.509 arcana. This app is meant to demonstrate an imagined world where we don't care about hierarchical certificate authorities, or going through a three-step process to request and then confirm a request for a certificate to ourselves from ourselves, when that certificate is little more than a gold filigree doily wrapped around a public key.

You can just run this script, a bit over 500 lines of python, to generate the public/private key pair, and wrap them in the ceremony that makes them palatable to the TLS 1.3 infrastructure. Feel free to copy this code and its ideas for your own projects, subject only to the Apache 2.0 license.

Install

You need a basic python 3 installation, and poetry.

Clone this repository, and then:

poetry install

If you have some other preferred way of dealing with python packages, all of the dependencies are listed in pyproject.toml. They are:

  • python 3.7+
  • ecdsa
  • PyNaCl

Usage

./certified.py --help

# create a new Ed25519 certificate in "myserver-x509-cert.pem" (and its
# private key in "myserver-x509-key.pem") with the CN "myserver", that will
# expire in 365 days:
./certified.py -g myserver-x509 --name myserver --days 365

# show the contents of the certificate:
./certified.py -p myserver-x509-cert.pem

# show the contents of the private key (_including the private key data_):
./certified.py -k myserver-x509-key.pem

# dump out the ASN.1 structure of any random pem file (if you like exploring):
./certified.py --pp myserver-x509-key.pem

Try it out by running the test program echo.py, which will start a snarky echo service over TLS on a local socket and tell you how to connect to it with openssl s_client. Type a line of text through s_client and if it's echoed back to you, congratulations! You have a certificate and key file that can be used in a TLS service!

./echo.py -c myserver-x509

Note that LibreSSL won't work here, because they haven't implemented Ed25519 certificate support yet. If you're on OS X, where LibreSSL is masquerading as openssl, you can install the real openssl via "brew" and run it from /usr/share/opt/openssl/bin/openssl.

References

Authors

License

Apache 2.0 license, included in LICENSE.txt.