Crypter les liens entre les utilisateurs enregistrés et leurs données sensibles
Je veux qu'il soit impossible de relier les utilisateurs à leurs données sensibles sans leur mot de passe - même avec un accès complet à la base de données.
De plus, si un utilisateur possède plusieurs éléments de données sensibles, je souhaite également éviter de relier les différents éléments entre eux
Sur la base des commentaires et de quelques recherches, j'ai mis à jour la question.
Je trouve un peu semblables questions , mais aucun ne semble donner les détails que je suis à la recherche, ou qui ont des conditions préalables légèrement différentes (partage de données) p.ex.
Ainsi, en plus d'enregistrer les utilisateurs du site Web et de les gérer avec des opérations CRUD standard, je stocke dans la base de données des données potentiellement sensibles des utilisateurs. À cet égard, cette question est similaire et les réponses m'offrent également des lignes directrices. Plus précisément, je ne devrais «rien stocker dans [ma] base de données qui pourrait être utilisé pour obtenir la clé de chiffrement sans connaître le mot de passe».
Le côté client est composé de simples pages html / css / js et, pour le moment, une application de bureau n'est pas une option. J'analyse les données uniquement en groupes (sur la base de variables dans les données) afin que les données individuelles ne présentent aucun intérêt. Cependant, je souhaite que les utilisateurs puissent voir leurs propres données et, par exemple, supprimer les données si vous le souhaitez.
Ce que je pense, c'est générer une clé pour chaque élément de données, chiffrer les paires clé-data_id dans la base de données et les déchiffrer chaque fois qu'une clé non chiffrée est nécessaire, que ce soit pour stocker des données ou lorsqu'un utilisateur souhaite voir ses données:
import json
from cryptography.fernet import Fernet
def get_key(password, data_id):
# Check that the given password is valid
if not self.check_password(password):
raise KeyError('The given password is not valid')
# Always use string representation of the data_id since json allows only string keys
data_id_str = str(data_id)
# Create a Fernet object with the password
f = Fernet(password)
# Set the encoding for the bytes <-> string conversion
encoding = 'utf-8'
# Decrypt and load into a dict the existing keys
if self.encrypted_keys:
# Ensure that the encrypted keys are in bytes for the Fernet
bytes_encrypted_keys = bytes(self.encrypted_keys)
# Decrypt the encrypted keys and transform the bytes object into a string
keys_string = f.decrypt(bytes_encrypted_key).decode(encoding)
# Load the string into a dict
keys_dict = json.loads(keys_string)
# Create an empty dict if no keys defined
else:
keys_dict = {}
# Try to get a key for the data_id
try:
key = keys_dict[data_id_str]
# The key not found
except KeyError:
# Generate a new a URL-safe 32-byte key and decode as a string into the keys_dict
key = keys_dict.setdefault(
data_id_str,
Fernet.generate_key().decode(encoding),
)
# Turn the updated keys_dict into a string
updated_keys_string = json.dumps(keys_dict)
# Encode the string into bytes for the Fernet
bytes_keys = updated_keys_string.encode(encoding)
# Encrypt the updated keys
self.encrypted_keys = f.encrypt(bytes_keys)
# Save the encrypted keys into the database
self.encrypted_keys.save()
# Return the decrypted key for the data_id
return key
Cela vous semble-t-il un processus raisonnable? Y a-t-il des défauts évidents qui me manquent? Est-ce exagéré? Y a-t-il d'autres choses que je devrais considérer?
Je suis conscient qu'un point faible est la force du mot de passe. Je vais essayer de gérer cela avec les contrôles de résistance standard.
Je comprends également qu'un accès au serveur donne la possibilité d'intercepter le processus et de compromettre les clés. Bien sûr, s'il y avait un moyen d'éviter cela, sans application de bureau, je serais intéressé. Actuellement, j'espère au moins sécuriser la base de données.
Merci pour le conseil!
Réponses
Si je comprends bien:
Oubliez le cryptage et le décryptage et la protection des clés. Rien de tout cela n'est nécessaire.
Utilisez un hachage de la même manière que les identités de mot de passe sont conservées.
Le hachage devient un identifiant unique des données sans révéler l'utilisateur.
Vous dérivez un hachage complexe approprié du mot de passe fourni par l'utilisateur. L'utilisateur peut ensuite fournir ce mot de passe pour que vous puissiez le hacher à nouveau pour obtenir l'identifiant correspondant à ses données.
Pas de chichi, pas de soucis, pas de mots de passe stockés.
--EDIT pour votre contrainte nouvellement ajoutée--
De plus, si un utilisateur possède plusieurs éléments de données sensibles, je souhaite également éviter de relier les différents éléments entre eux
Utilisez un Salt aléatoire pour produire un ID de hachage différent pour chaque objet blob de données. En l'absence d'autres contraintes, vous devrez calculer le hachage pour chaque sel du système pour trouver une correspondance. Cela peut être trivial pour des centaines, mais pour des valeurs beaucoup plus importantes, vous voudrez peut-être une contrainte supplémentaire.