<?php

namespace App\Services\Wireguard;

/**
 * A WireGuard keypair. Generated in PHP via libsodium rather than by shelling
 * out to `wg genkey`: the console runs in the web container, which has no
 * wg0 interface, and this keeps key generation testable.
 *
 * WireGuard keys are Curve25519. The private key is 32 random bytes with the
 * standard clamping applied; the public key is its scalar multiplication with
 * the curve base point — exactly what `wg pubkey` computes.
 */
final readonly class Keypair
{
    public function __construct(public string $privateKey, public string $publicKey) {}

    public static function generate(): self
    {
        $bytes = random_bytes(32);
        $bytes[0] = chr(ord($bytes[0]) & 248);
        $bytes[31] = chr((ord($bytes[31]) & 127) | 64);

        return new self(
            privateKey: base64_encode($bytes),
            publicKey: base64_encode(sodium_crypto_scalarmult_base($bytes)),
        );
    }

    /** A base64-encoded 32-byte key, the only shape WireGuard accepts. */
    public static function isValidKey(string $key): bool
    {
        $raw = base64_decode($key, true);

        return $raw !== false && strlen($raw) === 32 && base64_encode($raw) === $key;
    }
}
