Passed
Push — master ( 149dd5...081af3 )
by Charles
02:27
created

testV2EncryptedRequestAndResponse()   B

Complexity

Conditions 6
Paths 2

Size

Total Lines 62
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 42
dl 0
loc 62
rs 8.6257
c 0
b 0
f 0
cc 6
nc 2
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php declare(strict_types=1);
2
3
namespace ncryptf\Tests;
4
5
use DateTime;
6
use ncryptf\Token;
7
use ncryptf\Request;
8
use ncryptf\Response;
9
use ncryptf\Authorization;
10
use Middlewares\Utils\Factory;
11
use WildWolf\Psr16MemoryCache;
12
use ncryptf\Tests\AbstractTest;
13
use PHPUnit\Framework\TestCase;
14
15
use Middlewares\Utils\Dispatcher;
16
use ncryptf\Tests\mock\EchoResponse;
17
use ncryptf\middleware\RequestParser;
18
use ncryptf\Tests\mock\EncryptionKey;
19
use ncryptf\Tests\mock\Authentication;
20
use Psr\Http\Message\ResponseInterface;
21
use Psr\Http\Server\MiddlewareInterface;
22
use ncryptf\middleware\ResponseFormatter;
23
use Zend\Diactoros\Response\JsonResponse;
24
use Psr\Http\Message\ServerRequestInterface;
25
use Psr\Http\Server\RequestHandlerInterface;
26
27
class RequestResponseTest extends AbstractTest
28
{
29
    private $clientKeyPair = [
30
        'secret' => 'bvV/vnfB43spmprI8aBK/Fd8xxSBlx7EhuxfxxTVI2o=',
31
        'public' => 'Ojnr0KQy6GJ6x+eQa+wNwdHejZo8vY5VNyZY5NfwBjU='
32
    ];
33
34
    private $serverKeyPair = [
35
        'secret' => 'gH1+ileX1W5fMeOWue8HxdREnK04u72ybxCQgivWoZ4=',
36
        'public' => 'YU74X2OqHujLVDH9wgEHscD5eyiLPvcugRUZG6R3BB8='
37
    ];
38
39
    private $signatureKeyPair = [
40
        'secret' => '9wdUWlSW2ZQB6ImeUZ5rVqcW+mgQncN1Cr5D2YvFdvEi42NKK/654zGtxTSOcNHPEwtFAz0A4k0hwlIFopZEsQ==',
41
        'public' => 'IuNjSiv+ueMxrcU0jnDRzxMLRQM9AOJNIcJSBaKWRLE='
42
    ];
43
44
    private $nonce = 'bulRnKt/BvwnwiCMBLvdRM5+yNFP38Ut';
45
46
    private $expectedCipher = '1odrjBif71zRcZidfhEzSb80rXGJGB1J3upTb+TwhpxmFjXOXjwSDw45e7p/+FW4Y0/FDuLjHfGghOG0UC7j4xmX8qIVYUdbKCB/dLn34HQ0D0NIM6N9Qj83bpS5XgK1o+luonc0WxqA3tdXTcgkd2D+cSSSotJ/s+5fqN3w5xsKc7rKb1p3MpvRzyEmdNgJCFOk8EErn0bolz9LKyPEO0A2Mnkzr19bDwsgD1DGEYlo0i9KOw06RpaZRz2J+OJ+EveIlQGDdLT8Gh+nv65TOKJqCswOly0=';
47
    private $expectedSignature = 'dcvJclMxEx7pcW/jeVm0mFHGxVksY6h0/vNkZTfVf+wftofnP+yDFdrNs5TtZ+FQ0KEOm6mm9XUMXavLaU9yDg==';
48
49
    private $expectedv2Cipher = '3iWQAm7pUZyrfwb8J8IgjAS73UTOfsjRT9/FLTo569CkMuhiesfnkGvsDcHR3o2aPL2OVTcmWOTX8AY11odrjBif71zRcZidfhEzSb80rXGJGB1J3upTb+TwhpxmFjXOXjwSDw45e7p/+FW4Y0/FDuLjHfGghOG0UC7j4xmX8qIVYUdbKCB/dLn34HQ0D0NIM6N9Qj83bpS5XgK1o+luonc0WxqA3tdXTcgkd2D+cSSSotJ/s+5fqN3w5xsKc7rKb1p3MpvRzyEmdNgJCFOk8EErn0bolz9LKyPEO0A2Mnkzr19bDwsgD1DGEYlo0i9KOw06RpaZRz2J+OJ+EveIlQGDdLT8Gh+nv65TOKJqCswOly0i42NKK/654zGtxTSOcNHPEwtFAz0A4k0hwlIFopZEsXXLyXJTMRMe6XFv43lZtJhRxsVZLGOodP7zZGU31X/sH7aH5z/sgxXazbOU7WfhUNChDpuppvV1DF2ry2lPcg4SwqYwa53inoY2+eCPP4Hkp/PKhSOEMFlWV+dlQirn6GGf5RQSsQ7ti/QCvi/BRIhb3ZHiPptZJZIbYwqIpvYu';
50
51
    private $payload = <<<JSON
52
{
53
    "foo": "bar",
54
    "test": {
55
        "true": false,
56
        "zero": 0.0,
57
        "a": 1,
58
        "b": 3.14,
59
        "nil": null,
60
        "arr": [
61
            "a", "b", "c", "d"
62
        ]
63
    }
64
}
65
JSON;
66
67
    public function testv2EncryptDecrypt()
68
    {
69
        $request = new Request(
70
            \base64_decode($this->clientKeyPair['secret']),
71
            \base64_decode($this->signatureKeyPair['secret'])
72
        );
73
74
        $cipher = $request->encrypt($this->payload, \base64_decode($this->serverKeyPair['public']), 2, \base64_decode($this->nonce));
75
76
        $this->assertEquals($this->expectedv2Cipher, \base64_encode($cipher));
77
78
        $response = new Response(
79
            \base64_decode($this->serverKeyPair['secret'])
80
        );
81
82
        $plain = $response->decrypt($cipher);
83
84
        $this->assertEquals($this->payload, $plain);
85
    }
86
87
    public function testDecryptEmptyString()
88
    {
89
        $request = new Request(
90
            \base64_decode($this->clientKeyPair['secret']),
91
            \base64_decode($this->signatureKeyPair['secret'])
92
        );
93
94
        $cipher = $request->encrypt('', \base64_decode($this->serverKeyPair['public']));
95
96
        $response = new Response(
97
            \base64_decode($this->serverKeyPair['secret'])
98
        );
99
100
        $plain = $response->decrypt($cipher);
101
102
        $this->assertEquals('', $plain);
103
    }
104
105
    public function testv1EncryptDecrypt()
106
    {
107
        $request = new Request(
108
            \base64_decode($this->clientKeyPair['secret']),
109
            \base64_decode($this->signatureKeyPair['secret'])
110
        );
111
112
        $cipher = $request->encrypt($this->payload, \base64_decode($this->serverKeyPair['public']), 1, \base64_decode($this->nonce));
113
114
        $signature = $request->sign($this->payload);
115
116
        $this->assertEquals($this->expectedCipher, \base64_encode($cipher));
117
        $this->assertEquals($this->expectedSignature, \base64_encode($signature));
118
119
        $response = new Response(
120
            \base64_decode($this->serverKeyPair['secret'])
121
        );
122
123
        $plain = $response->decrypt($cipher, \base64_decode($this->clientKeyPair['public']), \base64_decode($this->nonce));
124
125
        $this->assertEquals($this->payload, $plain);
126
127
        $this->assertTrue($response->isSignatureValid(
128
            $this->payload,
129
            $signature,
130
            \base64_decode($this->signatureKeyPair['public'])
131
        ));
132
    }
133
134
135
    public function testV2EncryptedRequestAndResponse()
136
    {
137
        foreach ($this->testCases as $k => $params) {
138
            $serverKey = EncryptionKey::generate();
139
            $myKey = EncryptionKey::generate();
140
            $cache = Psr16MemoryCache::instance();
141
            $cache->set($serverKey->getHashIdentifier(), $serverKey);
142
143
            $auth = new Authorization($params[0], $params[1], $this->token, new DateTime, $params[2]);
144
            $token = $this->token;
145
146
            $response = Dispatcher::run(
147
                [
148
                    new RequestParser($cache),
149
                    new Authentication,
150
                    function ($request, $next) use ($params) {
0 ignored issues
show
Unused Code introduced by
The import $params is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
151
                        $this->assertInstanceOf('\ncryptf\Token', $request->getAttribute('ncryptf-token'));
152
                        $this->assertEquals(true, \is_array($request->getAttribute('ncryptf-user')));
153
                        return $next->handle($request);
154
                    },
155
                    new ResponseFormatter($cache, new EncryptionKey),
156
                    new EchoResponse,
157
                ],
158
                Factory::createServerRequest($params[0], $params[1])
159
                    ->withHeader('Authorization', $auth->getHeader())
160
                    ->withHeader('Content-Type', 'application/vnd.ncryptf+json')
161
                    ->withHeader('Accept', 'application/vnd.ncryptf+json')
162
                    ->withHeader('X-HashId', $serverKey->getHashIdentifier())
163
                    ->withHeader('X-PubKey', \base64_encode($myKey->getBoxPublicKey()))
164
                    ->withBody((function () use ($params, $serverKey, $myKey, $token) {
165
                        $data = \is_array($params[2]) ? \json_encode($params[2]): $params[2];
166
 
167
                        if (!empty($params[2])) {
168
                            $request = new Request(
169
                                $myKey->getBoxSecretKey(),
170
                                $token->signature
171
                            );
172
173
                            $encryptedData = $request->encrypt(
174
                                $data,
175
                                $serverKey->getBoxPublicKey()
176
                            );
177
                        }
178
                        $stream = fopen('php://memory', 'r+');
179
                        fwrite($stream, empty($params[2]) ? '' : \base64_encode($encryptedData));
0 ignored issues
show
Bug introduced by
It seems like $stream can also be of type false; however, parameter $handle of fwrite() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

179
                        fwrite(/** @scrutinizer ignore-type */ $stream, empty($params[2]) ? '' : \base64_encode($encryptedData));
Loading history...
Comprehensibility Best Practice introduced by
The variable $encryptedData does not seem to be defined for all execution paths leading up to this point.
Loading history...
180
                        rewind($stream);
0 ignored issues
show
Bug introduced by
It seems like $stream can also be of type false; however, parameter $handle of rewind() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

180
                        rewind(/** @scrutinizer ignore-type */ $stream);
Loading history...
181
                        return new \Zend\Diactoros\Stream($stream);
0 ignored issues
show
Bug introduced by
It seems like $stream can also be of type false; however, parameter $stream of Zend\Diactoros\Stream::__construct() does only seem to accept resource|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

181
                        return new \Zend\Diactoros\Stream(/** @scrutinizer ignore-type */ $stream);
Loading history...
182
                    })())
183
            );
184
185
            $this->assertSame('application/vnd.ncryptf+json', $response->getHeaderLine('Content-Type'));
186
            $this->assertTrue($response->hasHeader('x-hashid'));
187
188
            $r = new Response(
189
                $myKey->getBoxSecretKey()
190
            );
191
192
            $plaintext = $r->decrypt(
193
                \base64_decode((string)$response->getBody())
194
            );
195
196
            $this->assertEquals(\is_array($params[2]) ? \json_encode($params[2]) : $params[2], $plaintext);
197
        }
198
    }
199
200
    public function testV1EncryptedRequestAndResponse()
201
    {
202
        foreach ($this->testCases as $k => $params) {
203
            $serverKey = EncryptionKey::generate();
204
            $myKey = EncryptionKey::generate();
205
            $nonce = \random_bytes(24);
206
            $cache = Psr16MemoryCache::instance();
207
            $cache->set($serverKey->getHashIdentifier(), $serverKey);
208
209
            $auth = new Authorization($params[0], $params[1], $this->token, new DateTime, $params[2]);
210
            $token = $this->token;
211
            $response = Dispatcher::run(
212
                [
213
                    new RequestParser($cache),
214
                    new Authentication,
215
                    function ($request, $next) {
216
                        $this->assertInstanceOf('\ncryptf\Token', $request->getAttribute('ncryptf-token'));
217
                        $this->assertEquals(true, \is_array($request->getAttribute('ncryptf-user')));
218
                        return $next->handle($request);
219
                    },
220
                    new ResponseFormatter($cache, new EncryptionKey),
221
                    new EchoResponse,
222
                ],
223
                Factory::createServerRequest($params[0], $params[1])
224
                    ->withHeader('Authorization', $auth->getHeader())
225
                    ->withHeader('Content-Type', 'application/vnd.25519+json')
226
                    ->withHeader('Accept', 'application/vnd.25519+json')
227
                    ->withHeader('X-HashId', $serverKey->getHashIdentifier())
228
                    ->withHeader('X-Nonce', \base64_encode($nonce))
229
                    ->withHeader('X-PubKey', \base64_encode($myKey->getBoxPublicKey()))
230
                    ->withBody((function () use ($params, $serverKey, $myKey, $nonce, $token) {
231
                        $data = \is_array($params[2]) ? \json_encode($params[2]): $params[2];
232
233
                        $request = new Request(
234
                            $myKey->getBoxSecretKey(),
235
                            $token->signature
236
                        );
237
238
                        $encryptedData = $request->encrypt(
239
                            $data,
240
                            $serverKey->getBoxPublicKey(),
241
                            1,
242
                            $nonce
243
                        );
244
                        $stream = fopen('php://memory', 'r+');
245
                        fwrite($stream, $data === '' ? '' : \base64_encode($encryptedData));
0 ignored issues
show
Bug introduced by
It seems like $stream can also be of type false; however, parameter $handle of fwrite() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

245
                        fwrite(/** @scrutinizer ignore-type */ $stream, $data === '' ? '' : \base64_encode($encryptedData));
Loading history...
246
                        rewind($stream);
0 ignored issues
show
Bug introduced by
It seems like $stream can also be of type false; however, parameter $handle of rewind() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

246
                        rewind(/** @scrutinizer ignore-type */ $stream);
Loading history...
247
                        return new \Zend\Diactoros\Stream($stream);
0 ignored issues
show
Bug introduced by
It seems like $stream can also be of type false; however, parameter $stream of Zend\Diactoros\Stream::__construct() does only seem to accept resource|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

247
                        return new \Zend\Diactoros\Stream(/** @scrutinizer ignore-type */ $stream);
Loading history...
248
                    })())
249
            );
250
251
            $this->assertSame(200, $response->getStatusCode());
252
            $this->assertSame('application/vnd.ncryptf+json', $response->getHeaderLine('Content-Type'));
253
            if ($params[2] !== '') {
254
                $this->assertTrue($response->hasHeader('x-hashid'));
255
                $this->assertTrue($response->hasHeader('x-signature'));
256
                $this->assertTrue($response->hasHeader('x-sigpubkey'));
257
                $this->assertTrue($response->hasHeader('x-nonce'));
258
                $this->assertTrue($response->hasHeader('x-pubkey'));
259
                $this->assertTrue($response->hasHeader('x-public-key-expiration'));
260
            }
261
262
            $r = new Response(
263
                $myKey->getBoxSecretKey()
264
            );
265
266
            $plaintext = $r->decrypt(
267
                \base64_decode((string)$response->getBody()),
268
                \base64_decode($response->getHeaderLine('x-pubkey')),
269
                \base64_decode($response->getHeaderLine('x-nonce'))
270
            );
271
272
            $this->assertEquals(\is_array($params[2]) ? \json_encode($params[2]) : $params[2], $plaintext);
273
        }
274
    }
275
276
    public function testPublicKeyExtraction()
277
    {
278
        $publicKey = Response::getPublicKeyFromResponse(\base64_decode($this->expectedv2Cipher));
279
        $this->assertEquals(\base64_decode($this->clientKeyPair['public']), $publicKey);
280
    }
281
282
    public function testVersion()
283
    {
284
        $this->assertEquals(1, Response::getVersion(\base64_decode($this->expectedCipher)));
285
        $this->assertEquals(2, Response::getVersion(\base64_decode($this->expectedv2Cipher)));
286
    }
287
}
288