Verschlüsselung von Links zwischen registrierten Benutzern und ihren vertraulichen Daten

Nov 20 2020

Ich möchte es unpraktisch machen, die Benutzer ohne ihre Passwörter mit ihren sensiblen Daten zu verknüpfen - selbst bei vollem Zugriff auf die Datenbank.

Wenn ein Benutzer mehrere sensible Daten hat, möchte ich außerdem vermeiden, die verschiedenen Teile miteinander zu verknüpfen

Aufgrund der Kommentare und einiger Suchanfragen habe ich die Frage aktualisiert.

Ich habe ein paar ähnliche Fragen gefunden, aber keine scheint die Details anzugeben, nach denen ich suche, oder hat etwas andere Voraussetzungen (z. B. Datenaustausch).

Zusätzlich zur Registrierung von Website-Benutzern und deren Verwaltung mit Standard-CRUD-Vorgängen speichere ich einige möglicherweise vertrauliche Daten der Benutzer in der Datenbank. In dieser Hinsicht ist diese Frage ähnlich, und die Antworten bieten auch Richtlinien für mich. Insbesondere sollte ich "nichts in [meiner] Datenbank speichern, das zum Abrufen des Verschlüsselungsschlüssels verwendet werden könnte, ohne das Kennwort zu kennen".

Die Client-Seite besteht aus einfachen HTML / CSS / JS-Seiten, und im Moment ist eine Desktop-App keine Option. Ich analysiere die Daten nur in Gruppen (basierend auf Variablen in den Daten), so dass einzelne Daten nicht von Interesse sind. Ich möchte es den Benutzern jedoch ermöglichen, ihre eigenen Daten zu sehen und beispielsweise die Daten zu löschen, wenn dies gewünscht wird.

Ich denke, für jedes Datenelement wird ein Schlüssel generiert, die Schlüssel-Daten-ID-Paare in die Datenbank verschlüsselt und jedes Mal entschlüsselt, wenn ein unverschlüsselter Schlüssel benötigt wird, entweder zum Speichern von Daten oder wenn ein Benutzer seine Daten sehen möchte:

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

Scheint dies ein vernünftiger Prozess zu sein? Gibt es einige offensichtliche Mängel, die mir fehlen? Ist das übertrieben? Gibt es noch andere Dinge, die ich beachten sollte?

Mir ist bewusst, dass eine Schwachstelle darin die Stärke des Passworts ist. Ich werde versuchen, das mit den Standard-Festigkeitsprüfungen zu schaffen.

Ich verstehe auch, dass ein Zugriff auf den Server die Möglichkeit bietet, den Prozess abzufangen und die Schlüssel zu gefährden. Wenn es eine Möglichkeit gäbe, dies ohne eine Desktop-App zu verhindern, wäre ich natürlich interessiert. Derzeit hoffe ich zumindest, die Datenbank zu sichern.

Danke für den Ratschlag!

Antworten

user10216038 Nov 22 2020 at 03:44

Wenn ich richtig verstehe:

Vergessen Sie die Ver- und Entschlüsselung sowie den Schlüsselschutz. Nichts davon ist notwendig.

Verwenden Sie einen Hash genauso wie Passwortidentitäten.

Der Hash wird zu einer eindeutigen Kennung der Daten, ohne den Benutzer preiszugeben.

Sie leiten einen entsprechend komplexen Hash aus dem vom Benutzer angegebenen Kennwort ab. Der Benutzer kann dieses Kennwort später angeben, damit Sie es erneut hashen können, um die übereinstimmende Kennung für seine Daten abzuleiten.

Keine Aufregung, kein Muss, keine gespeicherten Passwörter.

--EDIT für Ihre neu hinzugefügte Einschränkung--

Wenn ein Benutzer mehrere sensible Daten hat, möchte ich außerdem vermeiden, die verschiedenen Teile miteinander zu verknüpfen

Verwenden Sie ein zufälliges Salt , um für jeden Daten-Blob eine andere Hash-ID zu erstellen. Ohne weitere Einschränkungen müssten Sie den Hash für jedes Salz im System berechnen, um eine Übereinstimmung zu finden. Das mag für Hunderte trivial sein, aber für viel größere Werte möchten Sie möglicherweise eine zusätzliche Einschränkung.