venerdì 4 dicembre 2009

Creare i certificati X.509

Bene, ora è giunto il momento di creare la nostra gerarchia di certificati, ma prima di fare questo guardiamoci un attimo attorno per capire come funzionano le cose fatte dai grandi gestori... se prendessimo come esempio le CA riconosciute ufficialmente, osserveremmo che loro richiedono solamente la richiesta di certificato, a cui applicano la firma, per poter poi restituire il certificato; questo viene fatto ai fini di sicurezza dato che voi, i proprietari della chiave privata, volete che NESSUNO sia in grado di venire a conoscenza dei dati che transitano; logicamente se generassero loro la vostra richiesta di certificato, avrebbero generato anche la chiave privata, e quindi la conoscerebbero; inoltre ve la dovrebbero trasmettere, esponendo la chiave privata a possibili sguardi inopportuni e riducendo largamente la sicurezza del sistema creato.
Nel nostro caso le cose si semplificano di molto dato che do per assunto una situazione prestabilita (che riduce altamente la sicurezza in caso di compromissione del server, ma non facendo transazioni bancarie lo ritengo un rischio accettabile): la chiave privata verrà utilizzata da servizi presenti sulla stessa macchina che gestisce la CA, quindi entrambe le chiavi possono risiedere a bordo di questa e gli unici occhi che le possono leggere sono i nostri (sempre che abbiate protetto bene il server).
Per generare la coppia di chiavi, ovvero la chiave privata e la richiesta di certificato (che contiene quella pubblica), eseguire la firma con la CA ed ottenere quindi il certificato, si può utilizzare il seguente script in /etc/*/makeCert.sh:

#!/bin/bash

# Script per la creazione della coppia chiavi pubblica/privata, per la generazione della richiesta di certificato, per la firma della richista trmaite la CA e per la generazione del certificato.
function newCert {
echo -n "Vuoi generare una chiave privata senza password? (s/N) ";
read ANS;
case ${ANS} in
"S"|"s"|"Y"|"y") echo "Attenzione, la chiave privata sara' leggibile da chiunque!";
openssl req -config ${opensslConf} -new -text -nodes -keyout ${CApath}/private/${NOME}.key -out ${CApath}/certs/${NOME}.pem.req;
;;
"N"|"n"|"") echo "Attenzione, ad ogni accesso alla chiave privata si dovra' fornire la password!";
openssl req -config ${opensslConf} -new -text -keyout ${CApath}/private/${NOME}.key -out ${CApath}/certs/${NOME}.pem.req;
echo "Per la rimozione della password usare il seguente comando: openssl rsa -in ${CApath}/private/${NOME}.key -out ${CApath}/private/${NOME}.unsecure.key";
;;
esac;
}
opensslConf=$(find /etc -iname openssl.cnf|sort|head -1);
CApath=$(grep "^[[:space:]]*dir[[:space:]]*=" ${opensslConf} | sed "s/.*=\s\+//" | awk '{print $1}');
if [ "$1" == "" ]; then
echo "La sintassi del comando e' $0 <nome_cert>";
exit -1;
fi;
NOME=$1;
if [ -s "${CApath}/newcerts/${NOME}.pem.crt" ]; then
echo "E' gia' presente il certificato ${CApath}/certs/${NOME}.pem.crt, vuoi rinnovarlo revocandolo ed emettendone uno nuovo [s/N]? ";
read ANS;
case ${ANS} in
"S"|"s"|"Y"|"y") echo "Verra' ora revocato il certificato";
openssl ca -config ${opensslConf} -revoke ${CApath}/newcerts/${NOME}.pem.crt
;;
"N"|"n"|"") echo "Si e' deciso di non revocare il certificato precedente, si potra' proseguire solamente sovrascrivendo i vecchi dati, ricordati che non puoi avere certificati con CN uguali.";
;;
esac;
unset ANS;
fi;
if [ -s "${CApath}/certs/${NOME}.pem.req" -o -s "${CApath}/private/${NOME}.key" ]; then
echo "E' gia' presente la richiesta di certificato ${CApath}/certs/${NOME}.pem.crt, vuoi sovrascriverla [s/N]? ";
read ANS;
case ${ANS} in
"S"|"s"|"Y"|"y") echo "La richiesta di certificato e le relative chiavi verranno sovrascritte.";
newCert;
;;
"N"|"n"|"") echo "Si e' deciso di non sovrascrivere la vecchia richiesta, impossibile proseguire.";
exit -1;
;;
esac;
unset ANS;
else
newCert;
fi;
OLD_UMASK=`umask`;
umask 77;
openssl ca -config ${opensslConf} -policy policy_anything -days 730 -out ${CApath}/newcerts/${NOME}.pem.crt -infiles ${CApath}/certs/${NOME}.pem.req;
chmod a+r ${CApath}/newcerts/*;
umask ${OLD_UMASK};

Dopo tutta questa sbrodolata di codice io sono esaurito, anche perchè lo scrivevo assieme al post e mentre facevo le prove; inoltre penso che se è la prima volta che vi avvicinate ad openssl abbiate le idee molto confuse... tranquilli, è normale. Negli script riportati in precedenza ci sono molti concetti sul funzionamento di openssl, su di alcuni schemi condizionali e sulle nomenclature (scelte da me con una certa logica); uno dei concetti più importanti che ci sono, riguarda il campo CN (Common Name) di un certificato: questo deve essere univoco all'interno di una CA, quindi se avete già emesso un certificato con quel CN è obbligatorio lo revochiate per poterne emettere un altro, anche se questo è già scaduto.
Con questo direi che la trattazione sembra abbastanza esaustiva o comunque sufficiente per rendervi operativi... ricordate che il CN è il campo fondamentale del vostro certificato, e deve contenere l'host, l'ip o l'indirizzo email, relativi al tipo di dati che si vuole proteggere.

Nessun commento:

Posta un commento