#!/bin/bash
# Script de génération de certificat auto-signé à partir d'un CSR
# Auteur : Cbillet
# Date : 10/11/2024
# Version : 1.0

# Liste des algorithmes de hachage valides
VALID_HASH_ALGS=("sha256" "sha384" "sha512")

# Affichage de l'aide
Help() {
    echo -e "\n\e[1;36mScript de génération de certificat auto-signé à partir d'un CSR\e[0m"
    echo -e "\n\e[1;32mUSAGE :\e[0m"
    echo -e "  $0 -c \e[3m<fichier_csr>\e[0m -k \e[3m<fichier_cle>\e[0m [-o \e[3m<fichier_certificat>\e[0m] [-d \e[3m<jours>\e[0m] [-H \e[3m<algorithme_hachage>\e[0m]"
    
    echo -e "\n\e[1;32mOPTIONS :\e[0m"
    echo -e "  \e[1;33m-c, --csr\e[0m \e[3m<fichier_csr>\e[0m          Fichier CSR en entrée (obligatoire)"
    echo -e "  \e[1;33m-k, --key\e[0m \e[3m<fichier_cle>\e[0m          Fichier de clé privée associé au CSR (obligatoire)"
    echo -e "  \e[1;33m-o, --output\e[0m \e[3m<output_file_name>\e[0m  Nom du fichier de certificat de sortie (par défaut : <fichier_csr>.crt)"
    echo -e "  \e[1;33m-d, --days\e[0m \e[3m<jours>\e[0m               Nombre de jours de validité du certificat (par défaut : 365)"
    echo -e "  \e[1;33m-H, --hash-alg\e[0m \e[3m<algo_hachage>\e[0m    Algorithme de hachage pour signer le certificat (par défaut : sha256)"
    echo -e "                                   Options valides : \e[1;34m${VALID_HASH_ALGS[*]}\e[0m"
    echo -e "  \e[1;33m-h, --help\e[0m                       Affiche cette aide\n"
    
    echo -e "\e[1;32mEXEMPLES :\e[0m"
    echo -e "  $0 -c server.csr -k server.key"
    echo -e "  $0 -c server.csr -k server.key -o my_cert.crt -d 730 -H sha512\n"
}


# Valeurs par défaut
CERT_DAYS=365
OUTPUT_CERT=""
HASH_ALG="sha256"

# Fonction pour demander une valeur si elle n'est pas définie
prompt_for_value() {
    local var_name="$1"
    local prompt_message="$2"
    local value=""

    while [[ -z "${!var_name}" ]]; do
        read -p "$prompt_message : " value
        if [[ -n "$value" ]]; then
            eval "$var_name='$value'"
        else
            echo "Erreur : La valeur de $var_name ne peut pas être vide."
        fi
    done
}

# Fonction pour vérifier si une valeur est dans la liste des valeurs valides
is_valid_option() {
    local value="$1"
    shift
    local valid_options=("$@")
    for option in "${valid_options[@]}"; do
        if [[ "$value" == "$option" ]]; then
            return 0
        fi
    done
    return 1
}

# Fonction pour vérifier si une valeur est un entier positif
is_integer() {
    local value="$1"
    [[ "$value" =~ ^[0-9]+$ ]]
}

# Gestion des options
while [[ "$#" -gt 0 ]]; do
    case "$1" in
        -h|--help) Help; exit 0;;
        -c|--csr) CSR_FILE="$2"; shift;;
        -k|--key) KEY_FILE="$2"; shift;;
        -o|--output) OUTPUT_CERT="$2"; shift;;
        -d|--days) CERT_DAYS="$2"; shift;;
        -H|--hash-alg) HASH_ALG="$2"; shift;;
        *) echo "Erreur : Option inconnue $1"; Help; exit 1;;
    esac
    shift
done

# Vérification que CERT_DAYS est un entier positif
if ! is_integer "$CERT_DAYS"; then
    echo "Erreur : La valeur spécifiée pour --days doit être un entier positif."
    exit 1
fi

# Demande les valeurs manquantes
prompt_for_value "CSR_FILE" "Veuillez spécifier le chemin du fichier CSR (ex: server.csr)"
prompt_for_value "KEY_FILE" "Veuillez spécifier le chemin du fichier de clé privée (ex: server.key)"

# Définit le nom de fichier de sortie par défaut si non spécifié
if [[ -z "$OUTPUT_CERT" ]]; then
    OUTPUT_CERT="${CSR_FILE%.csr}.crt"
    echo "Aucun fichier de sortie spécifié. Utilisation de $OUTPUT_CERT par défaut."
fi

# Vérifie l'existence des fichiers CSR et clé privée
if [[ ! -f "$CSR_FILE" ]]; then
    echo "Erreur : Le fichier CSR spécifié ($CSR_FILE) est introuvable."
    exit 1
fi

if [[ ! -f "$KEY_FILE" ]]; then
    echo "Erreur : Le fichier de clé privée spécifié ($KEY_FILE) est introuvable."
    exit 1
fi

# Vérifie que l'algorithme de hachage est valide
if ! is_valid_option "$HASH_ALG" "${VALID_HASH_ALGS[@]}"; then
    echo "Erreur : L'algorithme de hachage spécifié ($HASH_ALG) n'est pas valide."
    echo "Options valides : ${VALID_HASH_ALGS[*]}"
    exit 1
fi

# Génère le certificat auto-signé à partir du CSR avec l'algorithme de hachage spécifié
openssl x509 -req -in "$CSR_FILE" -signkey "$KEY_FILE" -out "$OUTPUT_CERT" -days "$CERT_DAYS" -"$HASH_ALG"

# Vérifie si le certificat a été généré avec succès
if [[ -f "$OUTPUT_CERT" ]]; then
    echo "Certificat auto-signé généré avec succès : $OUTPUT_CERT"
else
    echo "Erreur : La génération du certificat a échoué."
    exit 1
fi
