Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

certforge

ShellCheck

Small, dependency-light OpenSSL CLI for issuing X.509 certificates.

certforge.sh turns an OpenSSL config file into a CSR (to be signed by your own/internal CA) or, optionally, a self-signed certificate. Bring your own private key or let it generate one.

It's plain Bash + openssl — no PKI frameworks, no daemons.


Quickstart

git clone https://github.com/mairp/certforge.git
cd certforge

# Generate a private key + CSR to hand to your internal CA
./certforge.sh --config examples/server.cnf --name web01
# -> out/web01.key   (private key)
# -> out/web01.csr   (submit this to your CA)

# ...or produce a self-signed certificate instead
./certforge.sh --config examples/server.cnf --name web01 --self-signed
# -> out/web01.key / out/web01.csr / out/web01.crt

Edit examples/server.cnf (subject and subjectAltName) to match your host, then re-run. See Usage for all options and the internal-CA walkthrough.


Requirements

  • bash 4+
  • openssl 1.1+ / 3.x

Usage

The typical use is generating a CSR that an internal CA then signs. The same tool can also produce a self-signed certificate when you don't need an external signer.

certforge.sh --config <file.cnf> [--key <file.key>] [--self-signed] [options]
Option Description
-c, --config FILE Required. OpenSSL config describing the subject and extensions.
-k, --key FILE Reuse an existing private key (RSA or EC). If omitted, a new key is generated.
-o, --out DIR Output directory (default: ./out).
-n, --name NAME Base name for output files (default: derived from the config file name).
-t, --key-type T Key type to generate: rsa, ec, ed25519, or ed448 (default: rsa). Ignored with --key.
-b, --bits N RSA key size for a newly generated key (default: 2048). Only with --key-type rsa.
--curve NAME EC curve for a newly generated key (default: prime256v1). Only with --key-type ec.
-s, --self-signed Also emit a self-signed certificate instead of only a CSR.
-d, --days N Validity in days for the self-signed cert; positive integer (default: 365). Only applies with --self-signed.
--san LIST Override the config's subjectAltName. May be repeated; each value may also be comma-separated. All entries are merged, e.g. --san DNS:host.example.com --san IP:192.0.2.10.
-f, --force Overwrite existing output files.
-h, --help Show help.

Inputs and outputs

Input is an OpenSSL config file (.cnf) plus, optionally, an existing key. The tool covers three cases:

  1. .cnf only → generates a fresh private key and a CSR.
  2. .cnf + .key → generates a CSR using the key you already hold.
  3. --self-signed → additionally signs the request with that key to produce a ready-to-use certificate.

Output (in the chosen directory):

File When
<name>.key Only when a new key is generated.
<name>.csr Always.
<name>.crt Only with --self-signed.

Examples

# 1) CSR + new key — to be signed later by an internal CA
./certforge.sh --config examples/server.cnf

# 2) CSR reusing a private key you already have
./certforge.sh --config examples/server.cnf --key server.key

# 3) Self-signed certificate, valid for two years
./certforge.sh --config examples/server.cnf --self-signed --days 730

# 4) Custom key size, output directory and file name
./certforge.sh --config examples/server.cnf --bits 4096 --out ./certs --name web01

# 5) Override the SAN without editing the config (repeat --san for more entries)
./certforge.sh --config examples/server.cnf \
  --san DNS:api.example.com --san DNS:www.example.com --san IP:192.0.2.20

# 6) ECDSA key instead of RSA (default curve prime256v1 / P-256)
./certforge.sh --config examples/server.cnf --key-type ec

# 7) ECDSA on a specific curve
./certforge.sh --config examples/server.cnf --key-type ec --curve secp384r1

# 8) Edwards-curve EdDSA key (Ed25519)
./certforge.sh --config examples/server.cnf --key-type ed25519

Supported key types: RSA, EC (NIST/SECG curves via --curve), and Edwards-curve EdDSA (ed25519, ed448).

After case 1 or 2, submit the resulting <name>.csr to your CA. To inspect it:

openssl req -in out/server.csr -noout -text

Writing the config

certforge.sh passes your .cnf straight to openssl req, so anything OpenSSL understands works — including Subject Alternative Names. A ready-to-copy starting point lives in examples/server.cnf:

[ req ]
prompt             = no
default_bits       = 2048
distinguished_name = req_distinguished_name
req_extensions     = req_ext
x509_extensions    = x509_ext

[ req_distinguished_name ]
countryName            = US
stateOrProvinceName    = California
localityName           = San Francisco
organizationName       = Example Org
organizationalUnitName = Engineering
commonName             = server.example.com

[ req_ext ]
subjectAltName = @alt_names

[ x509_ext ]
subjectAltName   = @alt_names
basicConstraints = CA:FALSE
keyUsage         = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth

[ alt_names ]
DNS.1 = server.example.com
IP.1  = 192.0.2.10

For standing up your own CA, examples/self-signed-ca.cnf is a template with the right CA extensions (CA:TRUE, cert/CRL signing):

./certforge.sh --config examples/self-signed-ca.cnf --self-signed --days 3650 --name my-ca
# -> my-ca.key / my-ca.crt — a CA that can then sign other CSRs

End-to-end: signing a certforge CSR with an internal CA

The main workflow is generating a CSR with certforge.sh and having your internal CA sign it. Below is a complete, runnable example using a local OpenSSL CA to play the part of that internal CA.

1. Set up the internal CA (you already have this in a real environment):

# Internal root CA key + self-signed CA certificate
openssl genrsa -out internal-ca.key 4096
openssl req -x509 -new -nodes -key internal-ca.key -sha256 -days 3650 \
  -subj "/C=US/O=Example Org/OU=IT/CN=Example Internal Root CA" \
  -out internal-ca.crt

2. Generate the server key + CSR with certforge:

./certforge.sh --config examples/server.cnf --name web01 --out .
# -> web01.key  (private key)
# -> web01.csr  (submit this to the CA)

3. Have the internal CA sign the CSR. Provide an extensions file so the signed certificate keeps its SANs (a CA does not copy them from the CSR by default):

cat > web01-ext.cnf <<'EOF'
basicConstraints = CA:FALSE
keyUsage         = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName   = @alt_names
[ alt_names ]
DNS.1 = server.example.com
IP.1  = 192.0.2.10
EOF

openssl x509 -req -in web01.csr \
  -CA internal-ca.crt -CAkey internal-ca.key -CAcreateserial \
  -days 825 -sha256 -extfile web01-ext.cnf -out web01.crt

4. Verify the issued certificate against the CA:

openssl verify -CAfile internal-ca.crt web01.crt
# web01.crt: OK

openssl x509 -in web01.crt -noout -issuer -subject -ext subjectAltName
# issuer=C=US, O=Example Org, OU=IT, CN=Example Internal Root CA
# subject=..., CN=server.example.com
# X509v3 Subject Alternative Name:
#     DNS:server.example.com, IP Address:192.0.2.10

You now have web01.key + web01.crt signed by your internal CA. Deploy the key and certificate to the server, and distribute internal-ca.crt to clients that need to trust it.


Security notes

  • Generated private keys, CSRs and certificates are git-ignored by default — don't commit real keys.
  • Newly generated keys are written with 600 permissions.
  • Self-signed certificates are fine for labs and internal testing; for anything public-facing, get the CSR signed by a trusted CA.

License

MIT — see LICENSE if present, otherwise use freely.

About

certforge — a small OpenSSL CLI to generate CSRs (for signing by an internal CA) or self-signed certificates from a .cnf, with or without an existing key.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages