38 lines
1.2 KiB
PHP
38 lines
1.2 KiB
PHP
<?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;
|
|
}
|
|
}
|