Crypto es una implementación interna avanzada. No es necesaria para las operaciones habituales como publicar, obtener feeds o notificaciones. Consúltala cuando quieras construir verificaciones de firma o implementaciones de OAuth de bajo nivel del AT Protocol.
Descripción general de la criptografía en AT Protocol
Para construir una red social descentralizada, AT Protocol adopta ampliamente la criptografía de curva elíptica (ECC). Sus usos principales son los siguientes.
| Curva | Algoritmo | Uso principal |
|---|
| secp256r1 (P-256) | ES256 | OAuth (DPoP, Client Assertion) |
| secp256k1 (K256) | ES256K | Verificación de firmas de Feed Generator y Labeler |
Clases de par de claves
AbstractKeypair
AbstractKeypair es la clase base común para P256 / K256. Internamente utiliza phpseclib3.
// Genera un nuevo par de claves
$keypair = P256::create();
$keypair = K256::create();
// Carga desde una clave privada codificada en Base64 URL-safe
$keypair = P256::load($base64PrivateKey);
// Obtén en formato PEM
$privatePem = $keypair->privatePEM();
$publicPem = $keypair->publicPEM();
// Convierte a JWK (JSON Web Key)
$jwk = $keypair->toJWK();
P256 (secp256r1)
use Revolution\Bluesky\Crypto\P256;
$keypair = P256::create();
Se usa en OAuth (DPoP / Client Assertion). OAuthKey hereda de P256 y carga la clave privada desde config('bluesky.oauth.private_key').
También existe un comando Artisan para generar una nueva clave privada OAuth.
php artisan bluesky:new-private-key
K256 (secp256k1)
use Revolution\Bluesky\Crypto\K256;
$keypair = K256::create();
Se usa para la autenticación del Feed Generator y el Labeler. El PDS / Relay de Bluesky verifica las firmas con esta curva.
DidKey
La clase DidKey codifica y decodifica claves públicas al formato did:key.
En AT Protocol, las claves públicas se representan como una cadena did:key:z.... Consiste en un identificador de curva más la clave pública comprimida, codificados en multibase con Base58btc.
Codificar clave pública a did:key
use Revolution\Bluesky\Crypto\DidKey;
use Revolution\Bluesky\Crypto\K256;
$keypair = K256::create();
$publicPem = $keypair->publicPEM();
// Convierte al formato did:key
$didKey = DidKey::format($publicPem);
// => "did:key:zQ3s..."
Parsear la clave pública desde el DID Document
use Revolution\Bluesky\Crypto\DidKey;
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Support\DidDocument;
$didDoc = DidDocument::make(
Bluesky::identity()->resolveDID('did:plc:***')->json()
);
// Genera el objeto de clave pública de phpseclib3 desde el publicKey (multibase) del DID Document
$publicKey = DidKey::parse($didDoc->publicKey());
JsonWebToken (JWT)
La clase JsonWebToken proporciona codificación y decodificación de JWT.
use Revolution\Bluesky\Crypto\JsonWebToken;
// Genera un JWT (firmando con clave privada PEM)
$token = JsonWebToken::encode(
payload: ['iss' => 'did:plc:***', 'aud' => 'https://bsky.social', 'exp' => time() + 60],
key: $privatePem,
alg: 'ES256',
);
// Decodifica un JWT (sin verificar la firma)
$payload = JsonWebToken::decode($token);
DPoP (Demonstrated Proof of Possession)
DPoP es un mecanismo de seguridad que vincula el token de acceso OAuth a un par de claves específico del cliente. Previene ataques de replay del token.
La clase DPoP se usa internamente y normalmente no necesitas invocarla directamente. El middleware de OAuthAgent añade automáticamente la cabecera DPoP.
// Generación de la prueba DPoP (para la petición de token OAuth)
$proof = DPoP::authProof(
jwk: $jsonWebKey,
url: 'https://bsky.social/oauth/token',
method: 'POST',
nonce: $nonce,
);
// Generación de la prueba DPoP (para peticiones API, incluye ath)
$proof = DPoP::apiProof(
jwk: $jsonWebKey,
url: 'https://api.bsky.app/xrpc/...',
method: 'GET',
token: $accessToken,
nonce: $nonce,
);
AT Protocol utiliza un formato de firma compacto de 64 bytes, pero phpseclib3 devuelve el formato ASN.1 DER. La clase Signature se encarga de esta conversión.
use Revolution\Bluesky\Crypto\Signature;
// ASN.1 DER → compacto (64 bytes)
$compact = Signature::toCompact($derSignature);
// Compacto → ASN.1 DER
$der = Signature::fromCompact($compactSignature);
JsonWebKey
JsonWebKey es la clase que representa un JWK (JSON Web Key). Se usa para generar las pruebas DPoP.
use Revolution\Bluesky\Crypto\JsonWebKey;
// Genera un JWK a partir del par de claves
$jwk = $keypair->toJWK();
// O instancia directamente
$jwk = JsonWebKey::load(['kty' => 'EC', 'crv' => 'P-256', ...]);
OAuthKey
OAuthKey es una clase de clave específica de OAuth que hereda de P256 y utiliza el valor de config('bluesky.oauth.private_key') como clave privada.
use Revolution\Bluesky\Crypto\OAuthKey;
// Carga la clave privada desde la configuración
$oauthKey = OAuthKey::load();
// Se usa para firmar el JWT del Client Assertion
$jwk = $oauthKey->toJWK();
Normalmente se gestiona automáticamente dentro de Bluesky Socialite.
Enlaces de referencia