Sécuriser les données en JS : Chiffrement et confidentialité

January 22, 2017

Lors de cet article je vais faire un compte rendu (que je compléterai en partie) d’un article du MISC 88 concernant la sécurité et confidentialité des données en JavaScript.

Vous pouvez bien entendu trouver l’article complet sur le site de l’éditeur.

Les enjeux de la sécurité des données en JavaScript

Avec le développement des nouvelles API JavaScript les sites web possèdent de plus en plus de données personnelles et critiques sur les utilisateurs.

Certes parmi ces API nombreuses requièrent l’utilisation d’un certificat SSL pour pouvoir être utilisé - et encore cela dépend des navigateurs - il convient de constater que les informations ne sont pas toujours gérées de manière sécurisées côté serveur.

En effet, même si cela semble impensable de nombreux sites web stockes les mots de passe en clair. Et même dans les rares cas où il y a du chiffrement côté serveur la confidentialité n’est pas pour autant totalement assuré. Maintenant imaginons que le serveur ne fait que stocker une partie des informations sans pouvoir les manipuler ou interpréter directement, car le chiffrement serait effectué côté client. On pourrait avoir dans ce cas-ci un niveau de confidentialité plus élevé.

Optimisation des performances avec ASM.js

ASM.js est un sous ensemble de JavaScript ayant pour but de manipuler des structures de données avec des performances correctes s’approchant de celles obtenues par du code natif dans l’idéal. Toutefois, il faut prendre en compte que cet ensemble dépends du navigateur et du moteur JavaScript utilisé.

Concrètement ASM.js nous permet d’allouer un buffer pour ensuite le manipuler via des vues typées ce qui sera essentiel pour l’utilisation d’api de chiffrement JavaScript

WebCrypto API : Chiffrement, authentification et gestion des clés

Il est possible depuis peu d’utiliser l’api Web Cryptography API dans les cas suivants :

Cette API est basé sur le concept de future c’est-à-dire une interface qui définie un contrat asynchrone (ECMAScript 6). Les communications sont faites via deux paramètres de callback - un en cas du succès et l’autre pour l’échec.

On peut accéder à cette interface via le bout de code suivant

    window.crypto.subtle

Cette interface permet d’accéder à quatre familles d’opérations :

De plus, l’api window.crypto permet de générer un vecteur de valeur aléatoire. Par exemple si nous voulons 10 valeurs aléatoire nous pouvons utiliser le code suivant

    // get a vector of 10 unsigned int value (32bits)

    var randomValues = new Uint32Array(10);
    // randomize values

    window.crypto.getRandomValues(randomValues)

Nous allons à présent voir les différentes familles d’opération plus en détail.

Hashage avec WebCrypto : SHA-256 et autres algorithmes

Pour utiliser les fonctions de hash nous devons utiliser la méthode digest qui permet le hashage via les méthodes suivantes :

Je vais donner un exemple que j’avais réalisé en SHA-256

function sha256(str) {
  var buffer = new TextEncoder("utf-8").encode(str);
  return crypto.subtle.digest("SHA-256", buffer).then(function (hash) {
    return hex(hash);
  });
}
function hex(buffer) {
  var hexCodes = [];
  var view = new DataView(buffer);
  for (var i = 0; i < view.byteLength; i += 4) {
    var value = view.getUint32(i);
    var stringValue = value.toString(16);
    var padding = '00000000';
    var paddedValue = (padding + stringValue).slice(-padding.length);
    hexCodes.push(paddedValue);
  }
  return hexCodes.join("");
}
sha256("test").then(function(digest) {
  console.log(digest);
}); 

On remarque que le simple fait de faire un sha-256 neccessite plusieurs fonctions et se relève complexe avec notamment un traitement des données.

Comprendre la gestion des clés dans les applications sécurisées

Nous entrons maintenant dans la partie qui concerne les clés cryptographique. Ces clés seront utilisées dans pour les opérations suivantes il convient de voir leur gestion plus en détail.

Attention il y a une politique de même origine sur les clés, c’est-à-dire que deux sites ne peuvent se partager les clés directement

Nous avons donc les méthodes suivantes :

Nous pouvons faire transiter les clés dans du JSON au format JWK (voir JOSE).

Chiffrement des données avec WebCrypto API

L’utilisation de l’api de web cryptographie nous permet de chiffrer des données, bien entendu il faut au préalable importer les clés avant.

Nous pouvons effectuer du chiffrement symétrique et asymétrique.

Le chiffrement symétrique est de l’AES-256 avec les modes CTR, CBC, GCM, CFB tandis qu’en asymétrique nous avons à disposition du RSA (attention les données en entrée doivent être dans un ArrayBuffer).

Méthodes d’authentification en JavaScript : Signatures et vérification

Nous avons bien entendu la possibilité avec cette API d’effectuer de l’authentification de données. Pour cela nous pouvons signer et vérifier les données via les méthodes respectivement sign et verify .

Là encore il convient de différencier le mode symétrique (HMAC et AES-CMAC) du mode asymétrique. En asymétrique nous avons à disposition trois algorithmes (2 basé sur RSA et le dernier sur des courbes elliptiques) :

Résumé et perspectives sur la sécurité des données en JavaScript

Nous pouvons voir que le web évolue de plus en plus vers une augmentation de la sécurité et confidentialité des clients toutefois ces API bien qu’utiles semblent à mon avis hélas trop complexe pour y voir une intégration massive dans les diverses applications que nous pouvons utiliser.

comments powered by Disqus