Skip to content

Instantly share code, notes, and snippets.

@bdparrish
Last active August 5, 2024 17:49
Show Gist options
  • Save bdparrish/9d1efe0c87f8dafb85f8d01996eef069 to your computer and use it in GitHub Desktop.
Save bdparrish/9d1efe0c87f8dafb85f8d01996eef069 to your computer and use it in GitHub Desktop.
CLI for generating self signed certificates - server and client
#!/bin/bash
# Define color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# Function to create CA Certificate
create_ca_certificate() {
printf "${GREEN}Creating CA Certificate...${NC}\n"
# Generate a private key for the CA
openssl genpkey -algorithm RSA -out ca.key -pkeyopt rsa_keygen_bits:2048
if [ $? -ne 0 ]; then
printf "${RED}Failed to generate CA private key.${NC}\n"
return 1
fi
# Generate a self-signed CA certificate
openssl req -new -x509 -key ca.key -out ca.crt -days 365 -subj "/C=US/ST=District of Columbia/L=Washington/O=Virtru/OU=Federal/CN=Virtru Federal"
if [ $? -ne 0 ]; then
printf "${RED}Failed to generate CA certificate.${NC}\n"
return 1
fi
# Create a truststore and add the CA certificate to it
keytool -importcert -file ca.crt -alias ca -keystore truststore.jks -storepass changeit -noprompt
if [ $? -ne 0 ]; then
printf "${RED}Failed to create truststore or import CA certificate.${NC}\n"
return 1
fi
printf "${GREEN}CA Certificate and truststore created successfully.${NC}\n"
}
# Function to create Server Certificate
create_server_certificate() {
printf "${GREEN}Creating Server Certificate...${NC}\n"
# Check if server.crt already exists
if [ -f "server.crt" ]; then
read -p "server.crt already exists. Do you want to recreate it? (y/n): " choice
if [ "$choice" != "y" ]; then
printf "${YELLOW}Server certificate creation aborted.${NC}\n"
return
fi
fi
# Prompt for the Common Name (CN) value
read -p "Enter the Common Name (CN) for the server certificate: " server_cn
# Generate a private key for the server
openssl genpkey -algorithm RSA -out server.key -pkeyopt rsa_keygen_bits:2048
if [ $? -ne 0 ]; then
printf "${RED}Failed to generate server private key.${NC}\n"
return 1
fi
# Generate a certificate signing request (CSR) for the server
openssl req -new -key server.key -out server.csr -subj "/C=US/ST=District of Columbia/L=Washington/O=Virtru/OU=Federal/CN=${server_cn}"
if [ $? -ne 0 ]; then
printf "${RED}Failed to generate server CSR.${NC}\n"
return 1
fi
# Create the server.ext file with the DNS alt name
cat > server.ext << EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = ${server_cn}
EOF
# Sign the server CSR with the CA certificate to create the server certificate
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 -extfile server.ext
if [ $? -ne 0 ]; then
printf "${RED}Failed to generate server certificate.${NC}\n"
return 1
fi
# Output PEM files for the server certificate and key
openssl x509 -in server.crt -out server-crt.pem -outform PEM
openssl rsa -in server.key -out server-key.pem
printf "${GREEN}Server certificate and PEM files created successfully.${NC}\n"
}
# Function to create Client Certificate
create_client_certificate() {
printf "${GREEN}Creating Client Certificate...${NC}\n"
# Prompt for the Common Name (CN) value
read -p "Enter the Common Name (CN) for the client certificate: " client_cn
# Prompt for the subject's email address
read -p "Enter the email address for the client certificate: " client_email
# Generate a sanitized filename from the CN value
client_filename=$(echo "${client_cn}" | tr '[:upper:]' '[:lower:]' | tr ' ' '_')
# Check if the client certificate file already exists
if [ -f "${client_filename}.crt" ]; then
read -p "${client_filename}.crt already exists. Do you want to replace it? (y/n): " choice
if [ "$choice" != "y" ]; then
printf "${YELLOW}Client certificate creation aborted.${NC}\n"
return
fi
fi
# Generate a private key for the client
openssl genpkey -algorithm RSA -out "${client_filename}.key" -pkeyopt rsa_keygen_bits:2048
if [ $? -ne 0 ]; then
printf "${RED}Failed to generate client private key.${NC}\n"
return 1
fi
# Generate a certificate signing request (CSR) for the client
openssl req -new -key "${client_filename}.key" -out "${client_filename}.csr" -subj "/C=US/ST=State/L=City/O=Organization/OU=Org Unit/CN=${client_cn}/emailAddress=${client_email}"
if [ $? -ne 0 ]; then
printf "${RED}Failed to generate client CSR.${NC}\n"
return 1
fi
# Sign the client CSR with the CA certificate to create the client certificate
openssl x509 -req -in "${client_filename}.csr" -CA ca.crt -CAkey ca.key -CAcreateserial -out "${client_filename}.crt" -days 365
if [ $? -ne 0 ]; then
printf "${RED}Failed to generate client certificate.${NC}\n"
return 1
fi
# Generate a PKCS#12 (P12) file containing the client certificate and key
openssl pkcs12 -export -out "${client_filename}.p12" -inkey "${client_filename}.key" -in "${client_filename}.crt" -passout pass:changeit
if [ $? -ne 0 ]; then
printf "${RED}Failed to generate client P12 file.${NC}\n"
return 1
fi
printf "${GREEN}Client certificate and P12 file created successfully.${NC}\n"
}
# Function to change the password for the truststore
change_truststore_password() {
printf "${GREEN}Changing truststore password...${NC}\n"
# Prompt for the current and new passwords
read -sp "Enter the current truststore password (default - changeit): " current_password
printf "\n"
read -sp "Enter the new truststore password: " new_password
printf "\n"
read -sp "Confirm the new truststore password: " confirm_password
printf "\n"
# Check if the new passwords match
if [ "$new_password" != "$confirm_password" ]; then
printf "${RED}New passwords do not match. Password change aborted.${NC}\n"
return
fi
# Change the password for the truststore
keytool -storepasswd -keystore truststore.jks -storepass "$current_password" -new "$new_password"
if [ $? -ne 0 ]; then
printf "${RED}Failed to change truststore password.${NC}\n"
return 1
fi
printf "${GREEN}Truststore password changed successfully.${NC}\n"
}
# Function to change the password for a P12 file
change_p12_password() {
printf "${GREEN}Changing P12 password...${NC}\n"
# List all P12 files in the current directory
p12_files=(*.p12)
if [ ${#p12_files[@]} -eq 0 ]; then
printf "${RED}No P12 files found in the current directory.${NC}\n"
return 1
fi
printf "${YELLOW}Select a P12 file to change the password:${NC}\n"
select p12_file in "${p12_files[@]}"; do
if [ -n "$p12_file" ]; then
break
else
printf "${RED}Invalid selection. Please try again.${NC}\n"
fi
done
# Prompt for the current and new passwords
read -sp "Enter the current P12 password (default - changeit): " current_password
printf "\n"
read -sp "Enter the new P12 password: " new_password
printf "\n"
read -sp "Confirm the new P12 password: " confirm_password
printf "\n"
# Check if the new passwords match
if [ "$new_password" != "$confirm_password" ]; then
printf "${RED}New passwords do not match. Password change aborted.${NC}\n"
return
fi
# Change the password for the P12 file
openssl pkcs12 -in "$p12_file" -out temp.pem -passin pass:"$current_password" -passout pass:"$new_password"
if [ $? -ne 0 ]; then
printf "${RED}Failed to extract P12 content.${NC}\n"
rm -f temp.pem
return 1
fi
openssl pkcs12 -export -in temp.pem -out "$p12_file" -passin pass:"$new_password" -passout pass:"$new_password"
if [ $? -ne 0 ]; then
printf "${RED}Failed to re-export P12 file.${NC}\n"
rm -f temp.pem
return 1
fi
rm -f temp.pem
printf "${GREEN}P12 password changed successfully.${NC}\n"
}
verify_certificates() {
printf "${BLUE}Verifying certificates in the current folder...${NC}\n"
local ca_cert="ca.crt"
if [ ! -f "$ca_cert" ]; then
printf "${RED}CA certificate '$ca_cert' not found. Please ensure 'ca.crt' is in the current directory.${NC}\n"
return
fi
for cert_file in *.crt; do
if [ -f "$cert_file" ]; then
if [ "$cert_file" == "server.crt" ]; then
printf "${YELLOW}Verifying $cert_file as server certificate...${NC}\n"
openssl verify -CAfile "$ca_cert" -purpose sslserver "$cert_file"
else
printf "${YELLOW}Verifying $cert_file as client certificate...${NC}\n"
openssl verify -CAfile "$ca_cert" -purpose sslclient "$cert_file"
fi
else
printf "${RED}No certificate files found in the current directory.${NC}\n"
fi
done
}
check_file_exists() {
local filename=$1
if [ -f "$filename" ]; then
echo true
else
echo false
fi
}
# Function to display the menu
show_menu() {
printf "${BLUE}Select an option:${NC}\n"
printf "${YELLOW}1. Create CA Certificate${NC}\n"
printf "${YELLOW}2. Create Server Certificate${NC}\n"
printf "${YELLOW}3. Create Client Certificate${NC}\n"
printf "${YELLOW}4. Change Truststore Password${NC}\n"
printf "${YELLOW}5. Change P12 Password${NC}\n"
printf "${YELLOW}6. Verify Certificates${NC}\n"
printf "${YELLOW}7. Exit${NC}\n"
}
# Main script logic
while true; do
show_menu
read -p "Enter your choice [1-7]: " choice
case $choice in
1)
create_ca_certificate
;;
2)
create_server_certificate
;;
3)
create_client_certificate
;;
4)
change_truststore_password
;;
5)
change_p12_password
;;
6)
verify_certificates
;;
7)
printf "${RED}Exiting...${NC}\n"
exit 0
;;
*)
printf "${RED}Invalid option. Please try again.${NC}\n"
;;
esac
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment