Passed
Push — master ( 34eaf6...149dd5 )
by Charles
02:52
created

ResponseFormatter::checkRequest()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 9
rs 10
c 0
b 0
f 0
cc 3
nc 3
nop 1
1
<?php declare(strict_types=1);
2
3
namespace ncryptf\middleware;
4
5
use Exception;
6
7
use ncryptf\Request;
8
9
use Psr\Http\Message\StreamInterface;
10
use Psr\Http\Message\MessageInterface;
11
use Psr\Http\Message\ResponseInterface;
12
13
use Psr\Http\Server\MiddlewareInterface;
14
use Fig\Http\Message\StatusCodeInterface;
0 ignored issues
show
Bug introduced by
The type Fig\Http\Message\StatusCodeInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
use Psr\Http\Message\ServerRequestInterface;
16
use Psr\Http\Server\RequestHandlerInterface;
17
18
use ncryptf\middleware\EncryptionKeyInterface;
19
20
final class ResponseFormatter implements MiddlewareInterface
21
{
22
    const ENCODING_OPTIONS = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION;
23
24
    /**
25
     * @var EncryptionKeyInterface $key
26
     */
27
    protected $key;
28
29
    /**
30
     * @var array $contentType
31
     */
32
    protected $contentType = [
33
        'application/vnd.25519+json',
34
        'application/vnd.ncryptf+json'
35
    ];
36
37
    /**
38
     * Constructor
39
     * @param EncryptionKeyInterface $key
40
     */
41
    public function __construct(EncryptionKeyInterface $key)
42
    {
43
        $this->key = $key;
44
    }
45
46
    /**
47
     * Processes the request
48
     * @param ServerRequestInterface $request
49
     * @param RequestHandlerInterface $handler
50
     */
51
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
52
    {
53
        if ($this->checkRequest($request)) {
54
            $response = $handler->handle($request);
55
            $version = $request->getAttribute('ncryptf-version');
56
            $publicKey = $request->getAttribute('ncryptf-request-public-key');
57
            $token = $request->getAttribute('ncryptf-token');
58
            if ($version === null || $publicKey === null || $token === null) {
59
                return $response->withStatus(400, 'Unable to encrypt request.');
60
            }
61
62
            if (!($response instanceof MessageInterface)) {
0 ignored issues
show
introduced by
$response is always a sub-type of Psr\Http\Message\MessageInterface.
Loading history...
63
                throw new Exception('Response does not implement MessageInterface.');
64
            }
65
66
            $stream = $response->getBody();
67
            $class = $this->key;
68
            $key = $class::generate();
69
70
            $r = new Request(
71
                $key->getBoxSecretKey(),
72
                $token->signature
73
            );
74
75
            $content = $r->encrypt(
76
                (string)$stream,
77
                $publicKey,
78
                $version,
79
                $version === 2 ? null : \random_bytes(SODIUM_CRYPTO_BOX_NONCEBYTES)
80
            );
81
82
            if ($version === 1) {
83
                $response = $response->withHeader('x-sigpubkey', \base64_encode($token->getSignaturePublicKey()))
84
                    ->withHeader('x-signature', \base64_encode($r->sign((string)$stream)))
85
                    ->withHeader('x-public-key-expiration', $key->getPublicKeyExpiration())
86
                    ->withHeader('x-nonce', \base64_encode($r->getNonce()))
87
                    ->withHeader('x-pubkey', \base64_encode($key->getBoxPublicKey()));
88
            }
89
90
            $stream->rewind();
91
            $stream->write(\base64_encode($content));
92
            return $response->withBody($stream)
93
                ->withHeader('Content-Type', 'application/vnd.ncryptf+json')
94
                ->withHeader('x-hashid', \base64_encode($key->getHashIdentifier()));
95
        }
96
97
        return $handler->handle($request)
98
            ->withHeader('Content-Type', 'application/vnd.ncryptf+json');
99
    }
100
101
    /**
102
     * Check whether the request payload need to be processed
103
     * @param ServerRequestInterface $request
104
     * @return bool
105
     */
106
    private function checkRequest(ServerRequestInterface $request): bool
107
    {
108
        $contentType = $request->getHeaderLine('Accept');
109
        foreach ($this->contentType as $allowedType) {
110
            if (\stripos($contentType, $allowedType) === 0) {
111
                return true;
112
            }
113
        }
114
        return false;
115
    }
116
}
117