Created
September 26, 2025 19:27
-
-
Save qrkourier/872b3d29113e8f51cddda4a89728c80f to your computer and use it in GitHub Desktop.
generate ca, client, and server certs for testing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# Generates a self-signed user/client certificate for authentication purposes. | |
# It creates a private key, a public key, the certificate, and a PKCS#12 | |
# bundle for easy import into browsers or for use with tools like curl. | |
set -e | |
# --- Configuration --- | |
# Modern, preferred elliptic curve for the private key. | |
# secp384r1 offers an excellent balance of security and performance. | |
CURVE_NAME="secp384r1" | |
# Validity of the certificate in days. 10 years is common for client certs. | |
VALIDITY_DAYS=3650 | |
# --- User Input --- | |
echo "--- Client Certificate Generator ---" | |
read -p "Enter the user's email address (e.g., [email protected]): " EMAIL | |
read -p "Enter a base filename for the output files (e.g., 'john_doe_auth') [default: cert]: " FILENAME | |
FILENAME=${FILENAME:-cert} | |
# Prompt for the PKCS#12 export password securely | |
echo "You will now create a password for the PKCS#12 file (.p12)." | |
echo "This password is required when importing the file into a browser or keychain." | |
read -s -p "Enter Export Password: " P12_PASSWORD | |
echo | |
read -s -p "Verify Export Password: " P12_PASSWORD_VERIFY | |
echo | |
if [ "$P12_PASSWORD" != "$P12_PASSWORD_VERIFY" ]; then | |
echo "Error: Passwords do not match." | |
exit 1 | |
fi | |
echo | |
echo "--- Starting Generation ---" | |
# --- Step 1: Generate the Certificate Authority (CA) --- | |
echo "1. Generating CA private key (${FILENAME}_ca.key)..." | |
openssl ecparam -name "$CURVE_NAME" -genkey -out "${FILENAME}_ca.key" | |
echo " CA private key generated." | |
echo "2. Creating CA certificate (${FILENAME}_ca.crt)..." | |
read -p "Enter the CA organization name (e.g., 'My Test CA') [default: Test CA]: " CA_ORG | |
CA_ORG=${CA_ORG:-Test CA} | |
openssl req \ | |
-new \ | |
-x509 \ | |
-key "${FILENAME}_ca.key" \ | |
-out "${FILENAME}_ca.crt" \ | |
-days "$VALIDITY_DAYS" \ | |
-subj "/CN=${CA_ORG}/O=${CA_ORG}" \ | |
--addext "keyUsage = critical, keyCertSign, cRLSign" \ | |
--addext "basicConstraints = critical, CA:true" \ | |
--addext "subjectKeyIdentifier = hash" | |
echo " CA certificate created." | |
# --- Step 3: Generate Client Private Key --- | |
echo "3. Generating client private key (${FILENAME}.key)..." | |
openssl ecparam -name "$CURVE_NAME" -genkey -out "${FILENAME}.key" | |
echo " Client private key generated." | |
# --- Step 4: Generate Client Certificate Signing Request --- | |
echo "4. Creating client certificate signing request..." | |
openssl req \ | |
-new \ | |
-key "${FILENAME}.key" \ | |
-out "${FILENAME}.csr" \ | |
-subj "/CN=${EMAIL}" | |
# --- Step 5: Sign Client Certificate with CA --- | |
echo "5. Signing client certificate with CA (${FILENAME}.crt)..." | |
openssl x509 \ | |
-req \ | |
-in "${FILENAME}.csr" \ | |
-CA "${FILENAME}_ca.crt" \ | |
-CAkey "${FILENAME}_ca.key" \ | |
-CAcreateserial \ | |
-out "${FILENAME}.crt" \ | |
-days "$VALIDITY_DAYS" \ | |
-extensions client_ext \ | |
-extfile <(echo "[client_ext] | |
keyUsage = digitalSignature | |
extendedKeyUsage = clientAuth | |
subjectKeyIdentifier = hash | |
authorityKeyIdentifier = keyid,issuer") | |
echo " Client certificate signed." | |
# --- Step 6: Extract the Client Public Key --- | |
echo "6. Extracting client public key (${FILENAME}.pub)..." | |
openssl ec -in "${FILENAME}.key" -pubout -out "${FILENAME}.pub" | |
echo " Client public key extracted." | |
# --- Step 7: Create the Client PKCS#12 Keystore --- | |
echo "7. Creating client PKCS#12 keystore (${FILENAME}.p12)..." | |
# This bundles the private key and the certificate into a single, password-protected file. | |
# The -name attribute is a "friendly name" that appears in the browser's UI. | |
openssl pkcs12 \ | |
-export \ | |
-in "${FILENAME}.crt" \ | |
-inkey "${FILENAME}.key" \ | |
-out "${FILENAME}.p12" \ | |
-name "${EMAIL}'s Authentication Key" \ | |
-passout pass:"${P12_PASSWORD}" | |
echo " Keystore created." | |
echo | |
echo "--- Success! ---" | |
echo "Generated files in the current directory:" | |
ls -l "${FILENAME}".* | |
echo | |
echo "--- Next Steps ---" | |
echo "-> Import '${FILENAME}.p12' into your web browser or system keychain. You will be prompted for the password you created." | |
echo "-> For command-line use with curl:" | |
echo " curl --cert ${FILENAME}.crt --key ${FILENAME}.key https://your-secure-service.com" | |
echo " OR" | |
echo " curl --cert-type P12 --cert ${FILENAME}.p12:YourPassword https://your-secure-service.com" | |
echo | |
echo "IMPORTANT: Guard the private key file ('${FILENAME}.key') and the PKCS#12 file ('${FILENAME}.p12') carefully. Anyone with access to them can impersonate you." | |
echo | |
echo "--- Generating Server Certificate ---" | |
# --- Step 8: Generate Server Private Key --- | |
echo "8. Generating server private key (${FILENAME}_server.key)..." | |
openssl ecparam -name "$CURVE_NAME" -genkey -out "${FILENAME}_server.key" | |
echo " Server private key generated." | |
# --- Step 9: Generate Server Certificate Signing Request --- | |
echo "9. Creating server certificate signing request..." | |
read -p "Enter the server hostname/FQDN (e.g., server.example.com): " SERVER_HOSTNAME | |
SERVER_HOSTNAME=${SERVER_HOSTNAME:-localhost} | |
openssl req \ | |
-new \ | |
-key "${FILENAME}_server.key" \ | |
-out "${FILENAME}_server.csr" \ | |
-subj "/CN=${SERVER_HOSTNAME}" | |
# --- Step 10: Sign Server Certificate with CA --- | |
echo "10. Signing server certificate with CA (${FILENAME}_server.crt)..." | |
openssl x509 \ | |
-req \ | |
-in "${FILENAME}_server.csr" \ | |
-CA "${FILENAME}_ca.crt" \ | |
-CAkey "${FILENAME}_ca.key" \ | |
-CAcreateserial \ | |
-out "${FILENAME}_server.crt" \ | |
-days "$VALIDITY_DAYS" \ | |
-extensions server_ext \ | |
-extfile <(echo "[server_ext] | |
keyUsage = keyEncipherment, dataEncipherment, digitalSignature | |
extendedKeyUsage = serverAuth | |
subjectAltName = DNS:${SERVER_HOSTNAME},DNS:localhost,IP:127.0.0.1 | |
subjectKeyIdentifier = hash | |
authorityKeyIdentifier = keyid,issuer") | |
echo " Server certificate signed." | |
# --- Step 11: Extract Server Public Key --- | |
echo "11. Extracting server public key (${FILENAME}_server.pub)..." | |
openssl ec -in "${FILENAME}_server.key" -pubout -out "${FILENAME}_server.pub" | |
echo " Server public key extracted." | |
# --- Step 12: Create Server PKCS#12 Keystore --- | |
echo "12. Creating server PKCS#12 keystore (${FILENAME}_server.p12)..." | |
openssl pkcs12 \ | |
-export \ | |
-in "${FILENAME}_server.crt" \ | |
-inkey "${FILENAME}_server.key" \ | |
-out "${FILENAME}_server.p12" \ | |
-name "${SERVER_HOSTNAME} Server Key" \ | |
-passout pass:"${P12_PASSWORD}" | |
echo " Server keystore created." | |
# Clean up temporary files | |
rm -f "${FILENAME}.csr" "${FILENAME}_server.csr" | |
echo | |
echo "--- Complete Success! ---" | |
echo "Generated CERTIFICATE AUTHORITY files:" | |
ls -l "${FILENAME}"_ca.* | |
echo | |
echo "Generated CLIENT certificate files:" | |
ls -l "${FILENAME}".key "${FILENAME}".crt "${FILENAME}".pub "${FILENAME}".p12 | |
echo | |
echo "Generated SERVER certificate files:" | |
ls -l "${FILENAME}"_server.* | |
echo | |
echo "--- Usage Instructions ---" | |
echo "CERTIFICATE AUTHORITY:" | |
echo "-> Install '${FILENAME}_ca.crt' as a trusted root CA in browsers/systems to trust your certificates" | |
echo "-> Keep '${FILENAME}_ca.key' extremely secure - it can sign new certificates" | |
echo | |
echo "CLIENT CERTIFICATE:" | |
echo "-> Import '${FILENAME}.p12' into your web browser or system keychain for client authentication." | |
echo "-> For command-line client use with curl:" | |
echo " curl --cert ${FILENAME}.crt --key ${FILENAME}.key --cacert ${FILENAME}_ca.crt https://your-secure-service.com" | |
echo | |
echo "SERVER CERTIFICATE:" | |
echo "-> Use '${FILENAME}_server.crt' and '${FILENAME}_server.key' to configure your web server (Apache, Nginx, etc.)" | |
echo "-> For testing with openssl s_server:" | |
echo " openssl s_server -cert ${FILENAME}_server.crt -key ${FILENAME}_server.key -CAfile ${FILENAME}_ca.crt -port 8443" | |
echo | |
echo "IMPORTANT: Guard ALL private key files carefully, especially the CA key. Anyone with access to them can impersonate you, your server, or create new certificates." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment