3. Public Key Infrastructure

par julien - nov. 2005

1 - Introduction

Jusqu'ici, nous avons principalement travaillé sur l'aspect SSL d'un point de vue technique et implémentation. Mais, si ce que nous venons de voir fournit déjà un bon niveau de sécurité, c'est loin d'être suffisant pour une utilisation globale sur le réseau Internet. C'est pourquoi les PKI existent. Comme nous allons le voir, les PKI fournissent un structure globale de sécurité dans laquelle SSL n'est qu'un des différents composants.

2 - La notion de 'confiance'

La notion de confiance dans les ordinateurs est apparu vers 1985 avec “Orange Book - Trusted Computer System Evaluation Criteria” [1]. Un ordinateur est définit de confiance si il fait ce que l'on lui demande et EXACTEMENT celà, rien de plus, rien de moins.

Si nous appliquons ce principe à la cryptographie, nous en trouvons vite les limitations. Comment vérifier une identité sur l'Internet ? Si je ne peut pas vérifier l'identité d'un serveur, comment savoir si la clé qu'il me donne est valide ? Si ce n'est pas celle d'un pirate ? etc…

C'est pourquoi les techniques de crypto ne suffisent pas, elles ont besoin d'une 'enveloppe', une structure qui assure à l'utilisateur qu'il peut avoir confiance dans la clé qu'il va utiliser.

Dans un pays, qui est cette autorité de confiance ? Et bien c'est la préfecture d'une région. Cette dernière va vérifier l'identité d'une personne et, si celà correspond, elle va lui délivrer une carte d'identité. Une fois que la carte d'identité est délivrée, la préfecture n'intervient plus dans le contrôle de l'identité. Elle se contente seulement de délivrer la carte d'identité et c'est tout.

Alors qu'est ce qui fait qu'une carte d'identité a autant de valeur ? Et bien c'est la confiance que nous plaçons dans la préfecture car cette autorité nous assure qu'elle a mis en place des moyens suffisant pour valider l'identité des personnes.

Si nous n'avions pas confiance dans la préfecture, une carte d'identité n'aurait aucune valeur! C'est pas plus compliqué que ça !!!

Les PKI fonctionnent de la même façon. La préfecture est remplacée par une société qui valide l'identité d'un serveur et de son propriétaire, comme le fait VeriSign, BeTRUSTed, etc… Comme vous avez confiance dans ces sociétés, vous aurez confiance dans les certificats qu'elles émettent, ces derniers jouant le rôle de carte d'identité.

Et vous savez pourquoi vous avez confiance dans ces sociétés?? (que nous apellerons des “autorités de certificats” ou “CA”)

Et bien tout simplement parce que leurs certificats sont inclus dans les navigateurs Internet, comme étant de confiance. Exemple dans Firefox:

Editions/Préférences/Avancé/Certificats/Gérer les certificats
et vous allez dans l'onglet "Autorités"

Vous avez devant les yeux la liste des préfectures reconnus par votre navigateur comme étant de confiance ;) Libre a vous d'en supprimer ou d'en ajouter !

Pour en ajouter, il suffit de cliquer sur un certificat de CA: http://www.linuxwall.info/ressources/ca-linuxwall.crt

et le navigateur vous demande a quoi peut servir le certificat:

  1. identifier des sites web
  2. identifier des utilisateurs d'email
  3. identifier des développeur de logiciels

a vous de choisir, mais la plupart du temps ce sera pour des sites web.

Et voilà, vous avez maintenant confiance dans tous les certificats émis par le CA nommé “Linuxwall.info”.

3 - Certificats signés

Si vous regardez au dos de votre carte d'identité, vous allez voir la ligne “Signature de l'autorité” suivi de la signature manuscrite du préfet (ou de son représentant). Dans la mécanique des PKI, le même système est utilisé sauf qu'il est, évidemment, mathématique.

Parlons un peu technique: c'est quoi une signature ?

Dans le premier chapitre de ce dossier (“les bases”) nous avons vu que le chiffrement à partir de la clé privée d'une entitée permettait d'assurer l'authentification.

Rappel:
	on récupére le message et on le déchiffre avec la 
	clé publique de cette même entitée, seul le possesseur 
	de la clé privée a pu le chiffrer donc on est sur que 
	le message vient de l'entitée.

Admettons que l'entitée 'sachiel' ait envie de se créer un certificat valide et signé par l'autorité 'Linuxwall.info'.

Je vais donc génerer une requête qui ne sera pas signée, je vais aller voir les gens qui gérent l'autorité Linuxwall.info directement et leur dire que je souhaite qu'ils valident mon identité.

Ils vont donc contrôler que je suis bien qui je prétend être (carte ID, photo, passeport, …) puis ils vont prendre ma requête que j'ai généré sur mon petit linux chez moi. Je vous rappel que celle-ci n'est pas signée par une autorité quelconque pour le moment (celà signifie que ma requête n'est en fait qu'une clé publique que l'on va inclure dans un certificat).

Donc les gens de Linuxwall.info mettent ma requête sur leur serveur. Ce dernier est le gardien de la clé privée de l'autorité. Voilà ce qu'il fait:

1. Le serveur lit le contenu de la requête que je leurs ais fourni

2. le serveur me demande de remplir les différents champs du futur certificats (voir “les bases”, section “certificats x509”)

3. Le serveur applique une fonction de hachage (MD5, SHA-1, …) sur le certificat tout fraîchement généré

⇒ On récupére donc une “empreinte” de 128 ou 160 bits

4. Cette empreinte est cryptée avec la clé privée du serveur selon le mécanisme de chiffrement asymétrique (RSA, DSA, ElGamal, …)

6. Ce que nous venons de récupérer constitue la signature. On l'ajoute à la fin du certificat

7. Je récupére un certificat signé par l'autorité Linuxwall.info .

Et voilà, je peut rentrer chez moi et utiliser ce certificat signé dans mes applications TLS… :)

reprenons ces étapes avec un petit schéma:

  +---------------------------------------+
  |    	REQUETE DE SACHIEL	    |
  +---------------------------------------+
	||
	\/
  +-------------------------------+
  |     Autorité de certificats   |
  |	de Linuxwall.info	    |=>__________________________________
  +-------------------------------+  1.saisie des champs x.509
				       __________________________________
			       2.hachage des champs et de la clé
			       publique = empreinte
			       __________________________________
			       3.chiffrement de l'empreinte avec
			       la clé privée de l'autorité
			       =signature
			       __________________________________
			       4.concaténation du certificat et
			       de la signature
			       __________________________________
			       //
  +-------------------------------+<=~
  |	CERTIFICAT SIGNE	    |
  +-------------------------------+
	||
	\/
  +-------------------------------+
  | 	Restitution à Sachiel   |
  +-------------------------------+

Voici la signature de Sachiel par Linuxwall.info:

  Signature Algorithm: sha1WithRSAEncryption
          13:1b:93:37:ea:c8:60:ed:40:67:25:06:3a:ea:45:15:79:94:
          23:22:ba:72:33:54:b2:d2:38:61:10:b7:b7:70:45:37:68:45:
          d2:55:fa:b8:2b:22:2a:66:ea:b8:21:ee:1c:5a:be:20:b2:f8:
          9d:50:7e:b7:44:d1:b1:f5:4d:eb:37:2f:50:43:96:30:df:74:
          d2:2c:1f:4a:77:ee:ce:7f:76:81:c6:be:36:4a:64:84:51:cc:
          1d:a7:f9:21:ab:83:cd:15:a3:68:d7:99:96:b6:89:73:ec:41:
          e0:8b:6d:e9:c6:84:c9:71:d5:90:87:2f:05:ea:43:bc:08:d3:
          71:58:c8:5d:28:e6:dc:17:15:16:c6:61:2f:53:57:38:0e:74:
          b2:0a:22:3d:d9:ad:23:f6:f9:ec:73:cf:ac:e2:6f:ee:ed:ea:
          f2:25:31:52:87:de:eb:b8:7c:1e:e7:e2:7f:63:74:70:de:48:
          4f:20:65:f3:22:77:8d:f9:cd:d6:dc:a2:5c:c0:0e:d8:4f:ec:
          2c:6e:e9:ec:6a:57:e4:80:f1:b7:f3:f9:95:df:f5:39:86:1a:
          51:64:a5:67:f0:2d:83:c3:00:cc:b4:a6:9a:4b:9b:0e:aa:4c:
          d9:7c:d3:6a:03:3d:d5:e8:46:d5:25:08:91:82:cb:16:92:33:
          80:f6:bd:bf

La ligne “Signature Algorithm” nous dit bien que nous avons utilisé sha1 pour calculer l'empreinte du certificat, puis que nous avons utilisé rsa pour chiffrer cette empreinte.

Vérification de signature

Ainsi, quand vous contactez https://www.linuxwall.info, votre navigateur vas regarder le certificat fourni par le serveur apache de linuxwall et y appliquer le hachage sha1.

Appelons “Ea” l'empreinte que le navigateur calcule, il le fait de façon autonome et à juste besoin du certificat du site web.

Maintenant, il faut que nous comparions cette empreinte Ea à quelque chose pour vérifier si elle est valide.

Pour celà, nous récupérons le certificat public de l'autorité Linuxwall.info, déjà ajoutée plus haut.

Dans le certificat de Linuxwall.info se trouve la clé publique de l'autorité. Utilisons cette dernière pour déchiffrer la signature du certificat de Sachiel.

Une fois la signature déchiffrée, nous récupérons l'empreinte calculée par l'autorité lors de l'émission du certificat. Appelons la “Eb”

La suite est simple, si Ea == Eb alors notre certificat est valide.

En d'autres termes, si l'empreintes que NOUS avons calculé est la même que l'empreinte que L'AUTORITE a calculé, alors c'est que le certificat est bien celui que nous attendons.

Nous venons de faire mathématiquement ce qu'un policier fait quand il regarde votre carte d'identité !!! :=)

Il reste un point qu'il faut préciser… QUI SIGNE LE CERTIFICAT DE L'AUTORITE ??? la réponse est simple: lui-même !

Dans le chapitre précédent, nous avons vu comment créer un certificat autosigné, et bien la c'est la même chose… à 2 détails prêt !

1. Un certificat d'autorité ne peut pas servir a sécuriser des applications (telles que HTTPS).

2. On précise lors de la création d'un tel certificat qu'il servira à signer d'autre certificats, à signer des listes de révocations, etc….

4 - Création d'une PKI

Aller un peu de pratique, ca fait longtemps qu'on a pas touché au shell ;=). Pour commencer, il faut installer OpenSSL. Rien de bien compliqué car il il a environ 80% de chance que ce dernier soit déjà installé à cause des nombreuses applications qui utilisent ses librairies de cryptographie.

Dans le cas contraire, apt-get/yum/emerge/make/… sont vos amis :D

Une fois l'installation effectuée, nous allons commencer par configurer OpenSSL, pour celà il faut vous rendre dans le fichier openssl.cnf. Sous debian, c'est dans le répertoire /usr/lib/ssl

Sauvegardez l'ancienne version du fichier et remplacé le par ce qui suis en modifiant certaines valeurs par défaut

authority:/usr/lib/ssl# cat openssl.cnf
[ ca ]
default_ca      = CA_default
[ CA_default ]
dir             = /var/certificats
certs           = $dir/ca/certs
new_certs_dir   = $dir/ca/newcerts
database        = $dir/ca/index.txt
certificate     = $dir/ca/ca.pem
serial          = $dir/ca/serial
private_key     = $dir/ca/ca.key
default_days    = 3650
default_md      = sha1
preserve        = no
policy          = policy_match
[ policy_match ]
countryName             = supplied
stateOrProvinceName     = supplied
localityName            = supplied
organizationName        = supplied
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional
[ req ]
distinguished_name      = req_distinguished_name
[ req_distinguished_name ]
countryName                     = Pays
countryName_default             = FR
stateOrProvinceName             = Departement
stateOrProvinceName_default     = Partout_en_France
localityName                    = Ville
localityName_default            = Niort
organizationName                = Entreprise/Organisation
organizationName_default        = Linuxwall.info
commonName                      = Nom ou URL
commonName_max                  = 64
emailAddress                    = Adresse Email
emailAddress_max                = 40
[CA_ROOT]
nsComment                       = "Autorite de Certificats"
subjectKeyIdentifier            = hash
authorityKeyIdentifier          = keyid,issuer:always
basicConstraints                = critical,CA:TRUE,pathlen:1
keyUsage                        = keyCertSign, cRLSign
[SERVER_RSA_SSL]
nsComment                       = "Certificat Serveur SSL"
subjectKeyIdentifier            = hash
authorityKeyIdentifier          = keyid,issuer:always
issuerAltName                   = issuer:copy
basicConstraints                = critical,CA:FALSE
keyUsage                        = digitalSignature, 
				  nonRepudiation, 
				  keyEncipherment
nsCertType                      = server
extendedKeyUsage                = serverAuth
authorityInfoAccess             = OCSP;URI:http://xxxxxxxxx
crlDistributionPoints           = URI:http://xxxxxxxxx/current
[CLIENT_RSA_SSL]
nsComment                       = "Certificat Client SSL"
subjectKeyIdentifier            = hash
authorityKeyIdentifier          = keyid,issuer:always
issuerAltName                   = issuer:copy
basicConstraints                = critical,CA:FALSE
keyUsage                        = digitalSignature, 
				  nonRepudiation
nsCertType                      = client
extendedKeyUsage                = clientAuth
[OCSP]
nsComment                       = "OCSP Responder"
subjectKeyIdentifier            = hash
authorityKeyIdentifier          = keyid,issuer:always
basicConstraints                = critical,CA:FALSE
extendedKeyUsage                = OCSPSigning
crlDistributionPoints           = URI:http://xxxxxxxxxx/current

Attelons nous maintenant à expliquer tout ce charabia :

Section [CA_Default]

la premiere section definit les chemins par default pour les fichiers du CA (CA=Certificate Autority=Autorité de Certificats).

On travaillera dans /var/certificats/ca (libre a vous de le modifier) le certif du CA a une durée de vie de 10ans par default et utilise la fonction de hachage SHA-1.

enfin, on précise que l'on utilisera la politique définie dans la section [policy_match]

Section [policy_match]

cette section contient la description de l'importance des champs selon 3 valeurs:

  1. match: les champs du certif du CA et du certif du client DOIVENT correspondre
  2. optionnal: ce champ n'est pas requis
  3. supplied: INDISPENSABLE et propre à un certificat (url du site par ex.)

Section [req_distinguished_name]

Elle contient les champs x509 utilisés et leurs valeurs par default Bon alors ici ce sont les valeurs par défaut pour l'autorité Linuxwall Mettez les votres a la place

Section [CA_ROOT]

Ici, on définie quels sont les champs x509 que l'on spécifiera dans le certificat autosigné de l'autorité en gros:

  1. il est declaré comme CA (CA:TRUE)
  2. il peut signer les certificats (keyCertSign)
  3. il peut generer des listes de révocations (cRLSign)

Section [SERVER_RSA_SSL]

Elle contient les champs x509 des certificats que l'on générera pour des serveurs

Section [CLIENT_RSA_SSL]

Idem, mais pour des clients

STOP, on s'arrête 2 secondes ici pour parler des champs 'nsCertType' et 'ExtendedKeyUsage'. Bon, ok les valeurs sont explicites mais il faut bien faire la différence entre les deux. Grace à ces variables on sépare proprement les rôles de chacun. De plus, regardez les valeurs keyUsage: le serveur à la possibilité de chiffrer des clés, ce qui nous est utile lors de l'établissement de canal de chiffrement TLS (voir TLS Handshake Protocol dans “les bases”).

De plus, le certificat du serveur contient les chemins des listes de révocations de certificats. Ainsi, un serveur se tiens constamment informés de l'état des différents certificats de la PKI via le protocole OCSP que nous verrons en dernier chapitre de ce dossier.

D'ailleurs en parlant d'OCSP….

Section [OCSP]

je ne m'attarde pas, on y reviendra dans le 5éme chapitre :=) sachez juste que c'est un protocole de diffusion de l'état des certificats de la PKI (valide, révoqué ou suspendu).

maintenant que le fichier de configuration est pret (et compris…), on attaque la suite

Génération d'une autorité de certificats

Ici, on travaille dans le repertoire /var/certificats/ca/ Mais, ce n'est pas une obligation, vous pouvez tout a fait adapter ce chemin pour le dossier que vous voulez ;=)

Creation du certificat racine autosigne:

#openssl req -new -x509 -config usr/lib/ssl/openssl.cnf \
-extensions CA_ROOT -sha1 -newkey rsa:2048 -nodes -keyout \
ca.key -out ca.pem -days 3650 

Ca mouline quelques secondes pour génerer les clés puis le script de génération vas vous demander de donner des valeurs pour remplir les différents champs x509 que l'on a spécifié dans le fichier de conf.

A la fin, on recupere:

  1. une cle prive de 2048 bits stockee dans le fichier ca.key
  2. un certificat public au format pem dans le fichier ca.pem

PREMIERE CHOSE A FAIRE:

#chmod 600 ca.key

on vas quand meme pas laisser notre cle privee en lecture a tout le monde….

Il faut également créer quelques fichiers qui sont indispensable au fonctionnement de l'autorité racine. Ces fichiers doivent être dans le répertoire “ca”.

1.le fichier serial contient le numéro de série du prochain certificat signé par l'autorité:

#echo "01">serial

2.le fichier index.txt contient une ligne par certificat signé. C'est ce fichier qui contient l'état des certificats:

#touch index.txt

3.le répertoire newcerts contient une copie de chacun des certificats signés par la PKI. Ces certificats sont nommés par leur numéros de série. Seuls les certificats signés sont stockés, par les clés privées correspondantes:

#mkdir newcerts

Ensuite, on veut pouvoir exporter notre certificat public sur tous les navigateurs possible, pour cela il suffit d'exporter le fichier ca.pem dans un serveur apache en le renommant ca.crt Exemple avec celui de Linuxwall.info à l'adresse:

http://www.linuxwall.info/ressources/ca-linuxwall.crt

Génération d'un certificat serveur

On attaque maintenant la creation du certificat d'un serveur. On se place dans /var/certificats la variable [NOM] est a adapter pour chaque certificats ;=)

On commence par creer une cle privee rsa 2048bits et une demande de signature CSR (Certificate Signing Request):

#openssl req -new -config /usr/lib/ssl/openssl.cnf -newkey \
rsa:2048 -nodes -keyout [NOM].key -out [NOM].csr

Ici, le serveur ne pose aucune question, il génère juste les deux fichiers. Ensuite, nous soumettons le fichier CSR à l'autorité de certificats en précisant que nous utilisons le schéma SERVER_RSA_SSL:

#openssl ca -config /usr/lib/ssl/openssl.cnf -extensions \
SERVER_RSA_SSL -in [NOM].csr -out [NOM]-signed-cert.pem

C'est ici que le CA vas nous demander de remplir les champs x509. ATTENTION à bien remplir le champ “CommonName” avec l'URL du site web si le certificat est pour un serveur web. (ex: CommonName= www.linuxwall.info)

A la fin de l'opération, nous récupérons [NOM]-signed-cert.pem qui est le certificat public du serveur. C'est lui que nous allons diffuser. N'oubliez pas de modifier les droits sur la clé privée quand vous l'importerez sur votre serveur. Par exemple, dans apache:

  1. r–r—– 1 root www-data 2005-05-13 webmail.key
  2. r–r—– 1 root www-data 2005-05-13 webmail-signed-cert.pem

Génération d'un certificat client

En fait, c'est la meme chose que pour le serveur sauf pour la 2eme commande ou il faut remplacer SERVER_RSA_SSL par CLIENT_RSA_SSL .

Le Common Name est moins important ici. La convention est: CommonName= Prenom NOM

Enfin, pour la partie OCSP, nous verrons celà dans le dernier chapitre..

5 - Conclusion

Et bien voilà un bon gros sujet de traité :=) Ne vous inquiétez pas si ce n'est pas particuliérement clair au début, j'ai passé un bon moment sur les PKI pour bien les comprendre. Ce n'est pas un sujet évident mais tellement puissant quand on parle de sécurité qu'il mérite largement quelques litres de café et un bon week end de boulot !!! J'essaie d'écrire ces chapitres avec le plus de pédagogie possible mais dans le cas des PKI j'avoue que j'ai un peu ramé pour trouver les bons termes… donc si quelques chose est flou, n'hésitez pas à passer sur le forum où à m'envoyer un mail : switcher{a}linuxwall.info .

			Bibliographie
		-----------------------------

[1] DEPARTMENT OF DEFENSE TRUSTED COMPUTER SYSTEM EVALUATION CRITERIA http://www.radium.ncsc.mil/tpep/library/rainbow/5200.28-STD.html~~DISCUSSION~~

fr/ressources/dossiers/ssl_pki/3_pki.txt · Last modified: 2011/03/16 01:41 (external edit)
CC Attribution-Noncommercial-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0