[Devoxx 2013] Cryptographic operations in the browser

devoxx 2013Après le multimédia, je continue les sessions autour du web avec les APIs de cryptographie natives dans le navigateur. La session est animée par Nick Van den Bleeken qui participe au groupe de standardisation sur le sujet au W3C.

La complexité des sites web augmentant très rapidement, de nouveaux besoins apparaissent. Un de ces besoins étant de protéger les données, qu’elles soient locales ou distantes. A cette fin, le W3C a commencé à travailler sur une API de cryptographie directement disponible dans le navigateur.

Les slides sont disponibles en ligne et un projet de démonstration est également proposé.

Les problématiques liées à la cryptographie coté client

Pour commencer, Nick nous a présenté les trois cas d’utilisation classiques de la cryptographie :

  • Pour s’authentifier
  • Pour signer numériquement des documents
  • Pour protéger des messages ou des documents lors de l’envoi ou lors de leur stockage

Techniquement, il est déjà possible de faire de la cryptographie dans le navigateur via des APIs JavaScript telles que SJCL, cryptoJS, JSBN ou openPGP.js. Il existe également un module dans Closure pour le faire.

Cependant, toutes ces implémentations en JavaScript pur ne sont pas optimales à cause de la nature même du langage. Il est particulièrement vulnérable aux attaques par chronométrage. Un autre problème de taille est que la fonction Math.random() n’est pas suffisamment robuste et sécurisée pour faire de la cryptographie.

Un autre problème majeur est lié aux performances nécessaires pour qu’un algorithme de chiffrement efficace puisse être mis en place. Le fait que JavaScript utilise des floats codés sur 64 bits pose des problèmes de performance.

Enfin, nous manquons cruellement d’experts en cryptographie suffisamment bons en JavaScript pour écrire des implémentations performantes des algorithmes de chiffrement qui tiendraient compte de tous ces points.

Des solutions existent cependant, en utilisant des applets Java ou en utilisant des plugins natifs propres à chaque navigateur. Dans tous les cas, cela nécessite un composant externe à installer. Et si, comme pour Java, il est déjà installé, les navigateurs ont une politique de plus en plus agressive sur la désactivation des plugins par défaut, pour contrer les multiples failles de sécurité trouvées. Sans compter que, sur mobile, il est impossible d’utiliser ces extensions.

Ce ne sont donc pas des solutions pérennes et il fallait trouver une alternative. C’est ce que propose le W3C avec l’arrivée de la spécification pour faire de la cryptographie directement dans le navigateur.

Toutes les entreprises impliquées dans les navigateurs dominants participent au groupe de réflexion ainsi que de grands noms du web tel que Netflix.

L’objectif étant d’amener des capacités cryptographiques sur tout les supports ayant un navigateur : PC de bureau, mobile, TV, etc.

Un cas d’utilisation plus concret

Après ce rappel du contexte qui entoure le développement de l’API, Nick nous a présenté un exemple de cas d’utilisation pour lequel l’API a été conçue.

En l’occurrence : échanger un document avec sa banque après avoir confirmé l’identité du client.

Tout commence par une série d’étapes d’initialisation :

  1. la banque doit fournir un code à usage unique (par SMS par exemple) au client pour confirmer que c’est bien lui qui initie la transaction ;
  2. la banque vérifie que l’utilisateur est sur son pc personnel et pas sur un PC public qui serait vulnérable ;
  3. le client génère une paire de clefs privée/publique ;
  4. les clefs sont stockées localement dans le navigateur ;
  5. la clef publique est transmise à la banque ;
  6. la clef publique de la banque est transmise au client.

Ces étapes ne sont nécessaires qu’une fois pour chaque couple périphérique/navigateur, afin de générer les clefs qui vont permettre de chiffrer les échanges. Elles se font en tache de fond, de manière transparente pour l’utilisateur, à l’exception de la saisie du code à usage unique.

Pour que le navigateur vous génère une clef cryptographique, vous devez utiliser la méthode window.crypto.subtle.generateKey à laquelle vous fournissez des informations de configuration de l’algorithme de chiffrement.

L’API est basée sur l’utilisation des promesses avec une méthode then qui sera appelée lorsque la clef est prête.

Les échanges de clefs avec la banque peuvent se faire à l’aide du format JWK, et il est possible d’enregistrer la clef publique de la banque dans le navigateur à l’aide de la méthode window.crypto.subtle.importKey.

L’import se fait, comme la génération, de manière asynchrone via des promesses. Bien évidement, les échanges réseaux se font via HTTPS si vous ne voulez pas compromettre l’ensemble.

Une fois les clefs générées et échangées, nous pouvons enfin entrer dans le vif du sujet.

Pour valider que la personne qui l’appelle est bien l’utilisateur initial, la banque envoie un message chiffré à l’aide de la clef publique de l’utilisateur.

Celui-ci reçoit le message, vérifie qu’il est bien chiffré avec sa clef privée à l’aide de la méthode window.crypto.subtle.verify, puis le déchiffre avec la méthode window.crypto.subtle.decrypt, qui renvoie le message en clair.

Maintenant que l’utilisateur possède le message initial en clair, il lui faut le signer à l’aide de la méthode window.crypto.subtle.sign, en utilisant la clef publique de la banque, avant de lui envoyer.

En comparant le message initial à celui qu’elle reçoit, la banque peut s’assurer que la personne avec qui elle communique est bien celle qui possède les bonnes clefs de chiffrage.

L’utilisateur et la banque peuvent maintenant s’échanger des messages ou des documents chiffrés avec les clefs publiques de leur destinataire, et s’assurer que seul celui-ci pourra les lire.

Autres cas d’utilisation

Il est également possible de gérer des clefs symétriques avec une passphrase afin de, par exemple, chiffrer des documents stockés dans le cloud. Cela se fait avec la méthode window.crypto.subtle.deriveKey.

Il est possible d’imaginer plein de cas d’utilisation concrets, comme faire un tchat sécurisé, chiffrer des données stockées dans le localstorage, voire même de stocker le code JavaScript dans le localstorage et générer des digests afin de s’assurer qu’il n’est pas altéré par un tiers.

La suite

La prochaine étape est de finaliser la spécification et d’étendre son support dans les navigateurs. En effet, pour le moment, seuls IE11 et Chrome supportent cette API. Et encore, IE11 supporte une ancienne version, basée sur des événements au lieu de promises, et Chrome nécessite l’activation d’un flag et ne possède pas les méthodes d’import et d’export de clefs.

Il existe également un polyfill nommé PolyCrypt qui, comme IE11, utilise l’ancienne API.

Il est également prévu de pouvoir chiffrer directement des flux de données, lorsque la spécification associée aux flux sera stabilisée au niveau du W3C.

Enfin, une évolution intéressante serait de pouvoir interagir avec des équipements de sécurité externe, types boîtiers et lecteurs de cartes. Cependant, cela demande une forte collaboration avec les fabricants de ces solutions, ce qui n’est pas aisé.

Conclusion

L’arrivée de cette API sera une très bonne chose pour mieux sécuriser les échanges. Et le stockage de données en local va permettre de s’affranchir de limites qui obligeaient à soit reporter le traitement sur le serveur, soit faire une application native.

Il est à noter que, pendant la séance de questions, a été évoquée la politique d’accès aux clefs qui, comme d’habitude, est basée sur la “same origin policy”. Seuls les fichiers servis par le domaine associé à la clef peuvent manipuler celle-ci.

Nombre de vue : 47

AJOUTER UN COMMENTAIRE