# Mini Projet - Installation d'une PKI + Implémentation avec un serveur FTP
GIBON Gabriel - JANVIER Luc
## Installation d’une PKI
### Créer une autorité racine (CA ROOT)
```
mkdir -p /root/ca/root_ca
cd /root/ca/root_ca
mkdir certs crl newcerts private
chmod 700 private
touch index.txt
echo 1000 > serial
```
Créer un fichier openssl.cnf :
```
[ ca ]
default_ca = CA_default
[ CA_default ]
# Repertoires
dir = /root/ca/root_ca
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
RANDFILE = $dir/private/.rand
private_key = $dir/private/ca.key.pem
certificate = $dir/certs/ca.cert.pem
crlnumber = $dir/crlnumber
crl = $dir/crl/ca.crl.pem
crl_extensions = crl_ext
default_crl_days = 30
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 375
preserve = no
policy = policy_strict
[ policy_strict ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_loose ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
string_mask = utf8only
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
# Extension to add when the -x509 option is used.
x509_extensions = v3_ca
[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address
# Optionally, specify some defaults.
countryName_default = FR
stateOrProvinceName_default = Bretagne
localityName_default = Rennes
0.organizationName_default = Luc et Gabriel
organizationalUnitName_default = SSI
emailAddress_default = mail@defoufurieux.fr
[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier=keyid:always
[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning
```
pass phrase : coucoulesamis
On va utiliser la clé privée qu'on vient de créer (ca.key.pem) pour créer le certificat de Root CA (ca.cert.pem).
```
openssl req -config openssl.cnf -key private/ca.key.pem -new -x509 -days 7300 -sha256 -extensions v3_ca -out certs/ca.cert.pem
Enter pass phrase for private/ca.key.pem: **********
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [FR]:
State or Province Name [Bretagne]:
Locality Name [Rennes]:
Organization Name [Luc et Gabriel]:
Organizational Unit Name [SSI]:
Common Name []:Luc Gabriel Root CA
Email Address [mail@defoufurieux.fr]:
```
Nous avons donc notre autorité de certification et son certificat on peut regarder ce qu'il y a dedans grâce a la commande
```
openssl x509 -noout -text -in certs/ca.cert.pem
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
6a:78:d1:78:61:23:b7:0c:76:78:66:5c:05:9a:bd:17:9e:57:cc:db
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = FR, ST = Bretagne, L = Rennes, O = Luc et Gabriel, OU = SSI, CN = Luc et \08\08\08Gabriel Root CA, emailAddress = mail@defoufurieux.fr
Validity
Not Before: Mar 16 10:17:23 2023 GMT
Not After : Mar 11 10:17:23 2043 GMT
Subject: C = FR, ST = Bretagne, L = Rennes, O = Luc et Gabriel, OU = SSI, CN = Luc et \08\08\08Gabriel Root CA, emailAddress = mail@defoufurieux.fr
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (4096 bit)
```
### Créer une autorité de certification (CA INTERMEDIAIRE)
```
mkdir -p /root/ca/intermediate_ca
cd /root/ca/intermediate_ca
mkdir certs crl csr newcerts private
chmod 700 private
touch index.txt
echo 1000 > serial
echo 1000 > /root/ca/intermediate_ca/crlnumber
```
Encore une fois comme pour l'autorité racine on crée un fichier openssl.cnf avec une légère différence (**on modifie uniquement la partie CA_default**):
```
[ CA_default ]
dir = /root/ca/intermediate_ca
private_key = $dir/private/intermediate.key.pem
certificate = $dir/certs/intermediate.cert.pem
crl = $dir/crl/intermediate.crl.pem
policy = policy_loose
new_certs_dir = $dir/certs
database = $dir/certs.db
serial = $dir/serial
crlnumber = $dir/crlnumber
```
On peut donc ensuite créer la clé privée de l'autorité intermédiaire et lui donné les droits de lecture pour le propriétaire.
```
openssl genrsa -aes256 -out private/intermediate.key.pem 4096
chmod 400 private/intermediate.key.pem
```
pass phrase : coucoulesamis
On utilise cette clé privée pour créer une demande de signature de certificat
```
openssl req -config openssl.cnf -new -sha256 -key private/intermediate.key.pem -out csr/intermediate.csr.pem
root@GRP04-PKI-CA-02-2:~/ca/intermediate_ca# openssl req -config openssl.cnf -new -sha256 -key private/intermediate.key.pem -out csr/intermediate.csr.pem
Enter pass phrase for private/intermediate.key.pem:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [FR]:FR
State or Province Name [Bretagne]:
Locality Name [Rennes]:
Organization Name [Luc et Gabriel]:
Organizational Unit Name [SSI]:
Common Name []:Luc Gabriel Root CA
Email Address [mail@defoufurieux.fr]:
```
Pour créer un certificat pour l'Autorité Intermédiaire, on utilise l'Autorité Racine avec l'extension "v3_intermediate_ca" pour signer le CSR de l'Intermédiaire.
Le certificat de l'Autorité Intermédiaire doit être valide pour une durée plus petite que celle de l'Autorité Racine.
Pour la prochaine commande nous avons besoin de transférer notre certificat a l'autorité racine pour le signer.
On utilise donc une commande scp pour le transferer sur l'autre serveur
```
scp -P 22 intermediate.csr.pem root@172.16.29.71:/root/ca/certstosign
```
Nous l'avons sur le serveur racine nous pouvons donc le signer grâce à la commande suivante
```
openssl ca -config openssl.cnf -extensions v3_intermediate_ca -days 3650 -notext -md sha256 -in /root/ca/certstosign/intermediate.csr.pem -out /root/ca/certsigned/intermediate.cert.pem
```
On lui rajoute les droits de lecture pour tout le monde puis on regarde s'il a bien été signé
```
openssl x509 -noout -text -in /root/ca/certsigned/intermediate.cert.pem
```
Encore une fois on retrouve les informations que l'on a donné lors de la génération du certificat mais aussi la ligne "Signature OK"
On peut également vérifier sa validité grâce à la commande
```
openssl verify -CAfile certs/ca.cert.pem /root/ca/certsigned/intermediate.cert.pem
/root/ca/certsigned/intermediate.cert.pem: OK
```
Quand une application essaies de vérifier la validité d'un certificat qui a été signé par une Autorité Intermédiaire, il doit également vérifier la validité du certificat de l'Autorité Intermédiaire auprès de l'Autorité Racine.
Pour valider la chaine de certification, on doit créer une chaine de certification des Autorité de Certification qu'on doit présenter à l'application.
Pour créer cette chaine de certification, on doit concaténer l'ensemble des certificats de l'Autorité Racine et de l'Autorité Intermédiaire. On utilisera ce fichier plus tard pour vérifier les certificats signés par l'Autorité Intermédiaire.
```
cat /root/ca/certsigned/intermediate.cert.pem certs/ca.cert.pem > /root/ca/chain/ca-chain.cert.pem
```
Puis on copie le certificat signé vers le serveur SUB CA :
```
scp -P 22 intermediate.cert.pem root@172.16.29.73:/root/ca/intermediate_ca/certs/.
```
### Certification d'un domaine web
La première étape pour certifier notre application web est de lui créer une clé privé grâce à notre autorité de certification.
```
openssl genrsa -aes256 -out private/www.luc.gabriel.bzh.key.pem 2048
chmod 400 private/www.luc.gabriel.bzh.key.pem
```
On utilise la clé privée pour créer la demande de signature de certificat.On copie le fichier openssl.cnf vers openssl-www.cnf et on ajoute la ligne : "subjectAltName = DNS:www.lucgabriel.bzh" à la partie "[ server_cert ]" :
```
cp openssl.cnf openssl-www.cnf
nano openssl-www.cnf
[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = DNS:www.lucgabriel.bzh
openssl req -config openssl-www.cnf -key private/www.luc.gabriel.bzh.key.pem -new -sha256 -out csr/www.luc.gabriel.bzh.csr.pem
```
On peut ensuite créer le certificat, il ne faut pas oublier par contre d'avoir remis dans le dossier "/ca/intermediate_ca/certs" le certificat intermediaire signé !
```
openssl ca -config openssl.cnf -extensions server_cert -days 375 -notext -md sha256 -in csr/www.luc.gabriel.bzh.csr.pem -out certs/www.lucgabriel.bzh.cert.pem -extensions server_cert
```
On retrouve notre certificat dans le fichier .db
```
root@certif:~/ca/intermediate_ca# cat certs.db
V 240326150610Z 1004 unknown /C=FR/ST=Bretagne/L=Rennes/O=Luc et Gabriel/OU=SSI/CN=www.lucgabriel.bzh/emailAddress=mail@defoufurieux.fr
```
On va donc vérifier les informations de notre certificat
```
openssl x509 -noout -text -in certs/www.lucgabriel.bzh.cert.pem
root@certif:~/ca/intermediate_ca# openssl x509 -noout -text -in certs/www.lucgabriel.bzh.cert.pem
```
On remarque dans notre certificat le "issuer" est l'Autorité Intermédiaire. Le "subject" fait référence au certificat lui-même.
On va utiliser le fichier de la chaine de certification (ca-chain.cert.pem), créé précédemment, pour vérifier que ce nouveau certificat est bien valide dans toute la chaine de confiance.
```
openssl verify -CAfile chain/ca-chain.cert.pem certs/www.lucgabriel.bzh.cert.pem
certs/www.lucgabriel.bzh.cert.pem: OK
```
Envoyer les fichier csr,crt,key vers le serveur web
On créer un fichier .nokey pour enlever la passphrase du fichier .key pour la conf nginx:
```
openssl rsa -in www.luc.gabriel.bzh.key.pem -out ./www.lucgabriel.bzh.nokey.pem
```
fichier de conf nginx :
```
server {
listen 443 ssl;
server_name www.lucgabriel.bzh;
root /var/www/html/index.html;
location / {
root /var/www/html;
index index.html index.htm;
}
ssl_trusted_certificate /root/ca/web/ca-chain.cert.pem;
ssl_certificate /root/ca/web/www.lucgabriel.bzh.cert.pem;
ssl_certificate_key /root/ca/web/www.lucgabriel.bzh.nokey.pem;
}
```
## Implémentation avec un serveur FTP
### Context
Le but de cette deuxième partie du mini projet est d'implémenter la PKI sur un serveur FTP utilisant un certificat généré par la PKI.
### Création du certificat FTP
La création du certificat pour le serveur FTP s'effectue de la meme façon que pour le serveur web. On créer tout d'abord la paire de clé :
```
openssl genrsa -aes256 -out private/ftp.luc.gabriel.bzh.key.pem 2048
chmod 400 private/ftp.luc.gabriel.bzh.key.pem
```
On utilise la clé privée pour créer la demande de signature de certificat.On copie le fichier openssl.cnf vers openssl-ftp.cnf et on ajoute la ligne : "subjectAltName = DNS:ftp.lucgabriel.bzh" à la partie "[ server_cert ]" :
```
cp openssl.cnf openssl-ftp.cnf
nano openssl-ftp.cnf
[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = DNS:ftp.lucgabriel.bzh
openssl req -config openssl-ftp.cnf -key private/ftp.luc.gabriel.bzh.key.pem -new -sha256 -out csr/ftp.luc.gabriel.bzh.csr.pem
```
On peut ensuite créer le certificat, il ne faut pas oublier par contre d'avoir remis dans le dossier "/ca/intermediate_ca/certs" le certificat intermediaire signé !
```
openssl ca -config openssl.cnf -extensions server_cert -days 375 -notext -md sha256 -in csr/ftp.luc.gabriel.bzh.csr.pem -out certs/ftp.lucgabriel.bzh.cert.pem -extensions server_cert
```
On retrouve notre certificat dans le fichier .db
```
root@certif:~/ca/intermediate_ca# cat certs.db
V 240326150610Z 1004 unknown /C=FR/ST=Bretagne/L=Rennes/O=Luc et Gabriel/OU=SSI/CN=www.lucgabriel.bzh/emailAddress=mail@defoufurieux.fr
V 240513134654Z 1006 unknown /C=FR/ST=Bretagne/L=Rennes/O=Luc et Gabriel/OU=SSI/CN=ftp.lucgabriel.bzh/emailAddress=mail@defoufurieux.fr
```
On va donc vérifier les informations de notre certificat
```
openssl x509 -noout -text -in certs/ftp.lucgabriel.bzh.cert.pem
root@certif:~/ca/intermediate_ca# openssl x509 -noout -text -in certs/ftp.lucgabriel.bzh.cert.pem
```
On remarque dans notre certificat le "issuer" est l'Autorité Intermédiaire. Le "subject" fait référence au certificat lui-même.
On va utiliser le fichier de la chaine de certification (ca-chain.cert.pem), créé précédemment, pour vérifier que ce nouveau certificat est bien valide dans toute la chaine de confiance.
```
openssl verify -CAfile chain/ca-chain.cert.pem certs/ftp.lucgabriel.bzh.cert.pem
certs/ftp.lucgabriel.bzh.cert.pem: OK
```
### Implémentation du certificat sur le serveur FTP
Une fois l'installation du serveur FTP réalisé, nous devons le configurer avec cette configuration.
```
ftpd_banner=Bienvenue sur le serveur ftp de LUC
vsftpd_log_file=/var/log/vsftpd.log
ssl_enable=YES
ssl_sslv3=YES
local_enable=YES
write_enable=YES
local_root=/home/ftp
local_umask=022
download_enable=YES
dirlist_enable=YES
local_max_rate=0
rsa_cert_file=/etc/ssl/certs/ftp.lucgabriel.bzh.cert.pem
rsa_private_key_file=/etc/ssl/private/ftp.luc.gabriel.bzh.key.pem
anonymous_enable=NO
dirmessage_enable=YES
xferlog_enable=YES
listen=YES
```
Nous devons évidemment placer préalablement les fichier de certificat à l'endroit indiquer avec les droits de lecture.
On peut tester la connexion :
Sur le serveur client on lance :
```
lftp -e "set ssl:ca-file /root/ca/intermediate_ca/chain/ca-chain.cert.pem" 172.16.28.90
#on force la connexion en sslv3
lftp 172.16.28.90:~> set ftp:ssl-force true
lftp 172.16.28.90:/> user user
Mot de passe :
****
lftp user@172.16.28.90:~> pwd
ftp://user@172.16.28.90/%2Fhome/ftp
```
On obtient bien une connexion sur le serveur :
Vérification sur le serveur FTP dans /var/log/vsftpd.log
```
Tue Jun 13 15:41:49 2023 [pid 1215] CONNECT: Client "172.16.28.87"
Tue Jun 13 15:41:49 2023 [pid 1214] [user] OK LOGIN: Client "172.16.28.87"
```