Help us shape the future of Go! Take the 2026 Go Developer Survey

certtool

module
v0.8.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 25, 2026 License: Apache-2.0

README

Cert Tool

Logo

CI Go Reference codecov

A tool for generating X.509 certificates and private keys for TLS, code signing, and app signing, available as a standalone CLI and Go library. One command sets up a common situation: certtool writes a commented spec and generates every certificate in it.

# Download (Linux amd64, see Downloads for other builds)
curl -fLo certtool https://github.com/cloudfra/certtool/releases/latest/download/certtool-linux_amd64 && chmod +x certtool

# An Android app signing key: writes certs/android-signing.yaml, the certificate and key, and the
# android-signing.pfx keystore, whose password comes from CERTTOOL_PFX_PASSWORD
export CERTTOOL_PFX_PASSWORD="$KEYSTORE_PASSWORD"
./certtool --scenario android-signing --output-dir certs

Quick start

--scenario picks the certificates for a situation, writes them as a commented spec to --output-dir, and generates them there. The comments say what each certificate is for and how to install it.

Set your own subject fields, hostnames, and clients on the same command line:

# Websites: a root CA, an issuing CA name constrained to the hostnames, and a server certificate
./certtool --scenario web --organization "Acme Corp" --organizational-unit Platform \
  --hostnames www.example.com,example.com --output-dir certs

# Combine scenarios with commas: a VPN gateway with client certificates, and a code signing certificate
./certtool --scenario vpn,code-sign --organization "Acme Corp" --country CA \
  --hostnames vpn.example.com --clients alice,bob --output-dir certs

To change the certificates, edit the spec and generate again. Certificates already in --output-dir are reused, so new entries join the existing hierarchy; delete a certificate's files to regenerate it, or pass --overwrite to regenerate everything:

$EDITOR certs/web.yaml    # add a server, change a validity, ...
./certtool --spec certs/web.yaml --output-dir certs

Running the same --scenario command again is safe in automation: it reuses the spec and the certificates. If the spec was edited, it stops and says to use --spec, so edits are never lost. To only write the spec, add --export-spec certs.yaml (or - for standard output).

Scenario Makes
web Root and issuing CA, name constrained to --hostnames, and a server certificate
local-dev A self-signed certificate for localhost and development names
mtls, microservices CAs, server certificates, and client certificates for mutual TLS and service-to-service calls
database Server certificates for PostgreSQL, MySQL, Redis, and MongoDB, and client certificates for database users
active-directory An enterprise root and issuing CA, and an LDAPS .pfx per domain controller
kubernetes Every certificate kubeadm expects in /etc/kubernetes/pki
vpn, eap-tls OpenVPN and IKEv2 gateways, 802.1X Wi-Fi, and their client certificates
iot, kafka, docker MQTT brokers and devices, Kafka brokers and clients, the Docker API
git, ssh, ftps Git servers and commit signing (S/MIME or SSH), SSH and SFTP keys, FTPS
ios, android Development CAs and backends for iPhone and Android apps
android-signing, code-sign An Android upload key, and Windows or Linux code signing
proxy A CA for a TLS-inspecting proxy

Scenarios lists each one's inputs and the spec it writes. --yubikey signs a scenario with a root CA on a YubiKey, and --encrypt-to encrypts its keys.

Features

  • Set up a common situation in one command with --scenario: websites, mutual TLS, Kubernetes, Active Directory, VPNs, Git, SSH, iOS and Android apps, and more.
  • Generate self-signed X.509 public certificate and private key pairs in PEM format.
  • Generate code signing certificates as PKCS#12 (.pfx) files for Windows binary signing with signtool.exe.
  • Named platform profiles (windows7, windows10, windows11, linux, android) set secure defaults automatically.
  • Create CA (root) certificates for establishing a chain of trust.
  • Sign certificates with a parent CA to build certificate chains.
  • Keep the root CA key on a YubiKey: generate it on the device and sign certificates with it, without the key ever leaving the YubiKey.
  • Encrypt private key and .pfx files to a key on a YubiKey, or other age recipients, with --encrypt-to, so reading them needs the YubiKey instead of a password.
  • Generate whole certificate hierarchies (root, intermediates, leaves) in one command with --chain, or from a YAML spec with --spec.
  • RSA (2048, 4096-bit) and ECDSA (P-256, P-384, P-521) key algorithms, signed with a hash that matches the key (SHA-256, or SHA-384/SHA-512 for P-384/P-521).
  • Subject Alternative Names (SANs) for hostnames and IP addresses.
  • Always includes localhost and 127.0.0.1 as SANs (TLS mode).
  • Configure X.509 subject fields: Country, Organization, Locality, Province, and more.
  • Available as a Go library (github.com/cloudfra/certtool/pkg/certtool) for programmatic certificate generation.
  • Prebuilt binaries for all major operating systems and architectures.

Usage

Each example writes its files to the current directory. The use case guides walk through complete setups, including trusting the certificates and verifying them.

TLS certificates
# Self-signed certificate for localhost (RSA-2048, writes app.crt and app.key)
./certtool

# Certificate for your own hostnames and IP addresses
./certtool --common-name myapp.localhost --hostnames myapp.localhost,192.168.1.20 \
  --key-type ECDSA-256 --public-certificate dev.crt --private-key dev.key

# Root CA, then a server certificate signed by it
./certtool --ca --common-name "Acme Root CA" --organization Acme --key-type ECDSA-384 --validity 87600h \
  --max-path-len 0 --permitted-dns-domains example.com \
  --public-certificate root-ca.crt --private-key root-ca.key
./certtool --common-name api.example.com --hostnames api.example.com \
  --parent-public-certificate root-ca.crt --parent-private-key root-ca.key \
  --public-certificate api.crt --private-key api.key

Guides: Local development HTTPS, Private CA and mutual TLS.

Code signing certificates
# Windows 10 and 11: ECDSA P-256 in an AES-256 encrypted codesign.pfx
export CERTTOOL_PFX_PASSWORD="$PFX_PASSWORD"   # or --pfx-password
./certtool --code-sign --common-name "Acme Internal Software"

# Windows 7 and 8: RSA-2048 in a legacy 3DES encrypted PFX
./certtool --code-sign --target windows7 --pfx-output codesign-legacy.pfx

# PEM certificate and key for osslsigncode on Linux or macOS
./certtool --code-sign --target linux --public-certificate codesign.crt --private-key codesign.key
Target Aliases Key type Output Use with
windows10 (default) win10 ECDSA P-256 PFX, AES-256 Windows 10/11 signtool.exe
windows11 win11 ECDSA P-256 PFX, AES-256 Windows 11 signtool.exe
windows7 win7, windows8, win8, windows8.1, win8.1 RSA-2048 PFX, 3DES (legacy) Windows 7/8 signtool.exe
linux ECDSA P-256 PEM certificate and key osslsigncode

--key-type overrides the key type of any target. Guide: Code signing.

Certificate hierarchies

--chain takes the number of certificates in each layer, from the root down. The last layer is the leaves.

# One root, two intermediate CAs, and three leaves under each intermediate, in certs/
./certtool --chain 1,2,3 --common-name svc --organization Acme --output-dir certs

# Write the hierarchy as a YAML spec to edit, then generate from it
./certtool --chain 1,2,1 --export-spec certs.yaml
./certtool --spec certs.yaml --output-dir certs

For a common situation, start from a scenario instead.

Every certificate gets a unique name (for example Acme Root CA, Acme Intermediate CA 1, svc 1.2), so files never overwrite each other. Running --spec or --chain again reuses the certificates already in --output-dir, so adding entries to a spec extends the hierarchy; --overwrite regenerates everything (details). The certificate spec documentation covers naming, the spec format, and --name-prefix.

YubiKey root CA
# The PIN comes from CERTTOOL_YUBIKEY_PIN or --yubikey-pin; certtool never prompts
read -rs -p "YubiKey PIN: " CERTTOOL_YUBIKEY_PIN && export CERTTOOL_YUBIKEY_PIN

# Once: generate the root CA key on the YubiKey and write its certificate to root.crt
./certtool --yubikey-generate-root --common-name "Acme Root CA" --organization Acme \
  --key-type ECDSA-384 --validity 87600h --public-certificate root.crt

# Sign an intermediate CA with the YubiKey, then sign leaves with the intermediate
./certtool --yubikey --ca --common-name "Acme Issuing CA" --organization Acme \
  --public-certificate issuing-ca.crt --private-key issuing-ca.key
./certtool --common-name api.example.com --hostnames api.example.com \
  --parent-public-certificate issuing-ca.crt --parent-private-key issuing-ca.key \
  --public-certificate api.crt --private-key api.key

--yubikey --spec certs.yaml does the same from a YAML spec: the YubiKey signs each top-level entry (example).

--yubikey signs with a root CA that is already on the YubiKey, made by --yubikey-generate-root or by any other tool. It works on Windows with the prebuilt downloads, and on Linux, macOS, FreeBSD, and OpenBSD when certtool is built with CGO_ENABLED=1. Guide: YubiKey root CA, covering both a new and an existing root, requirements, automation, and troubleshooting.

Encrypted private keys

Keys that must stay files, such as server keys, can be encrypted to a key on a YubiKey made by age-plugin-yubikey, and to a backup. Encrypting needs neither the YubiKey nor the plugin:

./certtool --spec certs.yaml --output-dir certs --encrypt-to age1yubikey1...,age1...   # writes .key.age and .pfx.age files

# Later runs decrypt the keys they reuse with the YubiKey; CERTTOOL_YUBIKEY_PIN holds the PIN
./certtool --spec certs.yaml --output-dir certs --encrypt-to age1yubikey1...,age1... --age-yubikey

See Encrypted private keys.

Flags
TLS flags
Flag Default Description
--public-certificate app.crt X.509 public certificate output file
--private-key app.key Private key output file
--ca false Generate a root/CA certificate
--max-path-len -1 (no limit) With --ca or --yubikey-generate-root: how many CAs may sit below the CA (0 = it signs only leaves)
--permitted-dns-domains With --ca or --yubikey-generate-root: comma-separated DNS domains that certificates below the CA may use, as critical name constraints
--permitted-ip-ranges With --ca or --yubikey-generate-root: comma-separated CIDR ranges that certificates below the CA may use
--key-type RSA-2048 Key algorithm and length (RSA-2048, RSA-4096, ECDSA-256, ECDSA-384, ECDSA-521)
--hostnames Comma-separated hostnames and IP addresses to add as SANs
--validity 8760h (1 year) How long the certificate is valid for, as a Go duration (e.g. 8760h, 720h, 24h)
--common-name Common Name (CN) field of the X.509 subject (defaults to --organization)
--country US Country (C) field of the X.509 subject
--organization cloudfra Organization (O) field of the X.509 subject
--organizational-unit gows Organizational Unit (OU) field of the X.509 subject
--locality Seattle Locality/city (L) field of the X.509 subject
--province WA Province/state (ST) field of the X.509 subject
--parent-public-certificate Parent CA public certificate for signing
--parent-private-key Parent CA private key for signing (unencrypted PEM: PKCS#1, SEC 1, or PKCS#8)
Code signing flags
Flag Default Description
--code-sign false Generate a code signing certificate instead of a TLS certificate
--target windows10 Platform profile: windows7, windows10, windows11, linux, android (an RSA-4096 app signing keystore) (and aliases)
--pfx-output codesign.pfx Output path for the PKCS#12 (.pfx) file (Windows and Android targets)
--pfx-password Password for the .pfx file (defaults to CERTTOOL_PFX_PASSWORD; empty = no password)
Hierarchy flags
Flag Default Description
--chain Number of certificates per layer, from the root down (3, 1,1, 1,2,3). The last layer is the leaves. Cannot be combined with --spec
--name-prefix Prefix placed in front of the name of every certificate generated by --chain
--spec Path to a YAML spec describing the certificates to generate
--output-dir . Output directory for certificates generated by --spec or --chain
--overwrite false With --spec or --chain, regenerate every certificate instead of reusing the files already in --output-dir
--export-spec Write the resolved spec as YAML to this path instead of generating certificates. Works with --scenario, --chain, --spec, or plain flags; --scenario without it writes the spec to --output-dir and generates the certificates too. - writes to standard output
--scenario Write a commented spec for a common situation to --output-dir and generate its certificates, or with --export-spec only write the spec. Comma separated: web, local-dev, mtls, microservices, database, active-directory, kubernetes, vpn, eap-tls, iot, kafka, docker, git, ssh, ftps, ios, android, android-signing, code-sign, proxy. With --yubikey the root CA is the one on the YubiKey (details)
--clients Common names of the client certificates, users, or devices that --scenario makes, such as --scenario vpn --clients alice,bob
YubiKey flags
Flag Default Description
--yubikey false Sign with the root CA stored on a YubiKey instead of --parent-public-certificate/--parent-private-key
--yubikey-generate-root false Generate a root CA key on a YubiKey, store its self-signed certificate there, and write it to --public-certificate. Supports ECDSA-256, ECDSA-384, RSA-2048, and RSA-4096 (firmware 5.7+)
--yubikey-serial Serial number of the YubiKey to use. Required only when more than one is connected
--yubikey-slot 9c PIV slot holding the root CA: 9a, 9c, 9d, 9e, or 82 through 95
--yubikey-pin YubiKey PIN, required by --yubikey and --yubikey-generate-root (defaults to CERTTOOL_YUBIKEY_PIN; certtool never prompts)
--yubikey-management-key Management key in hex for --yubikey-generate-root (defaults to CERTTOOL_YUBIKEY_MANAGEMENT_KEY, otherwise the PIN-protected or factory default key)
--yubikey-touch-policy always Touch requirement for a key made by --yubikey-generate-root: always (every signature), cached (one touch per 15 seconds), or never
--yubikey-overwrite false Allow --yubikey-generate-root to replace a slot that already holds a certificate. The old key is destroyed
Encryption flags
Flag Default Description
--encrypt-to Encrypt every private key and .pfx to these comma-separated age recipients, written with an .age suffix: age1..., age1pq1..., age1tag1..., or age1yubikey1... (a key on a YubiKey)
--age-identity-file Age identity files that decrypt encrypted keys certtool reads: --parent-private-key, and the keys --spec and --chain reuse. CERTTOOL_AGE_IDENTITY can hold identities too
--age-yubikey false Decrypt those keys with the age key on the YubiKey. Needs the PIN
General flags
Flag Default Description
--version false Print version and build information, then exit

AI agents

certtool ships a skill that teaches AI agents how to use it: choosing a mode, recipes, handling secrets, and common mistakes. It lives in skills/certtool and follows the Agent Skills format, so any agent that supports skills can load it. In Claude Code, install it as a plugin:

/plugin install certtool --marketplace cloudfra/certtool

Claude Code versions before 2.1.275 take two steps: /plugin marketplace add cloudfra/certtool, then /plugin install certtool@certtool.

llms.txt indexes the documentation for language models, and AGENTS.md guides agents that change certtool itself.

Downloads

OS Arch Link
Linux amd64 curl -fLo certtool https://github.com/cloudfra/certtool/releases/latest/download/certtool-linux_amd64 && chmod +x certtool
Linux arm64 curl -fLo certtool https://github.com/cloudfra/certtool/releases/latest/download/certtool-linux_arm64 && chmod +x certtool
macOS arm64 curl -fLo certtool https://github.com/cloudfra/certtool/releases/latest/download/certtool-darwin_arm64 && chmod +x certtool
Windows amd64 $ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest -Uri "https://github.com/cloudfra/certtool/releases/latest/download/certtool-windows_amd64.exe" -OutFile "certtool.exe" -UseBasicParsing
Windows arm64 $ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest -Uri "https://github.com/cloudfra/certtool/releases/latest/download/certtool-windows_arm64.exe" -OutFile "certtool.exe" -UseBasicParsing

For other platforms, install with Go: go install github.com/cloudfra/certtool/cmd/certtool@latest.

Docker Images

Images are tagged by release (there is no latest tag):

docker run --rm docker.io/cloudfra/certtool:v0.7.0 --version

Build

example workflow Go Report Card Go Reference codecov

Install the latest stable version of Go.

# Clone the repository
git clone git@github.com:cloudfra/certtool.git
# Build the binary
make -j$(nproc)

Test

make test
make bench

Directories

Path Synopsis
cmd
certtool command
Package main is the entry point for certtool.
Package main is the entry point for certtool.
Package internal exposes build-time version metadata injected via ldflags.
Package internal exposes build-time version metadata injected via ldflags.
certtool
Package certtool implements the certtool command.
Package certtool implements the certtool command.
logging
Package logging configures the process-wide slog logger.
Package logging configures the process-wide slog logger.
safefile
Package safefile writes files that may hold secrets, such as private keys.
Package safefile writes files that may hold secrets, such as private keys.
pkg
certtool
Package certtool is the public interface for integrating with auto generating certificates.
Package certtool is the public interface for integrating with auto generating certificates.
yubikey
Package yubikey uses the PIV applet of a YubiKey as a certificate authority.
Package yubikey uses the PIV applet of a YubiKey as a certificate authority.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL