Awesome Open Source
Awesome Open Source

Bootstraping PKI with Yubikeys

Helper scripts to build and manage internal Certificate Authorities (CAs) with yubikey devices, because everybody needs a little bit of PKI, and we can definitely make it cheaper and easier to achieve.

This project is intended to be used as a template for the creation and management of certificate infrastructure, with CA information stored in git, and consists of a set of helper utilities to support the creation of root certificates, intermediate and end (client and certificate) Certificate Signing Requests (CSRs), as well as to load certificates and keys on to yubikeys and to use yubikeys to sign CSRs to create certificates.

This requires as many yubikeys as you would like to store certificates on, as well as an offline machine to generate the root keys and intermediate certificates. In future it may be possible to generate all keys on devices to aleviate this need for a trusted / airgapped machine.


What is PKI?

PKI is Public Key Infrastructure, a method using cryptographic certificates to validate or authenticate services or devices. This works using a trust chain, whereby devices can trust a root Certificate Authority (CA), then any certificates issued by that authority can be validated against that root.

Why would you need it?

This is commonly used for HTTPS/TLS on the web, where certificate authorities are distributed as part of your operating system or browser, allowing transparent validation and secure connections through the web. Sometimes it is useful to have an internal certificate authority (or a few), for use between micro-services, or in manufacturing to ensure security with physical devices.

Why would we want to use yubikeys?



Working on OSX, Linux, Some features supported on Windows (and PRs are welcome).


  • Git - to clone and manage the repository
  • OpenSSL - for key and certificate generation and signing
  • OpenSC - smartcard to pkcs11 adaptor
  • engine_pks11 - openssl pkcs11 engine
  • Yubico Manager for managing and interacting with keys

OSX: install with brew install openssl engine_pkcs11 opensc yubico-piv-tool. Linux: install with sudo apt install openssl opensc-pkcs11 libengine-pkcs11-openssl Windows: install with choco install openssl opensc, compile libp11 or grab a pre-compiled (win10, x64) libp11.dll from here, copy config from scripts/engine-win.conf to C:\Program Files\OpenSSL-Win64\openssl.cfg and update opensc-pkcs11.dll and pkcs11.dll locations to match installed.


First, create your own PKI git repository using this as a template, then use the following steps to create a Root / CA, Intermediate certificates, and Client or Server certificates.

Note that when deploying yubikeys you may wish to configure management and PIV pins to ensure that certificates are not mistakenly overwritten, and are only used by authorized parties. We recommend you read this getting started guide for PIV on yubikeys before getting underway.

Creating a new Certificate Authority (Root Certificate)

  1. Run mkdir CA_NAME to create a new directory for your CA
  2. Run cp example-ca/config CA_NAME/config to copy the example config to your new CA directory
  3. Edit CA_NAME/config to configure your CA
  4. Run ./scripts/ CA_NAME "Human Description" to create the root certificate
  5. Run ./scripts/yk-load CA_NAME CA_NAME to load the root certificate onto a connected yubikey
  6. Run rm CA_NAME/CA_NAME.key to remove CA key from the system
  7. Run git add CA_NAME/ to add your new CA to version control

Creating a new Intermediate Certificate

  1. Run ./scripts/ CA_NAME INT_NAME "Human Description" to create a new intermediate CSR under the provided CA
  2. Run ./scripts/ CA_NAME INT_NAME to sign the intermediate CSR using the root yubikey
  • You will need to enter the device pin and press the button on the yubikey when the light flashes to authorize the signing
  1. Disconnect the attached root yubikey and replace it with a new intermediate yubikey
  2. Run ./scripts/yk-load CA_NAME INT_NAME to load the CA onto a connected yubikey
  3. Run rm CA_NAME/INT_NAME.key to remove intermediate key from the system
  4. Run git add CA_NAME/INT_NAME.* to add your new intermediate to version control

Note that steps 4-6 can be elided if you need to do something else with your intermediate certificate

Creating a new End Certificate

  1. Run ./scripts/ CA_NAME CLIENT_NAME or ./scripts/ CA_NAME SERVER_NAME to create a new client or server cerficiate respectively
    • Note that server names are checked when making tls connections, so the server name must match the domain name
  2. Run ./scripts/ CA_NAME END_NAME to sign the client or server CSR using an intermediate yubikey
  • You will need to enter the device pin and press the button on the yubikey when the light flashes to authorize the signing
  1. Run git add CA_NAME/END_NAME.crt to add your new certificate to version control
  2. Do whatever you choose with the created certificate

Creating a new End (Client) Certificate (Windows)

  1. Copy ./templates/client.cfg.tmpl to CA_NAME/CLIENT_NAME.cfg
  2. Run ./scripts/new-client.cmd CA_NAME INT_NAME CLIENT_NAME to generate and sign the new client certificate with the provided intermediate (on the yubikey)


If you have any questions, comments, or suggestions, feel free to open an issue or a pull request.

Get A Weekly Email With Trending Projects For These Topics
No Spam. Unsubscribe easily at any time.
Shell (232,878
Pki (244
Certificate Authority (145
Yubikey (142
Related Projects