go-openssl

command module
v0.0.6 Latest Latest
Warning

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

Go to latest
Published: May 8, 2026 License: Apache-2.0 Imports: 3 Imported by: 0

README

go-openssl

go-openssl is the QuicksGo CLI used to generate .pem certificates and keys for RSA, ECC, or Ed25519.

Install

go install github.com/PointerByte/QuicksGo/cmd/go-openssl@latest

Commands

Generate a self-signed RSA certificate:

go-openssl generate --algorithm rsa --dir ./certs

Generate an ECC certificate with an optional salt:

go-openssl generate --algorithm ecc --ecc-curve p384 --dir ./certs --salt my-extra-entropy

Generate an Ed25519 certificate:

go-openssl generate --algorithm ed25519 --dir ./certs

Generate encrypted PEM files. The secret must be at least 256 bits, which means 32 bytes or more:

go-openssl generate --algorithm rsa --dir ./certs --encrypt-secret "12345678901234567890123456789012"

Read an encrypted certificate or key back as plain PEM:

go-openssl read --file ./certs/cert.pem --secret "12345678901234567890123456789012"

The generator can control:

  • the algorithm: rsa, ecc, or ed25519
  • the output directory through --dir
  • the certificate common name through --common-name
  • DNS Subject Alternative Names through repeated --dns
  • the organization value through --organization
  • validity time through --days
  • RSA key size through --rsa-bits
  • ECC curve through --ecc-curve
  • the output file names through --cert-file, --key-file, and --public-key-file
  • signing with an existing CA through --signed-by and --ca-key
  • reading an encrypted signing CA through --signed-by-secret and --ca-key-secret
  • whether the certificate is a CA through --ca
  • optional extra entropy through --salt
  • encrypting generated PEM files through --encrypt-secret

The command writes:

  • cert.pem
  • key.pem
  • public.pem

inside the selected directory by default.

When --signed-by is set, --ca-key must also be set. The generated certificate is signed by that CA, while key.pem and public.pem belong to the new certificate.

When --encrypt-secret is set, cert.pem, key.pem, and public.pem are written as QUICKSGO ENCRYPTED PEM envelopes using AES-256-GCM. Use go-openssl read, goopenssl.ReadPEMFile, goopenssl.ReadCertificateFile, goopenssl.ReadPrivateKeyFile, or goopenssl.ReadPublicKeyFile with the same secret to recover the original PEM content.

CLI to Go options

Every go-openssl generate flag maps to a field in goopenssl.Options when you call the generator from Go:

CLI flag Go field
--algorithm Algorithm
--dir OutputDir
--common-name CommonName
--dns DNSNames
--organization Organization
--days ValidForDays
--rsa-bits RSAKeySize
--ecc-curve ECCCurve
--salt Salt
--cert-file CertFileName
--key-file KeyFileName
--public-key-file PublicKeyFileName
--signed-by SignedBy
--ca-key CAKeyFile
--ca IsCA
--encrypt-secret EncryptSecret
--signed-by-secret SignedBySecret
--ca-key-secret CAKeySecret

go-openssl read is a read/decrypt helper and maps to the exported reader functions:

CLI flag Go equivalent
--file first argument to ReadPEMFile, ReadCertificateFile, ReadPrivateKeyFile, or ReadPublicKeyFile
--secret second argument to the reader function
--out write the returned bytes to the destination file

The Go examples below assume this import:

import goopenssl "github.com/PointerByte/QuicksGo/cmd/go-openssl/code"

Examples by Use Case

Each CLI example has an equivalent Go snippet using GenerateCertificates.

Create a CA certificate separately

Use --ca only for a certificate authority. Naming the certificate CA.pem makes sense for this case because it is used as a trust anchor, not as an individual service certificate.

go-openssl generate \
  --algorithm rsa \
  --rsa-bits 4096 \
  --ca \
  --dir ./certs/internal-ca \
  --common-name internal-ca.example.local \
  --dns internal-ca.example.local \
  --organization "Example Internal CA" \
  --days 3650 \
  --cert-file CA.pem \
  --key-file CA-key.pem \
  --public-key-file CA-public.pem

Equivalent Go code:

_, err := goopenssl.GenerateCertificates(goopenssl.Options{
	Algorithm:         "rsa",
	RSAKeySize:        4096,
	IsCA:              true,
	OutputDir:         "./certs/internal-ca",
	CommonName:        "internal-ca.example.local",
	DNSNames:          []string{"internal-ca.example.local"},
	Organization:      "Example Internal CA",
	ValidForDays:      3650,
	CertFileName:      "CA.pem",
	KeyFileName:       "CA-key.pem",
	PublicKeyFileName: "CA-public.pem",
})
Create server and client certificates signed by a CA

For mTLS, generate the CA first, then generate the server and client certificates with --signed-by and --ca-key. Keep the CA key in its own file so later commands do not overwrite it.

go-openssl generate \
  --algorithm ecc \
  --ecc-curve p521 \
  --ca \
  --dir ./certs/server \
  --common-name internal-ca.example.local \
  --organization "Example Platform" \
  --days 365 \
  --cert-file ca.pem \
  --key-file ca-key.pem \
  --public-key-file ca-public.pem

go-openssl generate \
  --algorithm ecc \
  --ecc-curve p521 \
  --dir ./certs/server \
  --common-name my-api.default.svc.cluster.local \
  --dns my-api.default.svc.cluster.local \
  --organization "Example Platform" \
  --days 365 \
  --cert-file cert.pem \
  --key-file key.pem \
  --public-key-file public.pem \
  --signed-by ./certs/server/ca.pem \
  --ca-key ./certs/server/ca-key.pem

go-openssl generate \
  --algorithm ecc \
  --ecc-curve p521 \
  --dir ./certs/client \
  --common-name my-api-client.default.svc.cluster.local \
  --dns my-api-client.default.svc.cluster.local \
  --organization "Example Platform" \
  --days 365 \
  --cert-file cert.pem \
  --key-file key.pem \
  --public-key-file public.pem \
  --signed-by ./certs/server/ca.pem \
  --ca-key ./certs/server/ca-key.pem

Equivalent Go code:

caResult, err := goopenssl.GenerateCertificates(goopenssl.Options{
	Algorithm:         "ecc",
	ECCCurve:          "p521",
	IsCA:              true,
	OutputDir:         "./certs/server",
	CommonName:        "internal-ca.example.local",
	Organization:      "Example Platform",
	ValidForDays:      365,
	CertFileName:      "ca.pem",
	KeyFileName:       "ca-key.pem",
	PublicKeyFileName: "ca-public.pem",
})
if err != nil {
	return err
}

_, err = goopenssl.GenerateCertificates(goopenssl.Options{
	Algorithm:         "ecc",
	ECCCurve:          "p521",
	OutputDir:         "./certs/server",
	CommonName:        "my-api.default.svc.cluster.local",
	DNSNames:          []string{"my-api.default.svc.cluster.local"},
	Organization:      "Example Platform",
	ValidForDays:      365,
	CertFileName:      "cert.pem",
	KeyFileName:       "key.pem",
	PublicKeyFileName: "public.pem",
	SignedBy:          caResult.CertificatePath,
	CAKeyFile:         caResult.PrivateKeyPath,
})
if err != nil {
	return err
}

_, err = goopenssl.GenerateCertificates(goopenssl.Options{
	Algorithm:         "ecc",
	ECCCurve:          "p521",
	OutputDir:         "./certs/client",
	CommonName:        "my-api-client.default.svc.cluster.local",
	DNSNames:          []string{"my-api-client.default.svc.cluster.local"},
	Organization:      "Example Platform",
	ValidForDays:      365,
	CertFileName:      "cert.pem",
	KeyFileName:       "key.pem",
	PublicKeyFileName: "public.pem",
	SignedBy:          caResult.CertificatePath,
	CAKeyFile:         caResult.PrivateKeyPath,
})
Create and read encrypted certificate files

Use --encrypt-secret to encrypt all generated PEM outputs. The same secret is required to read them later. The secret must be at least 32 bytes.

go-openssl generate \
  --algorithm rsa \
  --rsa-bits 4096 \
  --dir ./certs/encrypted \
  --common-name my-api.default.svc.cluster.local \
  --dns my-api.default.svc.cluster.local \
  --organization "Example Platform" \
  --days 365 \
  --encrypt-secret "12345678901234567890123456789012"

Read the encrypted certificate to stdout:

go-openssl read \
  --file ./certs/encrypted/cert.pem \
  --secret "12345678901234567890123456789012"

Write the decrypted PEM to another file:

go-openssl read \
  --file ./certs/encrypted/key.pem \
  --secret "12345678901234567890123456789012" \
  --out ./certs/encrypted/key.decrypted.pem

Equivalent Go code:

result, err := goopenssl.GenerateCertificates(goopenssl.Options{
	Algorithm:     "rsa",
	RSAKeySize:    4096,
	OutputDir:     "./certs/encrypted",
	CommonName:    "my-api.default.svc.cluster.local",
	DNSNames:      []string{"my-api.default.svc.cluster.local"},
	Organization:  "Example Platform",
	ValidForDays:  365,
	EncryptSecret: "12345678901234567890123456789012",
})
if err != nil {
	return err
}

certPEM, err := goopenssl.ReadPEMFile(result.CertificatePath, "12345678901234567890123456789012")
if err != nil {
	return err
}
_ = certPEM

certificate, err := goopenssl.ReadCertificateFile(result.CertificatePath, "12345678901234567890123456789012")
if err != nil {
	return err
}
_ = certificate

If a CA was generated encrypted, pass the read secrets when using it to sign a new certificate.

CLI:

go-openssl generate \
  --algorithm ecc \
  --ecc-curve p384 \
  --dir ./certs/service \
  --common-name service.default.svc.cluster.local \
  --dns service.default.svc.cluster.local \
  --signed-by ./certs/ca/ca.pem \
  --ca-key ./certs/ca/ca-key.pem \
  --signed-by-secret "12345678901234567890123456789012" \
  --ca-key-secret "12345678901234567890123456789012"

Equivalent Go code:

_, err = goopenssl.GenerateCertificates(goopenssl.Options{
	Algorithm:      "ecc",
	ECCCurve:       "p384",
	OutputDir:      "./certs/service",
	CommonName:     "service.default.svc.cluster.local",
	DNSNames:       []string{"service.default.svc.cluster.local"},
	SignedBy:       "./certs/ca/ca.pem",
	CAKeyFile:      "./certs/ca/ca-key.pem",
	SignedBySecret: "12345678901234567890123456789012",
	CAKeySecret:    "12345678901234567890123456789012",
})
Kubernetes service behind an Ingress

Use this when the public domain is terminated by an Ingress TLS certificate, but the application container also needs its own certificate for backend TLS, mTLS, sidecars, service meshes, or direct pod-to-service connections.

The Ingress certificate for api.example.com and the service certificate below are different pieces of material. The service certificate should include the Kubernetes service DNS names and can also include the public domain when the service validates that hostname directly.

RSA certificate with a 4096-bit key:

go-openssl generate \
  --algorithm rsa \
  --rsa-bits 4096 \
  --dir ./certs/my-api-public-rsa \
  --common-name my-api.default.svc \
  --dns my-api.default.svc \
  --dns my-api.default.svc.cluster.local \
  --dns api.example.com \
  --organization "Example Platform" \
  --days 365

Equivalent Go code:

_, err := goopenssl.GenerateCertificates(goopenssl.Options{
	Algorithm:    "rsa",
	RSAKeySize:   4096,
	OutputDir:    "./certs/my-api-public-rsa",
	CommonName:   "my-api.default.svc",
	DNSNames:     []string{"my-api.default.svc", "my-api.default.svc.cluster.local", "api.example.com"},
	Organization: "Example Platform",
	ValidForDays: 365,
})

ECC/ECDSA certificate with a P-256 key:

go-openssl generate \
  --algorithm ecc \
  --ecc-curve p256 \
  --dir ./certs/my-api-public-ecc \
  --common-name my-api.default.svc \
  --dns my-api.default.svc \
  --dns my-api.default.svc.cluster.local \
  --dns api.example.com \
  --organization "Example Platform" \
  --days 365

Equivalent Go code:

_, err := goopenssl.GenerateCertificates(goopenssl.Options{
	Algorithm:    "ecc",
	ECCCurve:     "p256",
	OutputDir:    "./certs/my-api-public-ecc",
	CommonName:   "my-api.default.svc",
	DNSNames:     []string{"my-api.default.svc", "my-api.default.svc.cluster.local", "api.example.com"},
	Organization: "Example Platform",
	ValidForDays: 365,
})

Use --ecc-curve p384 or ECCCurve: "p384" if your environment requires a larger curve.

Internal service-to-service communication

Use this when one Kubernetes workload talks to another directly, for example orders calling payments inside the cluster. Prefer internal Kubernetes DNS names in the SAN list.

RSA is the compatibility-first option:

go-openssl generate \
  --algorithm rsa \
  --rsa-bits 2048 \
  --dir ./certs/orders-to-payments-rsa \
  --common-name payments.default.svc \
  --dns payments.default.svc \
  --dns payments.default.svc.cluster.local \
  --organization "Example Internal Services" \
  --days 365

Equivalent Go code:

_, err := goopenssl.GenerateCertificates(goopenssl.Options{
	Algorithm:    "rsa",
	RSAKeySize:   2048,
	OutputDir:    "./certs/orders-to-payments-rsa",
	CommonName:   "payments.default.svc",
	DNSNames:     []string{"payments.default.svc", "payments.default.svc.cluster.local"},
	Organization: "Example Internal Services",
	ValidForDays: 365,
})

ECC/ECDSA keeps keys smaller and is a good fit when all clients support it:

go-openssl generate \
  --algorithm ecc \
  --ecc-curve p256 \
  --dir ./certs/orders-to-payments-ecc \
  --common-name payments.default.svc \
  --dns payments.default.svc \
  --dns payments.default.svc.cluster.local \
  --organization "Example Internal Services" \
  --days 365

Equivalent Go code:

_, err := goopenssl.GenerateCertificates(goopenssl.Options{
	Algorithm:    "ecc",
	ECCCurve:     "p256",
	OutputDir:    "./certs/orders-to-payments-ecc",
	CommonName:   "payments.default.svc",
	DNSNames:     []string{"payments.default.svc", "payments.default.svc.cluster.local"},
	Organization: "Example Internal Services",
	ValidForDays: 365,
})
Ed25519 keys for JWT signatures

Use Ed25519 when your JWT layer signs tokens with EdDSA. The command still writes cert.pem, key.pem, and public.pem; for JWT signing, the private and public key files are usually the values you need.

go-openssl generate \
  --algorithm ed25519 \
  --dir ./certs/jwt \
  --common-name jwt-signing.default.svc \
  --dns jwt-signing.default.svc \
  --organization "Example Security" \
  --days 365 \
  --key-file key.pem \
  --public-key-file public.pem

Equivalent Go code:

_, err := goopenssl.GenerateCertificates(goopenssl.Options{
	Algorithm:         "ed25519",
	OutputDir:         "./certs/jwt",
	CommonName:        "jwt-signing.default.svc",
	DNSNames:          []string{"jwt-signing.default.svc"},
	Organization:      "Example Security",
	ValidForDays:      365,
	KeyFileName:       "key.pem",
	PublicKeyFileName: "public.pem",
})

If your configuration expects Base64 DER values, convert the PEM files with openssl pkey:

openssl pkey -in ./certs/jwt/key.pem \
  -outform DER \
  | base64 -w 0

openssl pkey -pubin -in ./certs/jwt/public.pem \
  -outform DER \
  | base64 -w 0

Those values can be stored in configuration keys such as jwt.eddsa.private_key and jwt.eddsa.public_key.

Go Usage

The dependency can also be called directly from Go code:

package main

import (
	"log"

	goopenssl "github.com/PointerByte/QuicksGo/cmd/go-openssl/code"
)

func main() {
	_, err := goopenssl.GenerateCertificates(goopenssl.Options{
		Algorithm:  "ecc",
		ECCCurve:   "p256",
		OutputDir:  "./certs",
		CommonName: "localhost",
		Salt:       "my-extra-entropy",
	})
	if err != nil {
		log.Fatal(err)
	}
}

Documentation

Overview

Package main exposes the go-openssl CLI entrypoint.

Directories

Path Synopsis
Package code contains the go-openssl certificate generation logic used by the CLI and by other Go code that needs to create plain or encrypted PEM assets programmatically.
Package code contains the go-openssl certificate generation logic used by the CLI and by other Go code that needs to create plain or encrypted PEM assets programmatically.

Jump to

Keyboard shortcuts

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