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

# Versleuteling (Encryption)

> Uitleg over het versleutelen en ontsleutelen van waarden met AES-256-CBC via de Crypt-facade van Laravel. Behandelt onder meer het genereren van de APP_KEY, modelcasts en het veilig opslaan van persoonsgegevens.

## Wat is de Crypt-facade?

De versleutelingsservice van Laravel biedt een eenvoudige interface voor het versleutelen en ontsleutelen van waarden met AES-256-CBC-versleuteling (of AES-128-CBC) via **OpenSSL**.

Alle in Laravel versleutelde waarden zijn ondertekend met een **message authentication code (MAC)**.
Daardoor kan een versleutelde waarde die is gemanipuleerd niet meer worden ontsleuteld.

```mermaid theme={null}
flowchart LR
    A["Platte data"] -->|"Crypt::encryptString()"| B["Versleutelde waarde<br>(ondertekend met MAC)"]
    B -->|"Crypt::decryptString()"| A
    B -->|Manipulatie gedetecteerd| C["DecryptException"]
```

***

## Configuratie

### De APP\_KEY genereren

Voordat je versleuteling gebruikt, moet de `key`-instelling in `config/app.php` zijn geconfigureerd.
Deze waarde wordt gelezen uit de omgevingsvariabele `APP_KEY`.

Genereer een veilige sleutel met het commando `php artisan key:generate`.
Er wordt een cryptografisch veilige sleutel gegenereerd met de veilige willekeurige-getallengenerator van PHP.

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

Bij de installatie van Laravel wordt deze meestal automatisch gegenereerd. De gegenereerde sleutel wordt opgeslagen in het `.env`-bestand.

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

<Warning>
  Maak de `APP_KEY` nooit openbaar. Als deze sleutel uitlekt, kan alle versleutelde data worden ontsleuteld.
</Warning>

### Rotatie van de versleutelingssleutel

Als je de versleutelingssleutel wijzigt, worden alle geauthenticeerde gebruikerssessies uitgelogd.
Dat komt doordat Laravel alle cookies versleutelt, inclusief de sessiecookie.

Bovendien kan data die met de vorige sleutel is versleuteld niet meer worden ontsleuteld.

Om dit probleem te verzachten, kun je oude sleutels kommagescheiden opsommen in `APP_PREVIOUS_KEYS`.

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

Laravel gebruikt voor versleuteling altijd de huidige sleutel, maar als ontsleutelen met de huidige sleutel mislukt, probeert het de oude sleutels een voor een.
Zo kunnen gebruikers de applicatie blijven gebruiken tijdens een sleutelrotatie.

***

## Versleutelen

Versleutel waarden met de `encryptString`-methode van de `Crypt`-facade.
Versleutelde waarden gebruiken OpenSSL met AES-256-CBC-versleuteling en worden ondertekend met een MAC.

```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
{
    /**
     * Sla het API-token van de gebruiker op
     */
    public function store(Request $request): RedirectResponse
    {
        $request->user()->fill([
            'token' => Crypt::encryptString($request->token),
        ])->save();

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

<Tip>
  `encryptString` versleutelt strings **zonder** serialisatie. Gebruik `encrypt` als je objecten of arrays wilt versleutelen.
</Tip>

| Methode                        | Gebruik                                                                         |
| ------------------------------ | ------------------------------------------------------------------------------- |
| `Crypt::encryptString($value)` | Versleutelt een string zoals hij is                                             |
| `Crypt::encrypt($value)`       | Serialiseert de waarde en versleutelt daarna (geschikt voor arrays en objecten) |

***

## Ontsleutelen

Ontsleutel versleutelde waarden met de `decryptString`-methode van de `Crypt`-facade.
Als het ontsleutelen niet lukt, bijvoorbeeld omdat de MAC ongeldig is, wordt een `DecryptException` gegooid.

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

try {
    $decrypted = Crypt::decryptString($encryptedValue);
} catch (DecryptException $e) {
    // Afhandeling als het ontsleutelen mislukt
    abort(400, 'Ongeldige gegevens.');
}
```

| Methode                        | Gebruik                                                          |
| ------------------------------ | ---------------------------------------------------------------- |
| `Crypt::decryptString($value)` | Ontsleutelt als string                                           |
| `Crypt::decrypt($value)`       | Ontsleutelt en deserialiseert (geschikt voor arrays en objecten) |

***

## Modelcasts

Met de `encrypted`-cast op een Eloquent-model kun je attributen automatisch laten versleutelen en ontsleutelen.

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

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected function casts(): array
    {
        return [
            'secret_note'    => 'encrypted',           // Versleuteling van strings
            'profile_data'   => 'encrypted:array',     // Array versleuteld opslaan
            'preferences'    => 'encrypted:collection',// Collectie versleuteld opslaan
            'metadata'       => 'encrypted:object',    // Object versleuteld opslaan
            'settings'       => 'encrypted:json',      // Als JSON versleuteld opslaan
        ];
    }
}
```

Met een geconfigureerde cast wordt bij het toewijzen en ophalen van waarden op het model automatisch versleuteld en ontsleuteld.

```php theme={null}
// Wordt automatisch versleuteld opgeslagen in de DB
$user->secret_note = 'Geheime notitie';
$user->save();

// Wordt automatisch ontsleuteld opgehaald
echo $user->secret_note; // 'Geheime notitie'
```

<Info>
  De `encrypted:*`-casts gebruiken intern `Crypt::encrypt` en `Crypt::decrypt`.
  Als kolomtype in de database raden we `text` of `longText` aan.
</Info>

***

## Praktijkvoorbeeld: persoonsgegevens versleuteld opslaan

Een typisch patroon om persoonsgegevens (burgerservicenummers, creditcardnummers, enz.) veilig in de database op te slaan.

### Migratie

```php theme={null}
Schema::create('profiles', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained();
    $table->text('my_number')->nullable();     // Versleutelde waarden opslaan 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'],
        ]);

        // Het model versleutelt automatisch bij het opslaan
        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;

        // Het model ontsleutelt automatisch bij het teruggeven
        return view('profile.show', ['profile' => $profile]);
    }
}
```

***

## Samenvatting

| Wat je wilt doen                         | Methode                                       |
| ---------------------------------------- | --------------------------------------------- |
| De APP\_KEY genereren                    | `php artisan key:generate`                    |
| Een string versleutelen                  | `Crypt::encryptString($value)`                |
| Een string ontsleutelen                  | `Crypt::decryptString($value)`                |
| Een array of object versleutelen         | `Crypt::encrypt($value)`                      |
| Modelattributen automatisch versleutelen | De cast `'column' => 'encrypted'`             |
| Sleutelrotatie                           | Oude sleutels opsommen in `APP_PREVIOUS_KEYS` |

## Volgende stappen

<Columns cols={2}>
  <Card title="Hashing" icon="lock" href="/nl/hashing">
    Leer hoe je wachtwoorden veilig hasht en verifieert.
  </Card>

  <Card title="Autorisatie" icon="shield" href="/nl/authorization">
    Uitleg over toegangscontrole met policies en gates.
  </Card>
</Columns>


## Related topics

- [Redis](/nl/redis.md)
- [Deployment](/nl/deployment.md)
- [Contracts](/nl/contracts.md)
- [Facades](/nl/facades.md)
