Passed
Push — master ( 52d862...8362e5 )
by Pol
01:53
created

WopiProofValidator::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
/**
4
 * For the full copyright and license information, please view
5
 * the LICENSE file that was distributed with this source code.
6
 */
7
8
declare(strict_types=1);
9
10
namespace ChampsLibres\WopiLib\Service;
11
12
use ChampsLibres\WopiLib\Discovery\WopiDiscoveryInterface;
13
use ChampsLibres\WopiLib\Service\Contract\WopiProofValidatorInterface;
14
use phpseclib3\Crypt\PublicKeyLoader;
15
use Psr\Http\Message\RequestInterface;
16
use Throwable;
17
18
use function strlen;
19
use const OPENSSL_ALGO_SHA256;
20
21
final class WopiProofValidator implements WopiProofValidatorInterface
22
{
23
    private WopiDiscoveryInterface $wopiDiscovery;
24
25 2
    public function __construct(WopiDiscoveryInterface $wopiDiscovery)
26
    {
27 2
        $this->wopiDiscovery = $wopiDiscovery;
28 2
    }
29
30
    public function __constructX(string $accessToken, string $url, string $timestamp)
31
    {
32
        $this->expected = sprintf(
0 ignored issues
show
Bug Best Practice introduced by
The property expected does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
33
            '%s%s%s%s%s%s',
34
            pack('N', strlen($accessToken)),
35
            $accessToken,
36
            pack('N', strlen($url)),
37
            strtoupper($url),
38
            pack('N', 8),
39
            pack('J', $timestamp)
40
        );
41
    }
42
43 1
    public function isValid(RequestInterface $request): bool
44
    {
45 1
        $xWopiProof = $request->getHeaderLine('X-WOPI-Proof');
46 1
        $xWopiProofOld = $request->getHeaderLine('X-WOPI-ProofOld');
47 1
        $timestamp = $request->getHeaderLine('X-WOPI-Timestamp');
48
49 1
        $key = $this->wopiDiscovery->getPublicKey();
50 1
        $keyOld = $this->wopiDiscovery->getPublicKeyOld();
51
52 1
        $url = (string) $request->getUri();
53 1
        $params = [];
54 1
        parse_str($request->getUri()->getQuery(), $params);
55
56 1
        $expected = sprintf(
57 1
            '%s%s%s%s%s%s',
58 1
            pack('N', strlen($params['access_token'])),
59 1
            $params['access_token'],
60 1
            pack('N', strlen($url)),
61 1
            strtoupper($url),
62 1
            pack('N', 8),
63 1
            pack('J', $timestamp)
64
        );
65
66 1
        return $this->verify($expected, $xWopiProof, $key) || $this->verify($expected, $xWopiProofOld, $key) || $this->verify($expected, $xWopiProof, $keyOld);
67
    }
68
69
    /**
70
     * @param string $key The key in MSBLOB format
71
     */
72 1
    private function verify(string $expected, string $proof, string $key): bool
73
    {
74
        try {
75 1
            $key = PublicKeyLoader::loadPublicKey($key);
76
        } catch (Throwable $e) {
77
            return false;
78
        }
79
80 1
        return 1 === openssl_verify(
81
            $expected,
82 1
            base64_decode($proof, true),
83
            $key,
84 1
            OPENSSL_ALGO_SHA256
85
        );
86
    }
87
}
88