web-dev-qa-db-fra.com

Comment crypter les données en frontend / backend avec une clé qui n'est stockée nulle part et n'est connue que du propriétaire?

J'ai lu un tas de réponses et de tutoriels sur la façon dont la cryptographie côté client n'est pas une bonne idée pour de nombreuses raisons énumérées principalement dans Javascript Cryptography Considered Harmful article. Quelques faits

  1. L'application utilisera HTTPS
  2. Il y aura une validation côté serveur et côté client
  3. Il n'y a pas de lien entre le mot de passe de l'utilisateur et le scénario suivant
  4. Le côté serveur est un service web RESTful (pas de session du tout)
  5. Le backend délivre JWT aux utilisateurs
  6. Le backend peut autoriser à la fois l'utilisateur/mot de passe ainsi que oauth (c'est-à-dire fb, Twitter, etc.)

Que veux-je chiffrer côté client?

L'utilisateur saisira certaines informations personnelles (nom, adresse, numéro de téléphone) via une application frontale (c'est-à-dire Vue.js, Angular, React, etc.)

Comment puis-je imaginer que cela va fonctionner?

L'utilisateur sélectionne des champs (c'est-à-dire des informations et des morceaux personnels), puis clique sur crypter. L'utilisateur fournira une clé de cryptage. Le frontend utilisera un js crypto library et crypter les informations et les remplacer dans le DOM et informer l'utilisateur de sauvegarder la clé de cryptage.

Comment puis-je communiquer ces informations au serveur?

Le frontend fera une requête HTTP PUT ou POST avec les informations personnelles (en clair/texte ou charabia) au serveur. Le serveur ne se soucie pas des données entrantes (c'est-à-dire à l'exception de sql ou d'autres formes d'injections) et les stocke immédiatement dans la base de données. Cette demande ne contiendra pas le encryption key mais, peut contenir un/des indicateur (s) pour spécifier quels champs ont été chiffrés.

Comment décrypter?

Lorsque l'utilisateur demande les informations, le backend renvoie tout ce qui se trouve sur le serveur tel quel. Les informations chiffrées seront affichées sous la forme gibberish pour l'utilisateur. En utilisant des drapeaux, le système leur donnera l'option decrypt et en cliquant dessus, cela leur demandera de saisir encryption key et effectue le déchiffrement localement.

La raison ultime?

Tout d'abord, tous les efforts seront faits pour s'assurer que le serveur et la base de données et tout sont à l'épreuve des balles mais, si pour une raison quelconque le serveur est piraté, le pirate se retrouverait avec des charges d'informations liées à des informations personnelles charabia.

La question ultime

Lire sur Internet, la cryptographie dans Javascript est fortement déconseillé, donc mes questions

  1. Compte tenu du scénario et de l'exigence ci-dessus, quels sont les risques imposant la mise en œuvre ci-dessus?
  2. Y a-t-il une approche que vous recommandez, où seul l'utilisateur contrôle la clé, et n'est stocké nulle part?
  3. Si je devais crypter ces informations dans le backend, comment puis-je communiquer le encrypt key en toute sécurité avec l'utilisateur? Peut-être crypter les informations à l'aide de la clé xyz, puis fournir un lien sécurisé à l'utilisateur pour cliquer et afficher la clé de cryptage xyz, ...?
  4. Quelles autres suggestions existe-t-il pour le chiffrement frontal et basé sur le backend?

Je voudrais donner à l'utilisateur l'assurance que lui seul sait déchiffrer la clé. Comment puis-je y parvenir de manière plus efficace? Sans avoir à stocker et gérer la clé de cryptage?

Mise à jour du 17 juillet 2018

Sur la base de la réponse acceptée, j'ai écrit un article sur la façon dont j'ai mis en œuvre la solution ici est le lien https://medium.com/@rhamedy/encryption-decryption-of-data-based-on-users- mot-de-passe-utilisant-pbkdf2-aes-algorithms-592f8c1bb79a

7
Raf

Lors de l'enregistrement initial de l'utilisateur, générez une clé de cryptage forte en utilisant un générateur de nombres pseudo-aléatoires cryptographiquement sécurisé; cette clé servira de clé de chiffrement des données (DEK) pour chiffrer les données de l'utilisateur. Mais vous ne voulez pas stocker le DEK n'importe où, au moins sous sa forme en clair. Vous souhaitez dériver une clé de chiffrement à partir du mot de passe de l'utilisateur, à l'aide d'une fonction de dérivation de clé telle que PBKDF2. Utilisez la clé que vous avez dérivée du mot de passe de l'utilisateur (la clé de cryptage de clé ou KEK) pour crypter le DEK. Ensuite, vous pouvez stocker en toute sécurité le texte chiffré de ce DEK dans la base de données.

Chaque fois que l'utilisateur se connecte par la suite, vous devez non seulement les authentifier, mais également dériver à nouveau la KEK à partir de leur mot de passe, puis utiliser cette clé dérivée pour déchiffrer le texte chiffré du DEK. Stockez le DEK dans la session sur le serveur, pas sur le client. Vous êtes maintenant en affaires; vous pouvez utiliser le DEK pour décrypter les informations côté serveur aussi longtemps que la session est active, mais pas après son expiration. Cela a l'avantage que l'utilisateur n'a pas à regarder un texte chiffré englouti. Vous pouvez à la place avoir un élément DOM de conteneur d'espace réservé disant "chiffré" ou quelque chose, et peut-être écouter les clics sur cet élément, qui invoque ensuite un appel à un point de terminaison API, qui récupère le texte chiffré de la base de données, le déchiffre sur le serveur avec le DEK que vous avez stocké dans la session, puis le retourne au client sous forme de texte brut juste là-bas, où vous pouvez l'injecter dans l'interface utilisateur pour que l'utilisateur puisse le voir. Aucune donnée sensible n'a besoin d'être stockée sur le client, et il n'est pas nécessaire d'effectuer des opérations cryptographiques sur le client. Cette approche présente également l'avantage supplémentaire que le DEK peut rester constant dans le temps. Si l'utilisateur change un jour son mot de passe, il suffit de dériver une KEK du nouveau mot de passe, de rechiffrer le même DEK qu'auparavant avec la nouvelle KEK et de stocker le nouveau texte chiffré du DEK dans la base de données comme auparavant.

6
vrtjason