web-dev-qa-db-fra.com

Javascript - Chiffrement côté client / stockage des clés

Je me rends compte que cela est souvent décrit comme une mauvaise idée. Donc, tout d'abord, je vais indiquer la motivation - n'hésitez pas à critiquer cela.

Créer un produit pour une industrie qui a tendance à trop se soucier de la sécurité. Le produit doit stocker et renvoyer des fichiers utilisateur, mais ils n'ont pas besoin d'être lisibles côté serveur.

Je pense qu'en chiffrant le côté client, cela réduirait la confiance requise des clients. Leurs données confidentielles ne seraient touchées que par JavaScript qu'ils pourraient inspecter et surveiller. Cela signifie également que tout problème de sécurité côté serveur qui autoriserait l'accès aux données stockées n'entraîne pas la disponibilité des documents clients (sauf s'ils peuvent modifier le JS servi).

Ma solution idéale serait -

- Key generated and injected to all clients users by clients IT team.
- JavaScript uses key to encrypt documents client side. These are then sent to the server and stored.
- On retrieval documents are decrypted again client side.

Il semble y avoir plusieurs bibliothèques pour prendre en charge la cryptographie côté client. Mais actuellement, je ne vois aucun moyen de stocker de manière persistante une clé pour l'utilisateur. Idéalement, cela serait similaire à l'ajout de certificats au magasin des navigateurs - c'est-à-dire qu'ils peuvent être injectés une fois.

Est-ce que quelqu'un a des suggestions?

6
Hector

(Pour être clair: cela protège uniquement les utilisateurs dans les situations où l'attaquant n'obtient qu'un accès en lecture seule et protège les utilisateurs qui n'ont pas utilisé le site depuis qu'un attaquant a remplacé le javascript par une version malveillante. Il ne protège pas les utilisateurs contre vous d'être malveillants dès le début, sauf si l'utilisateur vérifie/enregistre minutieusement tout le javascript que votre site leur fournit. Si cette dernière partie est importante pour vous, il pourrait y avoir un moyen d'utiliser ServiceWorkers pour alerter les utilisateurs chaque fois qu'une nouvelle version du javascript de votre site est exécutée, etc. , mais c'est pour une autre question.)

Vous pouvez stocker les clés de chiffrement localement dans le client avec localStorage ou IndexedDB. Les clés de chiffrement peuvent être des chaînes que votre client javascript utilise.

Sur les navigateurs pris en charge, pour une sécurité accrue, vous pouvez utiliser l'API Web Crypto (+ IndexedDB) à la place. Avec l'API Web Crypto, vous pouvez générer des clés en javascript et les utiliser pour le cryptage/décryptage, mais le code javascript ne peut pas accéder au matériel de clé brute quoi qu'il arrive. Cela signifie que même si un attaquant obtient un jour l'accès à votre serveur et remplace le javascript par une version malveillante, il ne peut pas le remplacer par une version qui laisse échapper les clés des utilisateurs. (Cependant, ils pourraient le remplacer par une version qui permet aux clients de télécharger leurs fichiers, de les décrypter et de les télécharger à nouveau en arrière-plan sur le serveur lors de leur prochaine visite sur le site. Cela prendrait du temps et pourrait être perceptible par les utilisateurs et/ou vous, donc cela pourrait vous donner suffisamment de temps pour corriger le problème avant que toutes les données utilisateur ne soient divulguées.)

4
Macil

Si vous utilisez le chiffrement asymétrique à partir de openpgp.js, la clé privée est stockée chiffrée par défaut puis brièvement déchiffrée pour déchiffrer ou signer un message avec la phrase secrète des utilisateurs.

Il n'est jamais stocké non chiffré et repose sur la mémorisation par l'utilisateur de la phrase secrète qu'il a utilisée pour créer la paire de clés.

Dans ce cas, même si le pirate a trouvé les clés privées, elles sont inutiles sans la phrase secrète.

L'inconvénient est que nous devons former l'utilisateur à stocker en toute sécurité sa phrase secrète quelque part!

2
user2677034

Si vous contrôlez le code source côté serveur:

Ma suggestion est que vous stockiez au moins 4 clés sur le backend que vous faites pivoter et côté serveur de chiffrement symétrique utilisateur, puis faites tout le côté serveur de chiffrement et de déchiffrement.

J'ai eu un cas d'utilisation similaire où mon flux de travail était (avec cryptage fernet):

  • L'utilisateur télécharge les données puis les chiffre avec 1 des 10 clés (tournées) puis stockées dans la base de données

  • Sur requête après avoir obtenu si de la base de données, puis déchiffrez-le et envoyez-le au frontend

Avantages:

  • Plus sûr, puis manipulez toutes les clés sur le frontend

  • Si la base de données a été exploitée via l'injection SQL, ce n'est pas du texte brut

Désavantages:

  • Besoin de plus de ressources côté serveur car cela ralentit le processus

  • Les clés sont toujours du côté du serveur de texte brut, donc si la machine hôte est compromise, aucune aide n'est possible, mais l'attaquant reste une étape de plus pour accéder aux données.

Si vous ne contrôlez pas le code côté serveur:

Le mieux que vous puissiez faire est de stocker la clé symétrique dans la base de données et d'en enregistrer une pour chaque utilisateur. Après la connexion, enregistrez-le dans le cookie en tant que session pour cet utilisateur

Avantages:

  • Facile à mettre en œuvre

  • Chaque utilisateur a sa propre clé symétrique si un compte d'utilisateur est compromis, les données des autres utilisateurs ne peuvent pas être déchiffrées

Désavantages:

  • Le cookie peut être volé, donc aucun en-tête iframe n'est indispensable

  • Si elles ne sont pas utilisées, les attaques par mitm HTTPS et HSTS peuvent facilement obtenir les données

Mais ne prenez pas ma suggestion car le Saint-Graal attend et recherche d'autres sources, c'est à vous de décider. ;)

1
Hrvoje Milković

Je pense qu'en chiffrant le côté client, cela réduirait la confiance requise des clients. Leurs données confidentielles ne seraient touchées que par JavaScript qu'ils pourraient inspecter et surveiller.

Ce n'est pas vraiment vrai. Aucune personne normale ne peut réellement inspecter et surveiller javascript les téléchargements du navigateur à partir d'un site, et si je fais suffisamment confiance au serveur/à l'administrateur du serveur/aux développeurs de logiciels serveur pour croire qu'ils ne m'envoient pas javascript avec une porte dérobée, je pourrais aussi bien faites-leur confiance pour stocker mes fichiers.

Je suis d'accord que c'est une couche de sécurité supplémentaire, mais c'est une couche qui est si facilement supprimée qu'il semble presque inutile de la mettre en œuvre. Il protège contre certains scénarios de menace - par exemple, il protège probablement les sauvegardes ou les anciens disques durs qui ne sont pas effacés de la fuite des données du client - mais cela ne réduit pas beaucoup la confiance que les clients doivent accorder au fournisseur de services.

Mais actuellement, je ne vois aucun moyen de stocker de manière persistante une clé pour l'utilisateur.

Si vous ne souhaitez pas le stocker dans le stockage du navigateur côté client, vous pouvez

a) Demander à l'utilisateur de fournir au client javascript une phrase secrète, de chiffrer symétriquement la clé avec la phrase secrète et un chiffrement symétrique fort et d'envoyer la clé au serveur pour y être stockée

b) Affichez la clé sous forme de code QR et demandez à l'utilisateur de prendre une photo avec son téléphone portable. Lorsque vous avez besoin de la clé, l'utilisateur peut copier-coller la chaîne de clé que le code QR résout pour revenir dans l'application javascript côté client. C'est très lourd, cependant.

1
Out of Band