Simple CA

test

simple-ca.sh is a Bash script that provides functions for creating and managing a simple Certificate Authority (CA) and generating certificates. It can create a single or two-level CA hierarchy, and generate client-server TLS certificates. The script is designed to be simple and easy to use, making it suitable for testing and development purposes, where a self-signed certificate is not sufficient.

All certificates generated by this script have a random serial number.

Functions

make_ca()

This function creates a root CA certificate and private key. It can optionally create an intermediate CA certificate and private key, which is signed by the root CA. The function takes several parameters to customize the CA creation process, such as the CA name, validity period, and whether to create an intermediate CA.

Usage:

make_ca  [--days <validity_days>] [--issuing-ca <name>] <ca_directory> <ca_name>
  • <ca_directory>: The directory where the CA files will be stored.
  • <ca_name>: The name of the CA.
  • --days <validity_days>: Optional. The number of days the CA certificate will be valid. Default is 3650 days (10 years).
  • --issuing-ca <name>: Optional. If specified, creates an intermediate CA with <ca_name> as the intermediate CA name and using as certificate and key file prefix for the issuing CA (instead of root's ca).

It also maintains a ca_bundle.pem file in the CA directory containing the root CA and any issuing CA certificates concatenated together. Use this bundle with openssl verify -CAfile <ca_directory>/ca_bundle.pem instead of relying on hash symlinks — this works identically on Linux, macOS, and Windows without symlink privileges.

make_cert()

This function generates a certificate and private key with TLS Web Server Authentication and Client Authentication EKUs. The certificate is signed by the specified CA (either root or intermediate).

Usage:

make_cert --ca-dir <ca_directory> [--days <validity_days>] [--issuing-ca <name>] <cert_directory> <subject_name>
  • <ca_directory>: The directory where the CA files are stored (used to find the CA certificate and key for signing).
  • <cert_directory>: The directory where the generated certificate and key will be stored.
  • <subject_name>: The subject name (Common Name) for the certificate.
  • --days <validity_days>: Optional. The number of days the certificate will be valid. Default is 365 days.
  • --issuing-ca <name>: Optional. If specified, uses the CA with the key <name>_key.pem and certificate <name>_cert.pem for signing instead of the root CA.

make_pfx()

This function creates a PKCS#12 (PFX) file containing the certificate, private key, and CA certificate chain. This is useful for importing the certificate into applications that require a PFX file.

Usage:

make_pfx --ca-dir <ca_directory> [--issuing-ca <file_prefix>] --path <pfx_file_path> [--password <pfx_password>]
  • --ca-dir <ca_directory>: The directory where the CA files are stored (used to find the CA certificate for the chain).
  • --issuing-ca <file_prefix>: The file prefix of the issuing CA to include in the chain.
  • --path <pfx_file_path>: The path where the generated PFX file will be saved.
  • --password <pfx_password>: Optional. The custom password to protect the PFX, instead of the default changeit.

Go binary

A Go port with the same feature set lives in src/simple-ca. It compiles to a single self-contained binary (~56 MB) with no runtime dependencies, and exposes make-ca, make-cert, and make-pfx as subcommands mirroring the Bash flag names.

Build for the host platform

cd src/simple-ca
go build -o simple-ca .
./simple-ca --help

Cross-compile

Go builds statically linked binaries for any target from any host:

cd src/simple-ca

# Linux
GOOS=linux   GOARCH=amd64 go build -o simple-ca-linux-amd64 .
GOOS=linux   GOARCH=arm64 go build -o simple-ca-linux-arm64 .

# macOS
GOOS=darwin  GOARCH=amd64 go build -o simple-ca-darwin-amd64 .
GOOS=darwin  GOARCH=arm64 go build -o simple-ca-darwin-arm64 .

# Windows
GOOS=windows GOARCH=amd64 go build -o simple-ca-windows-amd64.exe .

Usage

simple-ca make-ca   [--days N] [--issuing-ca PREFIX] [--aia-base-url URL] CA_DIR CA_NAME
simple-ca make-cert [--ca-dir DIR] [--days N] [--issuing-ca PREFIX] CERT_DIR SUBJECT [SAN...]
simple-ca make-pfx  --ca-dir DIR [--issuing-ca PREFIX] --path CERT_PATH [--password PASS]

generate-mobileconfig.py

generate-mobileconfig.py generates Apple .mobileconfig profiles for distributing CA certificates and optionally client certificates and IKEv2 VPN configuration to Apple devices (macOS / iOS / iPadOS).

Modes

Arguments supplied Profile content
--ca-cert only CA trust anchor
--ca-cert + --client-cert + --client-key CA trust anchor + PKCS#12 client certificate
All of the above + --remote-address + --match-domains CA + client cert + IKEv2 VPN

Usage

generate-mobileconfig.py --ca-cert CA.pem --output profile.mobileconfig \
    --identifier com.example.vpn \
    [--client-cert CLIENT.pem --client-key CLIENT_KEY.pem] \
    [--remote-address vpn.example.com --match-domains example.com] \
    [--profile-name "My VPN"] [--ca-name "My CA"] \
    [--client-name "My Cert"] [--vpn-name "My VPN Connection"] \
    [--openssl /usr/bin/openssl]

Required arguments

  • --ca-cert PEM — CA certificate PEM file to embed as a trust anchor.
  • --output FILE — Output .mobileconfig path.
  • --identifier ID — Reverse-DNS profile identifier (e.g. com.example.vpn). Derived automatically from --remote-address when a VPN profile is generated.

Client certificate (optional)

  • --client-cert PEM — Client certificate PEM file.
  • --client-key PEM — Client private key PEM file (required together with --client-cert).

VPN (requires client certificate)

  • --remote-address FQDN — VPN gateway hostname.
  • --match-domains DOMAIN [DOMAIN …] — Split-DNS domains routed through the VPN.

Display name overrides (all optional)

  • --profile-name NAME — Profile display name (default: VPN or Certificates).
  • --ca-name NAME — CA payload display name (default: certificate CN).
  • --client-name NAME — Client cert payload display name (default: certificate CN).
  • --vpn-name NAME — VPN connection display name (default: profile name).

Other

  • --openssl PATH — Path to the openssl binary (default: /usr/bin/openssl).

Examples

CA trust profile only:

python3 generate-mobileconfig.py \
    --ca-cert ca/ca_cert.pem \
    --identifier com.example.ca \
    --output ca-trust.mobileconfig

CA + client certificate:

python3 generate-mobileconfig.py \
    --ca-cert ca/ca_cert.pem \
    --client-cert certs/alice_cert.pem \
    --client-key  certs/alice_key.pem \
    --identifier com.example.certs \
    --output alice.mobileconfig

Full IKEv2 VPN profile:

python3 generate-mobileconfig.py \
    --ca-cert ca/ca_cert.pem \
    --client-cert certs/alice_cert.pem \
    --client-key  certs/alice_key.pem \
    --remote-address vpn.example.com \
    --match-domains example.com internal.example.com \
    --output alice-vpn.mobileconfig

Self Signed Ceritifcate

The following command will create a full-featured self-signed certificate that can act as CA certificate and be used for client and server authentication:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
    -keyout "key.pem" \
    -out "cert.pem" \
    -subj "/CN=<user name>/O=<user organization>/C=<CC>" \
    -addext "basicConstraints=critical,CA:TRUE" \
    -addext "keyUsage=critical,digitalSignature,keyEncipherment,keyCertSign,cRLSign" \
    -addext "extendedKeyUsage=serverAuth,clientAuth" \
    -addext "subjectAltName=DNS:<computer_name>"
S
Description
No description provided
Readme MIT 257 KiB
Languages
Python 45.4%
Go 30.1%
Shell 24.5%