Completed
Push — v2.0.x ( 11273c...f488cd )
by Florent
04:53 queued 01:28
created

ECDHESKeyAgreementTest::testGetAnAgreementKeyUsingP384Keys()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 27
Code Lines 19

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 27
rs 8.8571
cc 1
eloc 19
nc 1
nop 0
1
<?php
2
3
/*
4
 * The MIT License (MIT)
5
 *
6
 * Copyright (c) 2014-2016 Spomky-Labs
7
 *
8
 * This software may be modified and distributed under the terms
9
 * of the MIT license.  See the LICENSE file for details.
10
 */
11
12
use Base64Url\Base64Url;
13
use Jose\Algorithm\KeyEncryption\ECDHES;
14
use Jose\Algorithm\KeyEncryption\ECDHESA128KW;
15
use Jose\Algorithm\KeyEncryption\ECDHESA192KW;
16
use Jose\Algorithm\KeyEncryption\ECDHESA256KW;
17
use Jose\Object\JWK;
18
19
/**
20
 * Class ECDHESKeyAgreementTest.
21
 *
22
 * @group ECDHES
23
 */
24
class ECDHESKeyAgreementTest extends \PHPUnit_Framework_TestCase
25
{
26
    /**
27
     * @see https://tools.ietf.org/html/rfc7518#appendix-C
28
     */
29
    public function testGetAgreementKey()
30
    {
31
        $receiver = new JWK([
32
            'kty' => 'EC',
33
            'crv' => 'P-256',
34
            'x'   => 'weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ',
35
            'y'   => 'e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck',
36
            'd'   => 'VEmDZpDXXK8p8N0Cndsxs924q6nS1RXFASRl6BfUqdw',
37
        ]);
38
39
        $sender = new JWK([
40
            'kty' => 'EC',
41
            'crv' => 'P-256',
42
            'x'   => 'gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0',
43
            'y'   => 'SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps',
44
            'd'   => '0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd',
45
        ]);
46
47
        $header = [
48
            'enc' => 'A128GCM',
49
            'apu' => 'QWxpY2U',
50
            'apv' => 'Qm9i',
51
        ];
52
        $expected = Base64Url::decode('9FdsD3uzmeK4ImyoWpP5PA');
53
        $ecdh_es = new ECDHES();
54
        $additional_header_values = [];
55
56
        $this->assertEquals($expected, $ecdh_es->getAgreementKey(128, $sender, $receiver, $header, $additional_header_values));
57
        $this->assertTrue(array_key_exists('epk', $additional_header_values));
58
        $this->assertTrue(array_key_exists('kty', $additional_header_values['epk']));
59
        $this->assertTrue(array_key_exists('crv', $additional_header_values['epk']));
60
        $this->assertTrue(array_key_exists('x', $additional_header_values['epk']));
61
        $this->assertTrue(array_key_exists('y', $additional_header_values['epk']));
62
    }
63
64
    /**
65
     *
66
     */
67
    public function testGetAgreementKeyWithA128KeyWrap()
68
    {
69
        $header = ['enc' => 'A128GCM'];
70
71
        $receiver = new JWK([
72
            'kty' => 'EC',
73
            'crv' => 'P-256',
74
            'x'   => 'weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ',
75
            'y'   => 'e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck',
76
            'd'   => 'VEmDZpDXXK8p8N0Cndsxs924q6nS1RXFASRl6BfUqdw',
77
        ]);
78
79
        $sender = new JWK([
80
            'kty' => 'EC',
81
            'crv' => 'P-256',
82
            'x'   => 'gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0',
83
            'y'   => 'SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps',
84
            'd'   => '0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo',
85
        ]);
86
87
        $cek = [4, 211, 31, 197, 84, 157, 252, 254, 11, 100, 157, 250, 63, 170, 106, 206, 107, 124, 212, 45, 111, 107, 9, 219, 200, 177, 0, 240, 143, 156, 44, 207];
88
        foreach ($cek as $key => $value) {
89
            $cek[$key] = str_pad(dechex($value), 2, '0', STR_PAD_LEFT);
90
        }
91
        $cek = hex2bin(implode('', $cek));
92
93
        $ecdh_es = new ECDHESA128KW();
94
        $encrypted_cek = $ecdh_es->wrapAgreementKey($sender, $receiver, $cek, 128, $header, $header);
95
        $this->assertTrue(array_key_exists('epk', $header));
96
        $this->assertTrue(array_key_exists('crv', $header['epk']));
97
        $this->assertTrue(array_key_exists('kty', $header['epk']));
98
        $this->assertTrue(array_key_exists('x', $header['epk']));
99
        $this->assertTrue(array_key_exists('y', $header['epk']));
100
        $this->assertEquals('P-256', $header['epk']['crv']);
101
        $this->assertEquals('EC', $header['epk']['kty']);
102
        $this->assertEquals($cek, $ecdh_es->unwrapAgreementKey($receiver, $encrypted_cek, 128, $header));
103
    }
104
105
    /**
106
     *
107
     */
108
    public function testGetAgreementKeyWithA192KeyWrap()
109
    {
110
        $header = ['enc' => 'A192GCM'];
111
        $receiver = new JWK([
112
            'kty' => 'EC',
113
            'crv' => 'P-256',
114
            'x'   => 'weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ',
115
            'y'   => 'e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck',
116
            'd'   => 'VEmDZpDXXK8p8N0Cndsxs924q6nS1RXFASRl6BfUqdw',
117
        ]);
118
119
        $sender = new JWK([
120
            'kty' => 'EC',
121
            'crv' => 'P-256',
122
            'x'   => 'gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0',
123
            'y'   => 'SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps',
124
            'd'   => '0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo',
125
        ]);
126
127
        $cek = [4, 211, 31, 197, 84, 157, 252, 254, 11, 100, 157, 250, 63, 170, 106, 206, 107, 124, 212, 45, 111, 107, 9, 219, 200, 177, 0, 240, 143, 156, 44, 207];
128
        foreach ($cek as $key => $value) {
129
            $cek[$key] = str_pad(dechex($value), 2, '0', STR_PAD_LEFT);
130
        }
131
        $cek = hex2bin(implode('', $cek));
132
133
        $ecdh_es = new ECDHESA192KW();
134
        $encrypted_cek = $ecdh_es->wrapAgreementKey($sender, $receiver, $cek, 192, $header, $header);
135
        $this->assertTrue(array_key_exists('epk', $header));
136
        $this->assertTrue(array_key_exists('crv', $header['epk']));
137
        $this->assertTrue(array_key_exists('kty', $header['epk']));
138
        $this->assertTrue(array_key_exists('x', $header['epk']));
139
        $this->assertTrue(array_key_exists('y', $header['epk']));
140
        $this->assertEquals('P-256', $header['epk']['crv']);
141
        $this->assertEquals('EC', $header['epk']['kty']);
142
        $this->assertEquals($cek, $ecdh_es->unwrapAgreementKey($receiver, $encrypted_cek, 192, $header));
143
    }
144
145
    /**
146
     *
147
     */
148
    public function testGetAgreementKeyWithA256KeyWrap()
149
    {
150
        $header = ['enc' => 'A256GCM'];
151
        $receiver = new JWK([
152
            'kty' => 'EC',
153
            'crv' => 'P-256',
154
            'x'   => 'weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ',
155
            'y'   => 'e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck',
156
            'd'   => 'VEmDZpDXXK8p8N0Cndsxs924q6nS1RXFASRl6BfUqdw',
157
        ]);
158
159
        $sender = new JWK([
160
            'kty' => 'EC',
161
            'crv' => 'P-256',
162
            'x'   => 'gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0',
163
            'y'   => 'SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps',
164
            'd'   => '0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo',
165
        ]);
166
167
        $cek = [4, 211, 31, 197, 84, 157, 252, 254, 11, 100, 157, 250, 63, 170, 106, 206, 107, 124, 212, 45, 111, 107, 9, 219, 200, 177, 0, 240, 143, 156, 44, 207];
168
        foreach ($cek as $key => $value) {
169
            $cek[$key] = str_pad(dechex($value), 2, '0', STR_PAD_LEFT);
170
        }
171
        $cek = hex2bin(implode('', $cek));
172
173
        $ecdh_es = new ECDHESA256KW();
174
        $encrypted_cek = $ecdh_es->wrapAgreementKey($sender, $receiver, $cek, 256, $header, $header);
175
        $this->assertTrue(array_key_exists('epk', $header));
176
        $this->assertTrue(array_key_exists('crv', $header['epk']));
177
        $this->assertTrue(array_key_exists('kty', $header['epk']));
178
        $this->assertTrue(array_key_exists('x', $header['epk']));
179
        $this->assertTrue(array_key_exists('y', $header['epk']));
180
        $this->assertEquals('P-256', $header['epk']['crv']);
181
        $this->assertEquals('EC', $header['epk']['kty']);
182
        $this->assertEquals($cek, $ecdh_es->unwrapAgreementKey($receiver, $encrypted_cek, 256, $header));
183
    }
184
185
    /**
186
     * @expectedException \InvalidArgumentException
187
     * @expectedExceptionMessage Curves are different
188
     */
189
    public function testCurvesAreDifferent()
190
    {
191
        $receiver = new JWK([
192
            'kty' => 'EC',
193
            'crv' => 'P-521',
194
            'x'   => 'AekpBQ8ST8a8VcfVOTNl353vSrDCLLJXmPk06wTjxrrjcBpXp5EOnYG_NjFZ6OvLFV1jSfS9tsz4qUxcWceqwQGk',
195
            'y'   => 'ADSmRA43Z1DSNx_RvcLI87cdL07l6jQyyBXMoxVg_l2Th-x3S1WDhjDly79ajL4Kkd0AZMaZmh9ubmf63e3kyMj2',
196
        ]);
197
198
        $sender = new JWK([
199
            'kty' => 'EC',
200
            'crv' => 'P-256',
201
            'x'   => 'gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0',
202
            'y'   => 'SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps',
203
            'd'   => '0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo',
204
        ]);
205
206
        $ecdh_es = new ECDHES();
207
        $ecdh_es->getAgreementKey(256, $sender, $receiver);
208
    }
209
210
    /**
211
     * @expectedException \InvalidArgumentException
212
     * @expectedExceptionMessage "epk" parameter missing
213
     */
214
    public function testEPKParameterAreMissing()
215
    {
216
        $sender = new JWK([
217
            'kty' => 'EC',
218
            'crv' => 'P-256',
219
            'x'   => 'gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0',
220
            'y'   => 'SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps',
221
            'd'   => '0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo',
222
        ]);
223
224
        $ecdh_es = new ECDHES();
225
        $ecdh_es->getAgreementKey(256, $sender);
226
    }
227
228
    /**
229
     * @expectedException \InvalidArgumentException
230
     * @expectedExceptionMessage "epk" parameter is not an array of parameter
231
     */
232
    public function testBadEPKParameter()
233
    {
234
        $header = ['epk' => 'foo'];
235
        $sender = new JWK([
236
            'kty' => 'EC',
237
            'crv' => 'P-256',
238
            'x'   => 'gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0',
239
            'y'   => 'SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps',
240
            'd'   => '0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo',
241
        ]);
242
243
        $ecdh_es = new ECDHES();
244
        $ecdh_es->getAgreementKey(256, $sender, null, $header);
245
    }
246
247
    /**
248
     * @expectedException \InvalidArgumentException
249
     * @expectedExceptionMessage The key must be private
250
     */
251
    public function testNotAPrivateKey()
252
    {
253
        $receiver = new JWK([
254
            'kty' => 'EC',
255
            'crv' => 'P-256',
256
            'x'   => 'weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ',
257
            'y'   => 'e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck',
258
        ]);
259
260
        $sender = new JWK([
261
            'kty' => 'EC',
262
            'crv' => 'P-256',
263
            'x'   => 'gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0',
264
            'y'   => 'SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps',
265
        ]);
266
267
        $ecdh_es = new ECDHES();
268
        $ecdh_es->getAgreementKey(256, $sender, $receiver);
269
    }
270
271
    /**
272
     * @expectedException \InvalidArgumentException
273
     * @expectedExceptionMessage The key type must be "EC"
274
     */
275
    public function testNotAnECKey()
276
    {
277
        $receiver = new JWK([
278
            'kty' => 'EC',
279
            'crv' => 'P-256',
280
            'x'   => 'weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ',
281
            'y'   => 'e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck',
282
        ]);
283
284
        $sender = new JWK([
285
            'kty' => 'dir',
286
            'dir' => Base64Url::encode('ABCD'),
287
        ]);
288
289
        $ecdh_es = new ECDHES();
290
        $ecdh_es->getAgreementKey(256, $sender, $receiver);
291
    }
292
293
    /**
294
     * @expectedException \InvalidArgumentException
295
     * @expectedExceptionMessage Key components ("x", "y" or "crv") missing
296
     */
297
    public function testECKeyHasMissingParameters()
298
    {
299
        $receiver = new JWK([
300
            'kty' => 'EC',
301
            'crv' => 'P-256',
302
            'x'   => 'weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ',
303
            'y'   => 'e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck',
304
        ]);
305
306
        $sender = new JWK([
307
            'kty' => 'EC',
308
            'dir' => Base64Url::encode('ABCD'),
309
        ]);
310
311
        $ecdh_es = new ECDHES();
312
        $ecdh_es->getAgreementKey(256, $sender, $receiver);
313
    }
314
315
    public function testGetAnAgreementKeyUsingP521Keys()
316
    {
317
        $header = [
318
            'enc' => 'A128GCM',
319
            'apu' => 'QWxpY2U',
320
            'apv' => 'Qm9i',
321
        ];
322
323
        $receiver = new JWK([
324
            'kty' => 'EC',
325
            'crv' => 'P-521',
326
            'x'   => 'AekpBQ8ST8a8VcfVOTNl353vSrDCLLJXmPk06wTjxrrjcBpXp5EOnYG_NjFZ6OvLFV1jSfS9tsz4qUxcWceqwQGk',
327
            'y'   => 'ADSmRA43Z1DSNx_RvcLI87cdL07l6jQyyBXMoxVg_l2Th-x3S1WDhjDly79ajL4Kkd0AZMaZmh9ubmf63e3kyMj2',
328
        ]);
329
330
        $sender = new JWK([
331
            'kty' => 'EC',
332
            'crv' => 'P-521',
333
            'd'   => 'Fp6KFKRiHIdR_7PP2VKxz6OkS_phyoQqwzv2I89-8zP7QScrx5r8GFLcN5mCCNJt3rN3SIgI4XoIQbNePlAj6vE',
334
            'x'   => 'AVpvo7TGpQk5P7ZLo0qkBpaT-fFDv6HQrWElBKMxcrJd_mRNapweATsVv83YON4lTIIRXzgGkmWeqbDr6RQO-1cS',
335
            'y'   => 'AIs-MoRmLaiPyG2xmPwQCHX2CGX_uCZiT3iOxTAJEZuUbeSA828K4WfAA4ODdGiB87YVShhPOkiQswV3LpbpPGhC',
336
        ]);
337
338
        $ecdh_es = new ECDHES();
339
        $agreement_key = $ecdh_es->getAgreementKey(256, $sender, $receiver, $header);
340
        $this->assertEquals('clNz59mGIo1vb1wRLUz7FYB2pGx3TpQ-pRiqdEPdW1o', Base64Url::encode($agreement_key));
341
    }
342
343
    public function testGetAnAgreementKeyUsingP384Keys()
344
    {
345
        $header = [
346
            'enc' => 'A128GCM',
347
            'apu' => 'QWxpY2U',
348
            'apv' => 'Qm9i',
349
        ];
350
351
        $receiver = new JWK([
352
            'kty' => 'EC',
353
            'crv' => 'P-384',
354
            'x'   => '6f-XZsg2Tvn0EoEapQ-ylMYNtsm8CPf0cb8HI2EkfY9Bqpt3QMzwlM7mVsFRmaMZ',
355
            'y'   => 'b8nOnRwmpmEnvA2U8ydS-dbnPv7bwYl-q1qNeh8Wpjor3VO-RTt4ce0Pn25oGGWU',
356
        ]);
357
358
        $sender = new JWK([
359
            'kty' => 'EC',
360
            'crv' => 'P-384',
361
            'd'   => 'pcSSXrbeZEOaBIs7IwqcU9M_OOM81XhZuOHoGgmS_2PdECwcdQcXzv7W8-lYL0cr',
362
            'x'   => '6f-XZsg2Tvn0EoEapQ-ylMYNtsm8CPf0cb8HI2EkfY9Bqpt3QMzwlM7mVsFRmaMZ',
363
            'y'   => 'b8nOnRwmpmEnvA2U8ydS-dbnPv7bwYl-q1qNeh8Wpjor3VO-RTt4ce0Pn25oGGWU',
364
        ]);
365
366
        $ecdh_es = new ECDHES();
367
        $agreement_key = $ecdh_es->getAgreementKey(256, $sender, $receiver, $header);
368
        $this->assertEquals('-Fj6ZkBpOcITxDcloKVNItlIH6qF2gyjw7oIHIEChp8', Base64Url::encode($agreement_key));
369
    }
370
371
    /**
372
     * @expectedException \InvalidArgumentException
373
     * @expectedExceptionMessage Curve "P-192" is not supported
374
     */
375
    public function testUnsupportedCurve()
376
    {
377
        $header = [
378
            'enc' => 'A128GCM',
379
            'apu' => 'QWxpY2U',
380
            'apv' => 'Qm9i',
381
        ];
382
383
        $receiver = new JWK([
384
            'kty' => 'EC',
385
            'crv' => 'P-192',
386
            'x'   => 'm2Jmp98NRH83ramvp0VVIQJXK56ZEwuM',
387
            'y'   => '84lz6hQtPJe9WFPPgEyOUwh3tuW2kOS_',
388
        ]);
389
390
        $sender = new JWK([
391
            'kty' => 'EC',
392
            'crv' => 'P-192',
393
            'd'   => 'qArdbBWdouFDDNNu0KQn5LvlC_2sUX2Y',
394
            'x'   => 'oiSisKljjDC_KrqGQl0WvxLvDOAxbKdL',
395
            'y'   => '97zCNl8vB9uiDcRhoH19DnplN0KSRn9A',
396
        ]);
397
398
        $ecdh_es = new ECDHES();
399
        $agreement_key = $ecdh_es->getAgreementKey(256, $sender, $receiver, $header);
400
        $this->assertEquals('-Fj6ZkBpOcITxDcloKVNItlIH6qF2gyjw7oIHIEChp8', Base64Url::encode($agreement_key));
401
    }
402
}
403