> ## 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 加密

> Laravel Bluesky 套件的 Crypto 模組。說明 P-256 / secp256k1 金鑰對、DID 金鑰、JWT、DPoP、簽章格式轉換。

<Warning>
  Crypto 屬於進階的內部實作。一般貼文、feed 取得、通知等操作不需使用。若要建置 AT Protocol 的低階簽章驗證或 OAuth 實作時再參考。
</Warning>

## AT Protocol 中的加密概觀

AT Protocol 為實現去中心化社群網路，全面採用橢圓曲線密碼（ECC）。主要用途如下。

```mermaid theme={null}
graph TD
    A["金鑰對<br>(P-256 / secp256k1)"] --> B["以私鑰簽章"]
    A --> C["將公鑰編碼為 did:key"]
    B --> D["DPoP token (OAuth)"]
    B --> E["Commit 簽章（儲存庫）"]
    B --> F["Label 簽章（Labeler）"]
    C --> G["註冊至 DID Document"]
    G --> H["以公鑰驗證簽章"]
```

| 曲線                | 演算法    | 主要用途                         |
| ----------------- | ------ | ---------------------------- |
| secp256r1 (P-256) | ES256  | OAuth（DPoP、Client Assertion） |
| secp256k1 (K256)  | ES256K | Feed Generator、Labeler 的簽章驗證 |

***

## 金鑰對類別

### AbstractKeypair

`AbstractKeypair` 為 P256 / K256 共用的基礎類別。內部使用 [phpseclib3](https://phpseclib.com/)。

```php theme={null}
// 產生新的金鑰對
$keypair = P256::create();
$keypair = K256::create();

// 從 URL-safe Base64 編碼的私鑰載入
$keypair = P256::load($base64PrivateKey);

// 以 PEM 格式取得
$privatePem = $keypair->privatePEM();
$publicPem  = $keypair->publicPEM();

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

### P256 (secp256r1)

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

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

用於 OAuth（DPoP / Client Assertion）。`OAuthKey` 繼承 P256，並從 `config('bluesky.oauth.private_key')` 載入私鑰。

也提供產生新 OAuth 私鑰的 Artisan 指令。

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

### K256 (secp256k1)

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

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

用於 Feed Generator 與 Labeler 的認證。Bluesky 的 PDS / Relay 會以此曲線驗證簽章。

***

## DidKey

`DidKey` 類別將公鑰編碼 / 解碼為 `did:key` 格式。

### 什麼是 did:key 格式

AT Protocol 中公鑰以 `did:key:z...` 字串表達。這是在公鑰上附加曲線識別碼後，以 Base58btc 進行 multibase 編碼的結果。

```mermaid theme={null}
graph LR
    A["公鑰 (PEM)"] --> B["曲線識別碼 + 壓縮公鑰"]
    B --> C["Base58btc 編碼"]
    C --> D["did:key:z..."]
```

### 將公鑰編碼為 did:key

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

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

// 轉換為 did:key 格式
$didKey = DidKey::format($publicPem);
// => "did:key:zQ3s..."
```

### 從 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()
);

// 從 DID Document 的 publicKey (multibase) 產生 phpseclib3 的公鑰物件
$publicKey = DidKey::parse($didDoc->publicKey());
```

***

## JsonWebToken (JWT)

`JsonWebToken` 類別提供 JWT 的編碼 / 解碼。

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

// 產生 JWT（以私鑰 PEM 簽章）
$token = JsonWebToken::encode(
    payload: ['iss' => 'did:plc:***', 'aud' => 'https://bsky.social', 'exp' => time() + 60],
    key: $privatePem,
    alg: 'ES256',
);

// 解碼 JWT（不驗證簽章）
$payload = JsonWebToken::decode($token);
```

***

## DPoP (Demonstrated Proof of Possession)

DPoP 是將 OAuth access token 綁定至特定 client 金鑰對的安全機制，可預防 token 重放攻擊。

```mermaid theme={null}
sequenceDiagram
    participant App as Laravel 應用程式
    participant AS as Authorization Server
    participant RS as Resource Server

    App->>AS: PAR 請求 (+ DPoP header)
    AS-->>App: request_uri
    App->>AS: token 請求 (+ DPoP header)
    AS-->>App: access token (DPoP bound)
    App->>RS: API 請求 (+ DPoP header + ath)
    RS-->>App: 回應
```

`DPoP` 類別為內部使用，通常無需直接呼叫。`OAuthAgent` middleware 會自動附加 DPoP header。

```php theme={null}
// 產生 DPoP proof（用於 OAuth token 請求）
$proof = DPoP::authProof(
    jwk: $jsonWebKey,
    url: 'https://bsky.social/oauth/token',
    method: 'POST',
    nonce: $nonce,
);

// 產生 DPoP proof（用於 API 請求，包含 ath）
$proof = DPoP::apiProof(
    jwk: $jsonWebKey,
    url: 'https://api.bsky.app/xrpc/...',
    method: 'GET',
    token: $accessToken,
    nonce: $nonce,
);
```

***

## Signature（簽章格式轉換）

AT Protocol 採用 64 位元組的緊湊簽章格式，但 phpseclib3 回傳的是 ASN.1 DER 格式。`Signature` 類別負責此轉換。

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

// ASN.1 DER → 緊湊格式（64 位元組）
$compact = Signature::toCompact($derSignature);

// 緊湊格式 → ASN.1 DER
$der = Signature::fromCompact($compactSignature);
```

***

## JsonWebKey

`JsonWebKey` 是代表 JWK (JSON Web Key) 的類別。用於產生 DPoP proof。

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

// 從金鑰對產生 JWK
$jwk = $keypair->toJWK();

// 或直接實體化
$jwk = JsonWebKey::load(['kty' => 'EC', 'crv' => 'P-256', ...]);
```

***

## OAuthKey

`OAuthKey` 是繼承自 P256 的 OAuth 專用金鑰類別，使用 `config('bluesky.oauth.private_key')` 的值作為私鑰。

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

// 從設定載入私鑰
$oauthKey = OAuthKey::load();

// 用於 Client Assertion JWT 的簽章
$jwk = $oauthKey->toJWK();
```

通常會在 Bluesky Socialite 內部自動處理。

***

## 參考連結

* [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

- [加密（Encryption）](/zh-TW/encryption.md)
- [設定](/zh-TW/configuration.md)
- [教學 - Laravel Console Starter](/zh-TW/packages/laravel-console-starter/tutorial.md)
- [Redis](/zh-TW/redis.md)
- [Core — AT Protocol 核心操作](/zh-TW/packages/laravel-bluesky/core.md)
