secretKey = sodium_crypto_sign_secretkey($pair); $this->signature = new PackageSignature(base64_encode(sodium_crypto_sign_publickey($pair))); $this->zip = (string) tempnam(sys_get_temp_dir(), 'lit-mcp-sig'); file_put_contents($this->zip, 'zip bytes'); } protected function tearDown(): void { unlink($this->zip); } public function testASignatureOverNameAndContentVerifies(): void { $signature = $this->sign('wp-lit-mcp-1.0.0.zip'); self::assertTrue($this->signature->verifies('wp-lit-mcp-1.0.0.zip', $this->zip, $signature)); } public function testAnotherAssetNameDoesNotVerify(): void { $signature = $this->sign('wp-lit-mcp-1.0.0.zip'); self::assertFalse($this->signature->verifies('wp-lit-mcp-1.0.1.zip', $this->zip, $signature)); } public function testChangedContentDoesNotVerify(): void { $signature = $this->sign('x.zip'); file_put_contents($this->zip, 'changed bytes'); self::assertFalse($this->signature->verifies('x.zip', $this->zip, $signature)); } public function testAnotherKeyDoesNotVerify(): void { $foreign = new PackageSignature(base64_encode(sodium_crypto_sign_publickey(sodium_crypto_sign_keypair()))); self::assertFalse($foreign->verifies('x.zip', $this->zip, $this->sign('x.zip'))); } /** @dataProvider malformedInput */ public function testMalformedInputFailsClosed(string $signature, string $publicKey, string $zipPath): void { $subject = new PackageSignature($publicKey === 'real' ? $this->realKey() : $publicKey); self::assertFalse($subject->verifies('x.zip', $zipPath === 'zip' ? $this->zip : $zipPath, $signature)); } /** @return array */ public static function malformedInput(): array { return [ 'signature is no base64' => ['not base64 !!', 'real', 'zip'], 'signature is empty' => ['', 'real', 'zip'], 'signature has the wrong length' => [base64_encode('short'), 'real', 'zip'], 'no key configured' => ['AAAA', '', 'zip'], 'key has the wrong length' => ['AAAA', base64_encode('short'), 'zip'], 'file is missing' => ['AAAA', 'real', '/nonexistent/x.zip'], ]; } private function sign(string $assetName): string { $message = PackageSignature::message($assetName, $this->zip); return base64_encode(sodium_crypto_sign_detached($message, $this->secretKey)); } private function realKey(): string { return base64_encode(sodium_crypto_sign_publickey(sodium_crypto_sign_keypair())); } }