Imaginons que j'écris une application Web ciblant des utilisateurs techniquement enclins et soucieux de la sécurité qui n'ont aucun problème à générer et à utiliser des clés GPG ou SSH.
Est-il possible d'utiliser ces clés pour s'authentifier auprès d'une application Web de manière sécurisée pour remplacer l'authentification traditionnelle par mot de passe?
Si c'est possible, à quoi ressembleront les étapes d'authentification? Existe-t-il peut-être une bonne implémentation connue d'une telle idée pour les langages et plates-formes populaires comme Ruby, .NET, Java ou Python?
Si ce n'est pas possible, quelles en sont les raisons? Y a-t-il peut-être une contrainte sur les navigateurs Web accédant au trousseau GPG ou au fichier de clé SSH?
Pour une application Web, le principal problème est que le code du site Web (Javascript dans un navigateur) n'est pas capable de lire et d'écrire des fichiers à volonté. Eh bien, en général, c'est plus une aubaine qu'un problème, mais ici cela signifie que le code Javascript ne pourra pas accéder aux clés privées SSH ou PGP.
Il y a des choses qui peuvent être faites, selon le niveau de connaissances technologiques de vos utilisateurs et le nombre d'opérations manuelles qu'ils toléreront:
Vous pouvez utiliser une extension de navigateur installée localement qui accède aux clés privées SSH ou PGP au nom du site Web. De préférence, un certain contrôle utilisateur est conseillé: nous ne voulons vraiment pas d'un navigateur qui signera les choses simplement parce qu'un site Web a dit de le faire.
Le serveur peut agir comme un serveur SSH et nécessite que les clients se connectent avec SSH et l'authentification client basée sur les clés. L'utilisateur exécuterait SSH en mode "proxy SOCKS". Le serveur Web lui-même n'écouterait que localhost
, c'est-à-dire qu'il serait inaccessible sauf via un tel proxy local. Dans ce mode, le serveur Web pourrait même être HTTP, pas HTTPS; ce serait vraiment remplacer SSL par SSH. Côté serveur, le suivi des utilisateurs doit utiliser mod_ident ou quelque chose de similaire (le serveur SSH sait qui est le client, mais les informations doivent être transmises au serveur HTTP; heureusement, c'est sur la même machine, donc l'identité de niveau Unix peut être utilisée).
Le site Web pourrait afficher un "défi" sous forme de fichier téléchargeable avec un contenu aléatoire. L'utilisateur obtient le fichier, le signe avec GnuPG et colle la sortie (blindée ASCII) dans un champ de texte sur le site Web. Le serveur vérifie la signature et l'accepte comme authentifiant l'utilisateur (à condition que le serveur connaisse déjà la clé publique de l'utilisateur). Clunky, mais fonctionne.
Une variante basée sur la messagerie de ce qui précède peut être recommandée, car les implémentations PGP sont souvent intégrées dans le logiciel de messagerie, et également parce qu'elles ouvrent la possibilité de ne pas avoir à faire confiance à une autorité de certification racine externe. Cela ressemblerait à ceci:
L'utilisateur se connecte au serveur Web avec HTTPS. Le serveur utilise un certificat auto-signé. Le navigateur en avertit ("l'avertissement rouge effrayant") mais permet à l'utilisateur de continuer.
Sur le site, l'utilisateur entre son nom. Ensuite, le serveur envoie un courriel signé et chiffré (avec PGP) à l'utilisateur; l'e-mail signé contient un nonce aléatoire, ainsi qu'une copie de l'empreinte numérique du certificat SSL du serveur. Le nonce aléatoire est également imprimé sur le site Web lui-même.
L'utilisateur vérifie la signature PGP sur l'e-mail du serveur, puis vérifie que l'empreinte correspond à celle qu'il peut voir depuis son navigateur; cela convainc l'utilisateur qu'il voit le certificat de serveur authentique, il n'y a donc pas d'attaque en cours Man-in-the-Middle . (C'est ici que nous remplaçons le système CA X.509 par une validation basée sur PGP.)
L'utilisateur vérifie également que le nonce affiché sur le site Web correspond à celui qu'il voit dans l'e-mail (c'est important).
L'utilisateur répond à l'e-mail en renvoyant son contenu, cette fois signé avec sa propre clé privée PGP, et chiffré avec la clé publique du serveur. Le serveur vérifie cet e-mail et sait ainsi que la valeur nonce a bien été reçue par l'utilisateur prévu.
Le serveur envoie la valeur nonce sous forme de cookie au navigateur de l'utilisateur. Cela permet de naviguer sans harceler l'utilisateur avec d'autres rondes d'authentification. Il appartient au serveur de décider combien de temps il acceptera le cookie comme jeton d'authentification valide.
Dans le schéma ci-dessus, il est important de noter qu'en renvoyant sa réponse par e-mail, l'utilisateur autorise vraiment le serveur à supposer que celui qui revient avec le nonce (tel que inclus dans l'e-mail) est vraiment l'utilisateur lui-même. C'est pourquoi il est important de vérifier manuellement que le nonce correspond à ce qui est affiché sur la page Web.
Est-il possible d'utiliser des paires de clés OpenPGP/SSH pour s'authentifier avec une application Web de manière sécurisée pour remplacer l'authentification traditionnelle par mot de passe?
Oui. Il est tout à fait possible.
Si c'est possible, à quoi ressembleront les étapes d'authentification? Existe-t-il peut-être une bonne implémentation connue d'une telle idée pour les langages et plates-formes populaires comme Ruby, .NET, Java ou Python?
Voir ma réponse pour la question suivante.
Si ce n'est pas possible, quelles en sont les raisons? Y a-t-il peut-être une contrainte sur les navigateurs Web accédant au trousseau GPG ou au fichier de clé SSH?
Le traitement des clés SSH et OpenPGP dans une application Web est possible avec des bibliothèques tierces (en particulier C ou Java étant donné leur écologie riche), mais vous ne pourriez pas tirer parti de la solution existante la plus courante - SSL/TLS.
Le meilleur pari serait que les utilisateurs génèrent un certificat client X509 signé par votre serveur pour s'authentifier - car votre application Web peut simplement s'appuyer sur le conteneur Web (Catalina Tomcat, ApacheD, IIS, etc.) pour effectuer un chiffrement et une authentification transparents pour votre application.
Sous le capot, les clés OpenPGP ont les mêmes exposants RSA qu'un certificat X509, donc des outils tels que openssl
peuvent convertir des clés GPG/PGP en certificats X509 auto-signés; idem pour clés SSH .
* Le site Web de confiance d'OpenPGP est considéré comme "auto-signé" du point de vue X509 car X509v3 ne peut pas avoir de chaîne de confiance à racines multiples pour autant que j'ai pu le déterminer.
Les réponses existantes offrent de bons conseils - utilisez plutôt la pile SSL dans le navigateur.
Cependant, il est en fait possible de faire exactement ce que vous voulez - en utilisant la cryptographie JavaScript.
Il y a une implémentation OpenPGP en JavaScript http://openpgpjs.org/ Je ne peux pas garantir sa qualité.
De plus, il est possible pour HTML5 JavaScript d'accéder à des fichiers locaux, par exemple http://www.html5rocks.com/en/tutorials/file/dndfiles/
Je pense que ce serait plus une curiosité qu'un système pratique.