Skip to content

Commit

Permalink
Server - Signature - Support algorithm field for verification
Browse files Browse the repository at this point in the history
  • Loading branch information
landrok committed Nov 6, 2020
1 parent 8b404c5 commit 31110a1
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 11 deletions.
33 changes: 22 additions & 11 deletions src/ActivityPhp/Server/Http/HttpSignature.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,22 @@ class HttpSignature
(:[\d]+)?
([\w\-\.#\/@]+)
)",
(algorithm="(?P<algorithm>[\w\s-]+)",)?
(headers="\(request-target\) (?P<headers>[\w\s]+)",)?
signature="(?P<signature>[\w+\/]+={0,2})"
/x';
/x';

/**
* Allowed keys when splitting signature
*
* @var array
*/
private $allowedKeys = [
'keyId',
'algorithm', // optional
'headers', // optional
'signature',
];

/**
* @var \ActivityPhp\Server
Expand Down Expand Up @@ -67,7 +80,7 @@ public function verify(Request $request)

// Split it into its parts (keyId, headers and signature)
$parts = $this->splitSignature($signature);
if (!$parts) {
if (!count($parts)) {
return false;
}

Expand Down Expand Up @@ -102,37 +115,35 @@ public function verify(Request $request)

/**
* Split HTTP signature into its parts (keyId, headers and signature)
*
* @param s tring $signature
* @return bool|array
*/
private function splitSignature(string $signature)
{
public function splitSignature(string $signature): array
{
if (!preg_match(self::SIGNATURE_PATTERN, $signature, $matches)) {
$this->server->logger()->info(
'Signature pattern failed',
[$signature]
);

return false;
return [];
}

// Headers are optional
if (!isset($matches['headers']) || $matches['headers'] == '') {
$matches['headers'] = 'date';
}

return $matches;
return array_filter($matches, function($key) {
return !is_int($key) && in_array($key, $this->allowedKeys);
}, ARRAY_FILTER_USE_KEY );
}

/**
* Get plain text that has been originally signed
*
* @param array $headers HTTP header keys
* @param \Symfony\Component\HttpFoundation\Request $request
* @return string
*/
private function getPlainText(array $headers, Request $request)
private function getPlainText(array $headers, Request $request): string
{
$strings = [];
$strings[] = sprintf(
Expand Down
42 changes: 42 additions & 0 deletions tests/ActivityPhp/Server/HttpSignatureTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,48 @@ public function testValidSignature()
);
}

/**
* Check that the pattern used splitting signature
* is working as intended
*/
public function testSplittingSignature()
{
$server = new Server([
'logger' => [
'driver' => '\Psr\Log\NullLogger'
],
'cache' => [
'enabled' => false,
]
]);

$verifier = new HttpSignature($server);

// Split a signature with headers but no algorithm
$signature = 'keyId="http://localhost:8001/accounts/bob#main-key",headers="(request-target) host date",signature="FbVtmZhMWrfbqQpXf1v86+ie/fL8Ng4O67PePKvxChnUtV7J8N6lndQcNfXcDuKDJ4Nda6gKUQabAF2JK2qeYPNZNJ1AdAa5Lak3hQd+rAbdMJdvQpzGhAaSWK6atqOTH9v2CWdjAQbzvY0nOfGiw3ymtDSvTL0pVlIvq116uMtci0WOHeIbuBSyzM23liJmBomlm4EeB3/V1BVWY2MwaQ1cHVzxR7epP6XYts3C1KbZrdMKxhlWJFLdbLy0YGu5HRkYZepAh2q2NriSikNg8YTJ67owgQv/LqhFKnObgZU6np54fBMSpg7eAdWSIbhhg1a/WHtzFicc9cgoWMRhEg=="';

$split = $verifier->splitSignature($signature);

$this->assertEquals($split, [
'keyId' => 'http://localhost:8001/accounts/bob#main-key',
'algorithm' => '',
'headers' => ' host date',
'signature' => 'FbVtmZhMWrfbqQpXf1v86+ie/fL8Ng4O67PePKvxChnUtV7J8N6lndQcNfXcDuKDJ4Nda6gKUQabAF2JK2qeYPNZNJ1AdAa5Lak3hQd+rAbdMJdvQpzGhAaSWK6atqOTH9v2CWdjAQbzvY0nOfGiw3ymtDSvTL0pVlIvq116uMtci0WOHeIbuBSyzM23liJmBomlm4EeB3/V1BVWY2MwaQ1cHVzxR7epP6XYts3C1KbZrdMKxhlWJFLdbLy0YGu5HRkYZepAh2q2NriSikNg8YTJ67owgQv/LqhFKnObgZU6np54fBMSpg7eAdWSIbhhg1a/WHtzFicc9cgoWMRhEg==',
]);

// Split a signature with headers and algorithm
$signature = 'keyId="http://localhost:8001/accounts/bob#main-key",algorithm="rsa-sha256",headers="(request-target) host date",signature="FbVtmZhMWrfbqQpXf1v86+ie/fL8Ng4O67PePKvxChnUtV7J8N6lndQcNfXcDuKDJ4Nda6gKUQabAF2JK2qeYPNZNJ1AdAa5Lak3hQd+rAbdMJdvQpzGhAaSWK6atqOTH9v2CWdjAQbzvY0nOfGiw3ymtDSvTL0pVlIvq116uMtci0WOHeIbuBSyzM23liJmBomlm4EeB3/V1BVWY2MwaQ1cHVzxR7epP6XYts3C1KbZrdMKxhlWJFLdbLy0YGu5HRkYZepAh2q2NriSikNg8YTJ67owgQv/LqhFKnObgZU6np54fBMSpg7eAdWSIbhhg1a/WHtzFicc9cgoWMRhEg=="';

$split = $verifier->splitSignature($signature);

$this->assertEquals($split, [
'keyId' => 'http://localhost:8001/accounts/bob#main-key',
'algorithm' => 'rsa-sha256',
'headers' => ' host date',
'signature' => 'FbVtmZhMWrfbqQpXf1v86+ie/fL8Ng4O67PePKvxChnUtV7J8N6lndQcNfXcDuKDJ4Nda6gKUQabAF2JK2qeYPNZNJ1AdAa5Lak3hQd+rAbdMJdvQpzGhAaSWK6atqOTH9v2CWdjAQbzvY0nOfGiw3ymtDSvTL0pVlIvq116uMtci0WOHeIbuBSyzM23liJmBomlm4EeB3/V1BVWY2MwaQ1cHVzxR7epP6XYts3C1KbZrdMKxhlWJFLdbLy0YGu5HRkYZepAh2q2NriSikNg8YTJ67owgQv/LqhFKnObgZU6np54fBMSpg7eAdWSIbhhg1a/WHtzFicc9cgoWMRhEg==',
]);
}

/**
* Check that a given request is correctly signed
* With a optionnal headers not specified (fallback on date)
Expand Down

0 comments on commit 31110a1

Please sign in to comment.