> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Verschlüsselung (Encryption)

> Erläutert, wie Sie Werte mithilfe der Crypt-Facade in Laravel per AES-256-CBC verschlüsseln und wieder entschlüsseln. Enthält Themen wie APP_KEY-Erzeugung, Model-Casts und die sichere Ablage personenbezogener Daten.

## Was ist die Crypt-Facade?

Der Verschlüsselungsdienst von Laravel stellt eine einfache Schnittstelle zur Verfügung, um Werte per **OpenSSL** und AES-256-CBC (bzw. AES-128-CBC) zu ver- und entschlüsseln.

Alle in Laravel verschlüsselten Werte werden mit einem **Message Authentication Code (MAC)** signiert.
Wird ein verschlüsselter Wert manipuliert, lässt er sich damit nicht mehr entschlüsseln.

```mermaid theme={null}
flowchart LR
    A["Klartext"] -->|"Crypt::encryptString()"| B["Verschlüsselter Wert<br>(mit MAC signiert)"]
    B -->|"Crypt::decryptString()"| A
    B -->|Manipulation erkannt| C["DecryptException"]
```

***

## Konfiguration

### APP\_KEY erzeugen

Vor der Verwendung der Verschlüsselung muss die Option `key` in `config/app.php` gesetzt sein.
Sie wird aus der Umgebungsvariable `APP_KEY` gelesen.

Erzeugen Sie einen sicheren Schlüssel mit dem Befehl `php artisan key:generate`.
Er nutzt PHPs sicheren Zufallszahlengenerator und erstellt kryptografisch starke Schlüssel.

```shell theme={null}
php artisan key:generate
```

Bei der Installation von Laravel wird der Schlüssel in der Regel automatisch erzeugt und in der `.env`-Datei gespeichert.

```ini theme={null}
APP_KEY=base64:J63qRTDLub5NuZvP+kb8YIorGS6qFYHKVo6u7179stY=
```

<Warning>
  Geben Sie den `APP_KEY` niemals heraus. Fällt er in die falschen Hände, können alle verschlüsselten Daten entschlüsselt werden.
</Warning>

### Rotation des Verschlüsselungsschlüssels

Wenn Sie den Verschlüsselungsschlüssel ändern, werden alle authentifizierten Nutzersitzungen abgemeldet.
Grund ist, dass Laravel alle Cookies – einschließlich Session-Cookies – verschlüsselt.

Zudem lassen sich mit einem alten Schlüssel verschlüsselte Daten nicht mehr entschlüsseln.

Um dieses Problem abzumildern, können Sie in `APP_PREVIOUS_KEYS` alte Schlüssel kommagetrennt hinterlegen.

```ini theme={null}
APP_KEY="base64:J63qRTDLub5NuZvP+kb8YIorGS6qFYHKVo6u7179stY="
APP_PREVIOUS_KEYS="base64:2nLsGFGzyoae2ax3EF2Lyq/hH6QghBGLIq5uL+Gp8/w="
```

Zum Verschlüsseln nutzt Laravel immer den aktuellen Schlüssel. Beim Entschlüsseln probiert es zunächst den aktuellen Schlüssel und, wenn dieser fehlschlägt, der Reihe nach die alten Schlüssel.
So können Nutzerinnen und Nutzer die Anwendung auch während der Rotation weiterverwenden.

***

## Verschlüsseln

Verschlüsseln Sie Werte mit der Methode `encryptString` der Facade `Crypt`.
Die Werte werden per OpenSSL und AES-256-CBC verschlüsselt und mit einem MAC signiert.

```php theme={null}
<?php

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Crypt;

class DigitalOceanTokenController extends Controller
{
    /**
     * Den API-Token des Nutzers speichern.
     */
    public function store(Request $request): RedirectResponse
    {
        $request->user()->fill([
            'token' => Crypt::encryptString($request->token),
        ])->save();

        return redirect('/secrets');
    }
}
```

<Tip>
  `encryptString` verschlüsselt Strings **ohne** vorherige Serialisierung. Möchten Sie Objekte oder Arrays verschlüsseln, verwenden Sie `encrypt`.
</Tip>

| Methode                        | Verwendung                                                            |
| ------------------------------ | --------------------------------------------------------------------- |
| `Crypt::encryptString($value)` | Verschlüsselt einen String direkt                                     |
| `Crypt::encrypt($value)`       | Serialisiert den Wert und verschlüsselt ihn (auch Arrays und Objekte) |

***

## Entschlüsseln

Entschlüsseln Sie Werte mit der Methode `decryptString` der Facade `Crypt`.
Kann der Wert nicht korrekt entschlüsselt werden – etwa wegen eines ungültigen MAC –, wird eine `DecryptException` ausgelöst.

```php theme={null}
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Support\Facades\Crypt;

try {
    $decrypted = Crypt::decryptString($encryptedValue);
} catch (DecryptException $e) {
    // Verhalten bei fehlgeschlagener Entschlüsselung
    abort(400, 'Ungültige Daten.');
}
```

| Methode                        | Verwendung                                                  |
| ------------------------------ | ----------------------------------------------------------- |
| `Crypt::decryptString($value)` | Als String entschlüsseln                                    |
| `Crypt::decrypt($value)`       | Entschlüsseln und deserialisieren (auch Arrays und Objekte) |

***

## Model-Casts

Mit dem Cast `encrypted` verschlüsselt Eloquent Attribute automatisch beim Speichern und entschlüsselt sie beim Auslesen.

```php theme={null}
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected function casts(): array
    {
        return [
            'secret_note'    => 'encrypted',           // Verschlüsselter String
            'profile_data'   => 'encrypted:array',     // Array verschlüsselt speichern
            'preferences'    => 'encrypted:collection',// Collection verschlüsselt speichern
            'metadata'       => 'encrypted:object',    // Objekt verschlüsselt speichern
            'settings'       => 'encrypted:json',      // Als JSON verschlüsselt speichern
        ];
    }
}
```

Ist der Cast gesetzt, werden Werte beim Setzen und Auslesen automatisch verschlüsselt bzw. entschlüsselt.

```php theme={null}
// Wird automatisch verschlüsselt in die Datenbank geschrieben
$user->secret_note = 'Geheime Notiz';
$user->save();

// Wird automatisch entschlüsselt zurückgegeben
echo $user->secret_note; // 'Geheime Notiz'
```

<Info>
  Die `encrypted:*`-Casts nutzen intern `Crypt::encrypt` und `Crypt::decrypt`.
  Als Datenbankspaltentyp empfehlen sich `text` oder `longText`.
</Info>

***

## Praxisbeispiel: personenbezogene Daten verschlüsselt speichern

Ein typisches Muster für die sichere Ablage personenbezogener Informationen (z. B. Sozialversicherungsnummern oder Kreditkartendaten).

### Migration

```php theme={null}
Schema::create('profiles', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained();
    $table->text('my_number')->nullable();     // Verschlüsselter Wert als text
    $table->text('bank_account')->nullable();
    $table->timestamps();
});
```

### Model

```php theme={null}
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Profile extends Model
{
    protected $fillable = ['user_id', 'my_number', 'bank_account'];

    protected function casts(): array
    {
        return [
            'my_number'    => 'encrypted',
            'bank_account' => 'encrypted',
        ];
    }
}
```

### Controller

```php theme={null}
use App\Models\Profile;
use Illuminate\Http\Request;

class ProfileController extends Controller
{
    public function store(Request $request)
    {
        $request->validate([
            'my_number'    => ['required', 'string'],
            'bank_account' => ['required', 'string'],
        ]);

        // Das Modell verschlüsselt die Werte automatisch beim Speichern
        Profile::create([
            'user_id'      => $request->user()->id,
            'my_number'    => $request->my_number,
            'bank_account' => $request->bank_account,
        ]);

        return redirect('/profile');
    }

    public function show(Request $request)
    {
        $profile = $request->user()->profile;

        // Das Modell entschlüsselt die Werte automatisch beim Auslesen
        return view('profile.show', ['profile' => $profile]);
    }
}
```

***

## Zusammenfassung

| Aufgabe                                    | Vorgehen                                          |
| ------------------------------------------ | ------------------------------------------------- |
| APP\_KEY erzeugen                          | `php artisan key:generate`                        |
| String verschlüsseln                       | `Crypt::encryptString($value)`                    |
| String entschlüsseln                       | `Crypt::decryptString($value)`                    |
| Array/Objekt verschlüsseln                 | `Crypt::encrypt($value)`                          |
| Modell-Attribute automatisch verschlüsseln | Cast `'column' => 'encrypted'`                    |
| Schlüsselrotation                          | Alte Schlüssel in `APP_PREVIOUS_KEYS` hinterlegen |

## Nächste Schritte

<Columns cols={2}>
  <Card title="Hashing" icon="lock" href="/de/hashing">
    Erfahren Sie, wie Sie Passwörter sicher hashen und prüfen.
  </Card>

  <Card title="Autorisierung" icon="shield" href="/de/authorization">
    Steuern Sie Zugriffe mit Policies und Gates.
  </Card>
</Columns>


## Related topics

- [Redis](/de/redis.md)
- [OAuth-2.0-Authentifizierung - Google Sheets API for Laravel](/de/packages/laravel-google-sheets/oauth.md)
- [Deployment](/de/deployment.md)
- [Routing](/de/routing.md)
- [Verzeichnisstruktur](/de/directory-structure.md)
