Laravel AT Protocol Client (alpha & unstable)
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

Consolidate crypto system to use phpseclib3 + firebase/php-jwt

+52 -44
-3
composer.json
··· 22 22 "illuminate/support": "^11.0|^12.0", 23 23 "illuminate/http": "^11.0|^12.0", 24 24 "guzzlehttp/guzzle": "^7.0", 25 - "web-token/jwt-core": "^3.0", 26 - "web-token/jwt-signature": "^3.0", 27 - "web-token/jwt-key-mgmt": "^3.0", 28 25 "phpseclib/phpseclib": "^3.0", 29 26 "firebase/php-jwt": "^6.0", 30 27 "socialdept/atp-schema": "^0.2",
+15 -31
src/Auth/DPoPKeyManager.php
··· 2 2 3 3 namespace SocialDept\AtpClient\Auth; 4 4 5 - use Jose\Component\Core\AlgorithmManager; 6 - use Jose\Component\Core\JWK; 7 - use Jose\Component\KeyManagement\JWKFactory; 8 - use Jose\Component\Signature\Algorithm\ES256; 9 - use Jose\Component\Signature\JWSBuilder; 10 - use Jose\Component\Signature\Serializer\CompactSerializer; 5 + use Firebase\JWT\JWT; 6 + use phpseclib3\Crypt\EC; 11 7 use SocialDept\AtpClient\Contracts\KeyStore; 12 8 use SocialDept\AtpClient\Data\DPoPKey; 13 9 14 10 class DPoPKeyManager 15 11 { 16 - protected AlgorithmManager $algorithmManager; 17 - 18 - protected JWSBuilder $jwsBuilder; 19 - 20 12 public function __construct( 21 13 protected KeyStore $keyStore 22 - ) { 23 - $this->algorithmManager = new AlgorithmManager([new ES256()]); 24 - $this->jwsBuilder = new JWSBuilder($this->algorithmManager); 25 - } 14 + ) {} 26 15 27 16 /** 28 17 * Generate new ES256 key pair ··· 30 19 public function generateKey(string $sessionId): DPoPKey 31 20 { 32 21 // Generate P-256 elliptic curve key pair 33 - $privateKey = JWKFactory::createECKey('P-256', [ 34 - 'use' => 'sig', 35 - 'alg' => 'ES256', 36 - ]); 37 - 38 - $publicKey = $privateKey->toPublic(); 22 + $privateKey = EC::createKey('secp256r1'); 23 + $publicKey = $privateKey->getPublicKey(); 39 24 $keyId = $this->generateKeyId($publicKey); 40 25 41 26 $dpopKey = new DPoPKey($privateKey, $publicKey, $keyId); ··· 77 62 'jwk' => $key->getPublicJwk(), 78 63 ]; 79 64 80 - $jws = $this->jwsBuilder 81 - ->create() 82 - ->withPayload(json_encode($payload)) 83 - ->addSignature($key->privateKey, $header) 84 - ->build(); 85 - 86 - $serializer = new CompactSerializer(); 87 - 88 - return $serializer->serialize($jws, 0); 65 + return JWT::encode( 66 + payload: $payload, 67 + key: $key->toPEM(), 68 + alg: 'ES256', 69 + head: $header 70 + ); 89 71 } 90 72 91 73 /** ··· 99 81 /** 100 82 * Generate key ID from public key 101 83 */ 102 - protected function generateKeyId(JWK $publicKey): string 84 + protected function generateKeyId($publicKey): string 103 85 { 104 - return hash('sha256', json_encode($publicKey->jsonSerialize())); 86 + $jwk = $publicKey->toString('JWK'); 87 + 88 + return hash('sha256', $jwk); 105 89 } 106 90 }
+29 -5
src/Data/DPoPKey.php
··· 2 2 3 3 namespace SocialDept\AtpClient\Data; 4 4 5 - use Jose\Component\Core\JWK; 5 + use phpseclib3\Crypt\Common\PrivateKey; 6 + use phpseclib3\Crypt\Common\PublicKey; 6 7 7 8 class DPoPKey 8 9 { 9 10 public function __construct( 10 - public readonly JWK $privateKey, 11 - public readonly JWK $publicKey, 11 + public readonly PrivateKey $privateKey, 12 + public readonly PublicKey $publicKey, 12 13 public readonly string $keyId, 13 14 ) {} 14 15 15 16 public function getPublicJwk(): array 16 17 { 17 - return $this->publicKey->jsonSerialize(); 18 + $jwk = $this->publicKey->toString('JWK'); 19 + 20 + return array_merge( 21 + json_decode($jwk, true), 22 + [ 23 + 'alg' => 'ES256', 24 + 'use' => 'sig', 25 + 'kid' => $this->keyId, 26 + ] 27 + ); 18 28 } 19 29 20 30 public function getPrivateJwk(): array 21 31 { 22 - return $this->privateKey->jsonSerialize(); 32 + $jwk = $this->privateKey->toString('JWK'); 33 + 34 + return array_merge( 35 + json_decode($jwk, true), 36 + [ 37 + 'alg' => 'ES256', 38 + 'use' => 'sig', 39 + 'kid' => $this->keyId, 40 + ] 41 + ); 42 + } 43 + 44 + public function toPEM(): string 45 + { 46 + return $this->privateKey->toString('PKCS8'); 23 47 } 24 48 }
+8 -5
src/Storage/EncryptedFileKeyStore.php
··· 3 3 namespace SocialDept\AtpClient\Storage; 4 4 5 5 use Illuminate\Contracts\Encryption\Encrypter; 6 - use Jose\Component\Core\JWK; 6 + use phpseclib3\Crypt\PublicKeyLoader; 7 7 use SocialDept\AtpClient\Contracts\KeyStore; 8 8 use SocialDept\AtpClient\Data\DPoPKey; 9 9 ··· 23 23 public function store(string $sessionId, DPoPKey $key): void 24 24 { 25 25 $data = [ 26 - 'privateKey' => $key->getPrivateJwk(), 27 - 'publicKey' => $key->getPublicJwk(), 26 + 'privateKey' => $key->privateKey->toString('PKCS8'), 27 + 'publicKey' => $key->publicKey->toString('PKCS8'), 28 28 'keyId' => $key->keyId, 29 29 ]; 30 30 ··· 47 47 $encrypted = file_get_contents($path); 48 48 $data = $this->encrypter->decrypt($encrypted); 49 49 50 + $privateKey = PublicKeyLoader::load($data['privateKey']); 51 + $publicKey = PublicKeyLoader::load($data['publicKey']); 52 + 50 53 return new DPoPKey( 51 - privateKey: JWK::createFromJson(json_encode($data['privateKey'])), 52 - publicKey: JWK::createFromJson(json_encode($data['publicKey'])), 54 + privateKey: $privateKey, 55 + publicKey: $publicKey, 53 56 keyId: $data['keyId'], 54 57 ); 55 58 }