pixelfed/app/Util/ActivityPub/Concern/HTTPSignature.php

95 lines
2.7 KiB
PHP
Raw Normal View History

2018-08-26 04:12:21 +00:00
<?php
namespace App\Util\ActivityPub\Concern;
use Zttp\Zttp;
2018-08-28 03:07:36 +00:00
class HTTPSignature
{
2018-08-26 04:12:21 +00:00
protected $localhosts = [
2018-08-28 03:07:36 +00:00
'127.0.0.1', 'localhost', '::1',
2018-08-26 04:12:21 +00:00
];
public $profile;
public $is_url;
public function validateUrl()
{
// If the profile exists, assume its valid
2018-08-28 03:07:36 +00:00
if ($this->is_url === false) {
return true;
2018-08-26 04:12:21 +00:00
}
$url = $this->profile;
2018-08-28 03:07:36 +00:00
2018-08-26 04:12:21 +00:00
try {
2018-08-28 03:07:36 +00:00
$url = filter_var($url, FILTER_VALIDATE_URL);
$parsed = parse_url($url, PHP_URL_HOST);
if (!$parsed || in_array($parsed, $this->localhosts)) {
return false;
}
2018-08-26 04:12:21 +00:00
} catch (Exception $e) {
2018-08-28 03:07:36 +00:00
return false;
2018-08-26 04:12:21 +00:00
}
2018-08-28 03:07:36 +00:00
2018-08-26 04:12:21 +00:00
return true;
}
public function fetchPublicKey($profile, bool $is_url = true)
{
$this->profile = $profile;
$this->is_url = $is_url;
$valid = $this->validateUrl();
2018-08-28 03:07:36 +00:00
if (!$valid) {
throw new \Exception('Invalid URL provided');
2018-08-26 04:12:21 +00:00
}
2018-08-28 03:07:36 +00:00
if ($is_url && isset($profile->public_key) && $profile->public_key) {
return $profile->public_key;
2018-08-26 04:12:21 +00:00
}
try {
2018-08-28 03:07:36 +00:00
$url = $this->profile;
$res = Zttp::timeout(30)->withHeaders([
'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
'User-Agent' => 'PixelFedBot v0.1 - https://pixelfed.org',
2018-08-26 04:12:21 +00:00
])->get($url);
2018-08-28 03:07:36 +00:00
$actor = json_decode($res->getBody(), true);
2018-08-26 04:12:21 +00:00
} catch (Exception $e) {
2018-08-28 03:07:36 +00:00
throw new Exception('Unable to fetch public key');
2018-08-26 04:12:21 +00:00
}
return $actor['publicKey']['publicKeyPem'];
}
public function sendSignedObject($senderProfile, $url, $body)
{
$profile = $senderProfile;
$context = new Context([
2018-08-28 03:07:36 +00:00
'keys' => [$profile->keyId() => $profile->private_key],
2018-08-26 04:12:21 +00:00
'algorithm' => 'rsa-sha256',
2018-08-28 03:07:36 +00:00
'headers' => ['(request-target)', 'Date'],
2018-08-26 04:12:21 +00:00
]);
$handlerStack = GuzzleHttpSignatures::defaultHandlerFromContext($context);
$client = new Client(['handler' => $handlerStack]);
$headers = [
2018-08-28 03:07:36 +00:00
'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
'Date' => date('D, d M Y h:i:s').' GMT',
2018-08-26 04:12:21 +00:00
'Content-Type' => 'application/activity+json',
2018-08-28 03:07:36 +00:00
'User-Agent' => 'PixelFedBot - https://pixelfed.org',
2018-08-26 04:12:21 +00:00
];
2018-08-28 03:07:36 +00:00
2018-08-26 04:12:21 +00:00
$response = $client->post($url, [
'options' => [
'allow_redirects' => false,
2018-08-28 03:07:36 +00:00
'verify' => true,
'timeout' => 30,
2018-08-26 04:12:21 +00:00
],
2018-08-28 03:07:36 +00:00
'headers' => $headers,
'body' => $body,
2018-08-26 04:12:21 +00:00
]);
return $response->getBody();
}
2018-08-28 03:07:36 +00:00
}