Vorname wird nur verschlüsselt angezeigt.

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
PythonNoob123
User
Beiträge: 2
Registriert: Samstag 23. November 2024, 11:37

Hallo liebes Forum,
ich drehe mich irgend wie im Kreis. Egal was ich probiere egal was ich mache immer nur verschlüsselt.
Vielleicht kann mir ja jemand weiter helfen, danke.

Also das Verschlüssel und Endschlüsseln an sich funktioniert.
Es scheint als wenn Django hier was verschluckt, aber ich komme nicht drauf.

Auf der postgre Datenbank ist die Spalte "iv" ein bytea

Mein model.py:

Code: Alles auswählen

class Testperson(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, db_column="id")
    vorname = EncryptedCharField(max_length=512, db_column="vorname", iv_field="iv")
    nachname = EncryptedCharField(max_length=512, db_column="nachname", iv_field="iv")
    iv = models.BinaryField(null=False, blank=True, db_column="iv")
meine fields.py:

Code: Alles auswählen

# core/fields.py
import os
from django.db import models
from core.crypto import encrypt_value, decrypt_value

class EncryptedCharField(models.CharField):
    """
    CharField, das automatisch verschlüsselt/entschlüsselt.
    IV wird pro Zeile aus einer BinaryField-Spalte geholt.
    """
    def __init__(self, *args, iv_field="iv", **kwargs):
        self.iv_field = iv_field
        super().__init__(*args, **kwargs)

    def _get_iv(self, instance):
        iv = getattr(instance, self.iv_field, None)
        if isinstance(iv, memoryview):
            iv = iv.tobytes()
        if iv is None or len(iv) != 16:
            raise ValueError(f"IV fehlt oder ist ungültig für {self.attname}")
        return iv

    def _create_iv_if_missing(self, instance):
        iv = getattr(instance, self.iv_field, None)
        if not iv or len(iv) != 16:
            iv = os.urandom(16)
            setattr(instance, self.iv_field, iv)
        return iv

    # Verschlüsseln beim Speichern
    def pre_save(self, instance, add):
        value = instance.__dict__.get(self.attname)
        if value is None:
            return value
        iv = self._create_iv_if_missing(instance)
        encrypted = encrypt_value(value, iv)
        instance.__dict__[self.attname] = encrypted
        return encrypted

    # Vom DB-Wert in das Feld laden (unverändert)
    def from_db_value(self, value, expression, connection):
        return value

    # Zugriff auf das Feld: automatisch entschlüsseln
    def __get__(self, instance, owner):
        if instance is None:
            return self

        encrypted_value = instance.__dict__.get(self.attname)
        if encrypted_value is None:
            return None

        try:
            iv = self._get_iv(instance)
            # nur hex entschlüsseln, andere Werte direkt zurückgeben
            int(encrypted_value, 16)
            return decrypt_value(encrypted_value, iv)
        except (ValueError, AttributeError):
            return encrypted_value

    # Setzen des Wertes: automatisch verschlüsseln
    def __set__(self, instance, value):
        iv = self._create_iv_if_missing(instance)
        encrypted = encrypt_value(value, iv)
        instance.__dict__[self.attname] = encrypted
meine views.py:

Code: Alles auswählen

@Testperson_required
def dashboard(request):

    user_id = request.session.get("user_id")
    tp = Testperson.objects.get(id=user_id)

    print(tp.vorname)

    return render(request, "core/dashboard.html", {
        "benutzer": tp
    })
Bei "print(tp.vorname)" wird der verschlüsselte Wert angezeigt und nicht z.b. "Tim".
Das gleiche auch in der html:

Code: Alles auswählen

<strong>Willkommen, {{ benutzer.vorname }} {{ benutzer.nachname }}!</strong>
Benutzeravatar
grubenfox
User
Beiträge: 631
Registriert: Freitag 2. Dezember 2022, 15:49

Da passiert wohl ein Fehler in

Code: Alles auswählen

        try:
            iv = self._get_iv(instance)
            # nur hex entschlüsseln, andere Werte direkt zurückgeben
            int(encrypted_value, 16)
            return decrypt_value(encrypted_value, iv)
        except (ValueError, AttributeError):
            return encrypted_value
und in der nicht ausgegebenen Fehlermeldung steht wahrscheinlich was hilfreiches (unter anderem ob dort nun eine ValueError-Exception oder eine AttributeError-Exception auftritt...)
Benutzeravatar
DeaD_EyE
User
Beiträge: 1300
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Nur ein Hinweis: Wenn jemand deine Datenbank einfach kopiert, kann derjenige alles entschlüsseln. Ich habe auch keine Idee, wie man sich davor schützen kann. Egal wie man es wendet, letztendlich benötigt die WebApp Zugriff auf den Schlüssel, um die Namen entschlüsseln zu können. Selbst wenn man asymetrische Verschlüsselung verwendet, hat man das Problem, dass die WebApp trotzdem Zugriff auf den privaten Schlüssel benötigt. Wenn die WebApp darauf zugreifen kann, kann der Hacker das auch.

Deswegen halte ich die Verschlüsselung für unnötig. Besser wäre es nur das an personenbezogenen Daten zu speichern, die wirklich notwendig sind. Umso weniger Daten man speicher, desto weniger Daten können gestohlen werden.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
nezzcarth
User
Beiträge: 1790
Registriert: Samstag 16. April 2011, 12:47

@DeaD_EyE: Was du beschreibst, gilt, wenn ein Angriff über die Webanwendung stattfindet oder wenn die Webanwendung und die Datenbank auf demselben System liegen. Spätestens wenn man den absoluten Hobby-Bereich verlässt, ist es heute aber eigentlich üblich, dass die Anwendung und das DBMS von einander getrennt laufen, d.h. man hat z.B. getrennte Container oder einen separaten Datenbankserver und entsprechend hat das System, auf dem die Datenbank läuft, wenn man es richtig macht auch keinen Zugriff auf den Schlüssel.

Die Verschlüsselung ist in diesen Fällen sehr wohl sinnvoll und verhindert Angriffe, die sich explizit auf das Datenbank-System beziehen; sie verhindert z.B. dass der Datenbankadmin oder andere User/Anwendungen (bei Fehlkonfiguration oder Bugs) die Daten sehen, sie verhindert Datenlecks bei physischem Zugriff auf den DB-Server, sie verhindert, dass diese Daten im Plaintext in SQL-Dumps auftauchen, etc. Ich stimme zu, dass Datensparsamkeit ein guter Grundsatz ist. Aber manchmal muss man eben schützenswerte Daten speichern. Und dann ist Verschlüsselung in der Datenbank schon ein sinnvoller Baustein.
Antworten