web-dev-qa-db-fra.com

Authentification par certificat client SSL

Est-il possible de faire un programme qui utilise l'authentification par certificat client avec uniquement des clés publiques et privées (je n'ai généré aucun certificat, je n'ai que des clés publiques et privées).

Simplement, je veux faire l'authentification sur le serveur avec l'authentification par certificat client. Mais il est difficile de créer un certificat client par programmation.

Je veux faire l'authentification du certificat client avec uniquement la clé publique et privée (je n'ai que la clé publique et privée, pas de certificat).

Il est possible d'envoyer la clé publique du serveur au lieu du certificat client pour l'authentification du certificat client?

10
Taleh Ibrahimli

Les certificats ne sont que la clé publique avec un contexte supplémentaire. Le nom de la clé, les signatures, les directives d'utilisation, etc. SSL/TLS dépend de ce contexte. Sinon, l'hôte auquel vous vous connectez ne saura pas si la clé vous appartient réellement ou non. Le mécanisme de confiance SSL repose sur le concept de certificats explicitement approuvés, puis sur les certificats implicitement approuvés qu'ils signent.

Mais si vous n'utilisez pas SSL ou TLS, le cryptage peut toujours se produire sans lui, mais la confiance doit se produire d'une manière différente. SSH en est un bon exemple: SSH utilise toujours des clés publiques et privées, mais comme il n'y a pas de hiérarchie de signatures, les informations supplémentaires fournies par les certificats ne seraient pas utiles, donc la clé est envoyée nue. Au lieu de cela, le client vous demande s'il faut ou non faire confiance à la clé publique du serveur la première fois qu'il se connecte et vérifie ensuite chaque fois si la clé publique correspond à ce qu'il a vu la dernière fois. Cela peut se produire car SSH n'utilise pas SSL ou TLS pour son cryptage.

Mais si vous utilisez le protocole SSL, le protocole dicte que la clé publique doit être présentée avec le contexte ajouté du certificat. Autrement dit, le certificat est le conteneur dans lequel la clé publique doit être placée pour que SSL puisse l'utiliser.

Si vous avez la clé privée, il est trivial de créer un certificat auto-signé à l'aide d'un outil comme OpenSSL.

11
tylerl

SSL/TLS prend en charge l'authentification client avec un certificat. Ce qui se passe vraiment en interne, c'est que:

  • Le serveur demande un "certificat client" via un message CertificateRequest.
  • Le client envoie son certificat sous la forme d'un message Certificate et calcule également une signature (à l'aide de sa clé privée) sur tous les messages précédents de la négociation; la signature est envoyée sous la forme d'un message CertificateVerify.
  • Le serveur en quelque sorte obtient la clé publique du client (normalement en décodant le certificat client comme un certificat X.509 , en le validant dans la manière X.509, puis en extraire la clé publique) et l'utilise pour vérifier la signature du client.

Cependant, dans le protocole lui-même, les certificats sont échangés sous forme de blocs d'octets opaques; chaque "certificat" est envoyé avec un en-tête de 3 octets qui spécifie sa longueur. Ainsi, si vous contrôlez à la fois le code serveur et client, c'est à vous de décider comment interpréter ces morceaux d'octets. Vous n'avez pas besoin d'envoyer un certificat X.509 . Vous pouvez envoyer un message vide, si vous le souhaitez.

Les points importants restent:

  • Pour que l'authentification ait un sens, le serveur doit connaître avec une certaine garantie la clé publique du client. La signature démontre que le client contrôle la clé privée, mais cela ne sert à rien que si la clé publique correspondante est attachée sans ambiguïté à une identité de client connue.

  • La paire de clés doit être d'un type adapté aux signatures (c'est-à-dire RSA ou DSA, pas Diffie-Hellman).

Les implémentations SSL existantes pourraient insister sur au moins le respect du format X.509, auquel cas vous devez encapsuler votre clé publique dans une sorte d'auto-signature Certificat X.509, qui est relativement facile par programmation avec certaines bibliothèques comme OpenSSL .

Il existe un standard pour remplacer les certificats X.509 dans SSL par des clés publiques OpenPGP, démontrant l'agilité de format inhérente à SSL.

9
Thomas Pornin

(Ceci est basé sur ma réponse à la même question sur SO . Il est souvent préférable de demander sur un seul site SE.)

Le protocole TLS permet uniquement l'échange de certificats, pas les clés publiques brutes. Même les "clés PGP" (si vous vouliez remplacer X.509 par OpenPGP pour l'authentification dans TLS , ce qui est beaucoup moins pris en charge) sont en fait des certificats (ils sont la combinaison signée d'une clé publique et un ensemble d'identifiants et d'attributs).

Comme le dit Thomas, vous pouvez éventuellement définir votre propre type de certificat et en faire une clé publique simple (bien que je ne sois pas sûr qu'ils puissent encore être appelés "certificats" techniquement).

D'un point de vue pratique, vous devriez être en mesure d'obtenir ce dont vous avez besoin en utilisant les piles SSL/TLS existantes et en modifiant la façon dont elles gèrent les certificats de vérification X.509, avec prudence. En effet, la plupart des piles SSL/TLS exposent la vérification des certificats X.509 via leurs API, mais peu autorisent d'autres types de certificats (par exemple OpenPGP) ou vous permettraient de personnaliser facilement leur code. La personnalisation des certificats non X.509 pourrait être assez difficile, pourrait entraîner des bogues supplémentaires si vous êtes nouveau dans la mise en œuvre de SSL/TLS et serait également difficile à déployer dans la pratique, car tous les clients potentiels devraient également prendre en charge vos personnalisations .

Vous pouvez effectuer l'authentification client à l'aide de certificats client X.509 auto-signés et vous fier à leurs clés publiques (, mais vous devrez vérifier cette clé publique par rapport à quelque chose que votre serveur connaît déjà, tel qu'un élément connu). liste ). Vous devez d'abord comprendre les implications en matière de sécurité pour l'implémentation. Ce n'est pas tout à fait le même problème que les certificats de serveur auto-signés. (Je suggère de conserver une approche plus traditionnelle pour vérifier le certificat du serveur.)

Vous pouvez faire en sorte que le client envoie un certificat auto-signé (éventuellement en utilisant certaines astuces concernant la liste des autorités de certification publiées par le serveur ) et soit effectuer la vérification dans la pile TLS ou plus tard dans l'application.

Notez que de nombreux conteneurs d'applications (par exemple Tomcat/Jetty en Java) s'attendent à ce que la couche SSL/TLS vérifie le certificat client. Par conséquent, si vous sautez l'authentification là-bas (et préférez le faire plus tard dans le conteneur ou dans le cadre de l'application), de nombreux cadres d'application seront confus. Vous devez être très prudent pour vous assurer que l'authentification est réellement effectuée quelque part avant d'effectuer toute action qui nécessite une authentification dans votre application.

Par exemple, il peut être correct d'avoir un gestionnaire de confiance qui laisse passer tout certificat client dans Tomcat/Jetty, mais vous ne pouvez pas compter sur le javax.servlet.request.X509Certificate l'attribut de demande doit avoir été vérifié de quelque façon que ce soit (ce que la plupart des frameworks attendraient autrement). Vous auriez besoin d'implémenter une logique de vérification dans votre application: par exemple, avoir un filtre avant toute fonctionnalité authentifiée qui compare la clé publique dans ce certificat client avec votre liste connue de clés publiques (ou comme vous voulez faire correspondre la clé publique à un identifiant). Alternativement, vous pouvez également effectuer cette vérification dans votre gestionnaire de confiance personnalisé (en Java), cela nécessitera moins de travail dans les applications.

Vous pouvez faire quelque chose de similaire dans un Apache Httpd + PHP (par exemple), en utilisant SSLVerifyClient optional_no_ca. Encore une fois, votre application PHP ne pouvait pas compter sur la vérification du certificat, vous devriez donc implémenter cette vérification là aussi.

Ne faites rien de tout cela à moins de comprendre à quel stade les informations de certificat que vous obtenez ont été vérifiées.

2
Bruno

en plus de notre cher ami, tylerl

vous devriez connaître la commande Linux OpenSSL et avoir une bonne programmation des compétences en PHP ou Perl. (spécialement PHP) voici quelques bons guides à ce sujet: 1 - http: // www. php.net/manual/en/book.openssl.php et 2-openssl. org vous devez avoir une connaissance approfondie de la commande openssl et de ses fonctions.

à la fin: (votre question) Est-il possible d'envoyer la clé publique du serveur au lieu du certificat client pour l'authentification du certificat client? non, à cause de vous, vous risquez d'oublier le protocole TLS Handshake qui montre étape par étape client-serveur l'authentification et l'échange de clés. http://msdn.Microsoft.com/en-us/library/windows/desktop/aa380513%28v=vs.85%29.aspx

0
Passenger