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

# Crypto — AT Protocol-cryptografie

> De Crypto-module van het Laravel Bluesky-pakket. Uitleg over P-256/secp256k1-sleutelparen, DID-keys, JWT, DPoP en handtekeningconversie.

<Warning>
  Crypto is een geavanceerde interne implementatie. Voor gewone taken zoals posten, feeds ophalen en notificaties heb je deze niet nodig. Raadpleeg dit onderdeel als je low-level handtekeningverificatie voor het AT Protocol of een eigen OAuth-implementatie bouwt.
</Warning>

## Overzicht van cryptografie in het AT Protocol

Het AT Protocol gebruikt overal elliptische-krommecryptografie (ECC) om een gedecentraliseerd sociaal netwerk mogelijk te maken. De belangrijkste toepassingen zijn:

```mermaid theme={null}
graph TD
    A["Sleutelpaar<br>(P-256 / secp256k1)"] --> B["Ondertekenen met de privésleutel"]
    A --> C["Publieke sleutel encoden als did:key"]
    B --> D["DPoP-tokens (OAuth)"]
    B --> E["Commit-handtekeningen (repository)"]
    B --> F["Labelhandtekeningen (Labeler)"]
    C --> G["Registratie in het DID Document"]
    G --> H["Handtekeningen verifiëren met de publieke sleutel"]
```

| Kromme            | Algoritme | Belangrijkste toepassing                               |
| ----------------- | --------- | ------------------------------------------------------ |
| secp256r1 (P-256) | ES256     | OAuth (DPoP, Client Assertion)                         |
| secp256k1 (K256)  | ES256K    | Handtekeningverificatie voor Feed Generator en Labeler |

***

## Sleutelpaarklassen

### AbstractKeypair

`AbstractKeypair` is de gemeenschappelijke basisklasse voor P256/K256. Intern wordt [phpseclib3](https://phpseclib.com/) gebruikt.

```php theme={null}
// Een nieuw sleutelpaar genereren
$keypair = P256::create();
$keypair = K256::create();

// Laden uit een URL-safe Base64-geëncodeerde privésleutel
$keypair = P256::load($base64PrivateKey);

// Ophalen in PEM-formaat
$privatePem = $keypair->privatePEM();
$publicPem  = $keypair->publicPEM();

// Converteren naar JWK (JSON Web Key)
$jwk = $keypair->toJWK();
```

### P256 (secp256r1)

```php theme={null}
use Revolution\Bluesky\Crypto\P256;

$keypair = P256::create();
```

Wordt gebruikt voor OAuth (DPoP / Client Assertion). `OAuthKey` erft van P256 en laadt de privésleutel uit `config('bluesky.oauth.private_key')`.

Er is ook een Artisan-command om een nieuwe OAuth-privésleutel te genereren.

```bash theme={null}
php artisan bluesky:new-private-key
```

### K256 (secp256k1)

```php theme={null}
use Revolution\Bluesky\Crypto\K256;

$keypair = K256::create();
```

Wordt gebruikt voor authenticatie van Feed Generators en Labelers. De PDS/Relay van Bluesky verifieert handtekeningen met deze kromme.

***

## DidKey

De `DidKey`-klasse encodeert en decodeert publieke sleutels in het `did:key`-formaat.

### Wat is het did:key-formaat?

In het AT Protocol wordt een publieke sleutel weergegeven als een string van de vorm `did:key:z...`. Dit is de publieke sleutel met een kromme-identifier, multibase-geëncodeerd met Base58btc.

```mermaid theme={null}
graph LR
    A["Publieke sleutel (PEM)"] --> B["Kromme-identifier + gecomprimeerde publieke sleutel"]
    B --> C["Base58btc-encoding"]
    C --> D["did:key:z..."]
```

### Een publieke sleutel encoden als did:key

```php theme={null}
use Revolution\Bluesky\Crypto\DidKey;
use Revolution\Bluesky\Crypto\K256;

$keypair = K256::create();
$publicPem = $keypair->publicPEM();

// Converteren naar did:key-formaat
$didKey = DidKey::format($publicPem);
// => "did:key:zQ3s..."
```

### Een publieke sleutel parsen uit een DID Document

```php theme={null}
use Revolution\Bluesky\Crypto\DidKey;
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Support\DidDocument;

$didDoc = DidDocument::make(
    Bluesky::identity()->resolveDID('did:plc:***')->json()
);

// Een phpseclib3-publiekesleutelobject maken uit de publicKey (multibase) van het DID Document
$publicKey = DidKey::parse($didDoc->publicKey());
```

***

## JsonWebToken (JWT)

De `JsonWebToken`-klasse biedt JWT-encoding en -decoding.

```php theme={null}
use Revolution\Bluesky\Crypto\JsonWebToken;

// Een JWT genereren (ondertekend met de privésleutel in PEM)
$token = JsonWebToken::encode(
    payload: ['iss' => 'did:plc:***', 'aud' => 'https://bsky.social', 'exp' => time() + 60],
    key: $privatePem,
    alg: 'ES256',
);

// Een JWT decoden (zonder handtekeningverificatie)
$payload = JsonWebToken::decode($token);
```

***

## DPoP (Demonstrated Proof of Possession)

DPoP is een beveiligingsmechanisme dat een OAuth-accesstoken bindt aan een specifiek client-sleutelpaar. Het voorkomt replay-aanvallen met tokens.

```mermaid theme={null}
sequenceDiagram
    participant App as Laravel-app
    participant AS as Authorization Server
    participant RS as Resource Server

    App->>AS: PAR-request (+ DPoP-header)
    AS-->>App: request_uri
    App->>AS: Tokenrequest (+ DPoP-header)
    AS-->>App: Accesstoken (DPoP bound)
    App->>RS: API-request (+ DPoP-header + ath)
    RS-->>App: Response
```

De `DPoP`-klasse wordt intern gebruikt; normaal hoef je deze niet rechtstreeks aan te roepen. De `OAuthAgent`-middleware voegt automatisch DPoP-headers toe.

```php theme={null}
// Een DPoP-proof genereren (voor OAuth-tokenrequests)
$proof = DPoP::authProof(
    jwk: $jsonWebKey,
    url: 'https://bsky.social/oauth/token',
    method: 'POST',
    nonce: $nonce,
);

// Een DPoP-proof genereren (voor API-requests, inclusief ath)
$proof = DPoP::apiProof(
    jwk: $jsonWebKey,
    url: 'https://api.bsky.app/xrpc/...',
    method: 'GET',
    token: $accessToken,
    nonce: $nonce,
);
```

***

## Signature (conversie van handtekeningformaten)

Het AT Protocol gebruikt een compact handtekeningformaat van 64 bytes, maar phpseclib3 geeft het ASN.1 DER-formaat terug. De `Signature`-klasse verzorgt deze conversie.

```php theme={null}
use Revolution\Bluesky\Crypto\Signature;

// ASN.1 DER → compact (64 bytes)
$compact = Signature::toCompact($derSignature);

// Compact → ASN.1 DER
$der = Signature::fromCompact($compactSignature);
```

***

## JsonWebKey

`JsonWebKey` is een klasse die een JWK (JSON Web Key) representeert. Deze wordt gebruikt bij het genereren van DPoP-proofs.

```php theme={null}
use Revolution\Bluesky\Crypto\JsonWebKey;

// Een JWK genereren uit een sleutelpaar
$jwk = $keypair->toJWK();

// Of rechtstreeks instantiëren
$jwk = JsonWebKey::load(['kty' => 'EC', 'crv' => 'P-256', ...]);
```

***

## OAuthKey

`OAuthKey` is een OAuth-specifieke sleutelklasse die erft van P256 en de waarde van `config('bluesky.oauth.private_key')` als privésleutel gebruikt.

```php theme={null}
use Revolution\Bluesky\Crypto\OAuthKey;

// De privésleutel laden uit de configuratie
$oauthKey = OAuthKey::load();

// Wordt gebruikt voor het ondertekenen van Client Assertion-JWT's
$jwk = $oauthKey->toJWK();
```

Normaal wordt dit automatisch afgehandeld binnen Bluesky Socialite.

***

## Referenties

* [AT Protocol: Identity](https://atproto.com/guides/identity)
* [AT Protocol: Cryptography spec](https://atproto.com/specs/cryptography)
* [phpseclib3](https://phpseclib.com/)

<Info>
  Source: [src/Crypto/](https://github.com/invokable/laravel-bluesky/tree/main/src/Crypto)
</Info>


## Related topics

- [Core — AT Protocol-kernbewerkingen](/nl/packages/laravel-bluesky/core.md)
- [Laravel LSP — IDE-functionaliteit via het Language Server Protocol](/nl/blog/laravel-lsp-introduction.md)
- [Tutorial - Laravel Console Starter](/nl/packages/laravel-console-starter/tutorial.md)
- [Laravel AI SDK](/nl/ai-sdk.md)
- [Bottutorial - Laravel Bluesky](/nl/packages/laravel-bluesky/bot-tutorial.md)
