Failed Conditions
Push — v7 ( e44e34...2109ab )
by Florent
04:36
created

testGetAgreementKeyWithA128KeyWrap()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 36
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 27
nc 2
nop 0
dl 0
loc 36
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * The MIT License (MIT)
7
 *
8
 * Copyright (c) 2014-2017 Spomky-Labs
9
 *
10
 * This software may be modified and distributed under the terms
11
 * of the MIT license.  See the LICENSE file for details.
12
 */
13
14
namespace Jose\Component\Encryption\Tests;
15
16
use Base64Url\Base64Url;
17
use Jose\Component\Core\JWK;
18
use Jose\Component\Encryption\Algorithm\KeyEncryption\ECDHES;
19
use Jose\Component\Encryption\Algorithm\KeyEncryption\ECDHESA128KW;
20
use Jose\Component\Encryption\Algorithm\KeyEncryption\ECDHESA192KW;
21
use Jose\Component\Encryption\Algorithm\KeyEncryption\ECDHESA256KW;
22
use Jose\Component\KeyManagement\JWKFactory;
23
24
/**
25
 * final class ECDHESKeyAgreementTest.
26
 *
27
 * @group ECDHES
28
 * @group Unit
29
 */
30
final class ECDHESKeyAgreementTest extends AbstractEncryptionTest
31
{
32
    /**
33
     * @see https://tools.ietf.org/html/rfc7518#appendix-C
34
     */
35
    public function testGetAgreementKey()
36
    {
37
        $receiver = JWK::create([
38
            'kty' => 'EC',
39
            'crv' => 'P-256',
40
            'x' => 'weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ',
41
            'y' => 'e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck',
42
        ]);
43
44
        $header = [
45
            'enc' => 'A128GCM',
46
            'apu' => 'QWxpY2U',
47
            'apv' => 'Qm9i',
48
        ];
49
        $ecdh_es = new ECDHES();
50
        $additional_header_values = [];
51
52
        $ecdh_es->getAgreementKey(128, 'A128GCM', $receiver, $header, $additional_header_values);
53
        $this->assertTrue(array_key_exists('epk', $additional_header_values));
54
        $this->assertTrue(array_key_exists('kty', $additional_header_values['epk']));
55
        $this->assertTrue(array_key_exists('crv', $additional_header_values['epk']));
56
        $this->assertTrue(array_key_exists('x', $additional_header_values['epk']));
57
        $this->assertTrue(array_key_exists('y', $additional_header_values['epk']));
58
    }
59
60
    public function testGetAgreementKeyWithA128KeyWrap()
61
    {
62
        $header = ['enc' => 'A128GCM'];
63
64
        $public = JWK::create([
65
            'kty' => 'EC',
66
            'crv' => 'P-256',
67
            'x' => 'weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ',
68
            'y' => 'e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck',
69
        ]);
70
71
        $private = JWK::create([
72
            'kty' => 'EC',
73
            'crv' => 'P-256',
74
            'x' => 'weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ',
75
            'y' => 'e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck',
76
            'd' => 'VEmDZpDXXK8p8N0Cndsxs924q6nS1RXFASRl6BfUqdw',
77
        ]);
78
79
        $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];
80
        foreach ($cek as $key => $value) {
81
            $cek[$key] = str_pad(dechex($value), 2, '0', STR_PAD_LEFT);
82
        }
83
        $cek = hex2bin(implode('', $cek));
84
85
        $ecdh_es = new ECDHESA128KW();
86
        $encrypted_cek = $ecdh_es->wrapAgreementKey($public, $cek, 128, $header, $header);
87
        $this->assertTrue(array_key_exists('epk', $header));
88
        $this->assertTrue(array_key_exists('crv', $header['epk']));
89
        $this->assertTrue(array_key_exists('kty', $header['epk']));
90
        $this->assertTrue(array_key_exists('x', $header['epk']));
91
        $this->assertTrue(array_key_exists('y', $header['epk']));
92
        $this->assertEquals('P-256', $header['epk']['crv']);
93
        $this->assertEquals('EC', $header['epk']['kty']);
94
        $this->assertEquals($cek, $ecdh_es->unwrapAgreementKey($private, $encrypted_cek, 128, $header));
95
    }
96
97
    public function testGetAgreementKeyWithA192KeyWrap()
98
    {
99
        $header = ['enc' => 'A192GCM'];
100
101
        $public = JWK::create([
102
            'kty' => 'EC',
103
            'crv' => 'P-256',
104
            'x' => 'weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ',
105
            'y' => 'e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck',
106
        ]);
107
108
        $private = JWK::create([
109
            'kty' => 'EC',
110
            'crv' => 'P-256',
111
            'x' => 'weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ',
112
            'y' => 'e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck',
113
            'd' => 'VEmDZpDXXK8p8N0Cndsxs924q6nS1RXFASRl6BfUqdw',
114
        ]);
115
116
        $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];
117
        foreach ($cek as $key => $value) {
118
            $cek[$key] = str_pad(dechex($value), 2, '0', STR_PAD_LEFT);
119
        }
120
        $cek = hex2bin(implode('', $cek));
121
122
        $ecdh_es = new ECDHESA192KW();
123
        $encrypted_cek = $ecdh_es->wrapAgreementKey($public, $cek, 192, $header, $header);
124
        $this->assertTrue(array_key_exists('epk', $header));
125
        $this->assertTrue(array_key_exists('crv', $header['epk']));
126
        $this->assertTrue(array_key_exists('kty', $header['epk']));
127
        $this->assertTrue(array_key_exists('x', $header['epk']));
128
        $this->assertTrue(array_key_exists('y', $header['epk']));
129
        $this->assertEquals('P-256', $header['epk']['crv']);
130
        $this->assertEquals('EC', $header['epk']['kty']);
131
        $this->assertEquals($cek, $ecdh_es->unwrapAgreementKey($private, $encrypted_cek, 192, $header));
132
    }
133
134
    public function testGetAgreementKeyWithA256KeyWrap()
135
    {
136
        $header = ['enc' => 'A256GCM'];
137
138
        $public = JWK::create([
139
            'kty' => 'EC',
140
            'crv' => 'P-256',
141
            'x' => 'weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ',
142
            'y' => 'e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck',
143
        ]);
144
145
        $private = JWK::create([
146
            'kty' => 'EC',
147
            'crv' => 'P-256',
148
            'x' => 'weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ',
149
            'y' => 'e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck',
150
            'd' => 'VEmDZpDXXK8p8N0Cndsxs924q6nS1RXFASRl6BfUqdw',
151
        ]);
152
153
        $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];
154
        foreach ($cek as $key => $value) {
155
            $cek[$key] = str_pad(dechex($value), 2, '0', STR_PAD_LEFT);
156
        }
157
        $cek = hex2bin(implode('', $cek));
158
159
        $ecdh_es = new ECDHESA256KW();
160
        $encrypted_cek = $ecdh_es->wrapAgreementKey($public, $cek, 256, $header, $header);
161
        $this->assertTrue(array_key_exists('epk', $header));
162
        $this->assertTrue(array_key_exists('crv', $header['epk']));
163
        $this->assertTrue(array_key_exists('kty', $header['epk']));
164
        $this->assertTrue(array_key_exists('x', $header['epk']));
165
        $this->assertTrue(array_key_exists('y', $header['epk']));
166
        $this->assertEquals('P-256', $header['epk']['crv']);
167
        $this->assertEquals('EC', $header['epk']['kty']);
168
        $this->assertEquals($cek, $ecdh_es->unwrapAgreementKey($private, $encrypted_cek, 256, $header));
169
    }
170
171
    /**
172
     * @expectedException \InvalidArgumentException
173
     * @expectedExceptionMessage The header parameter "epk" is missing
174
     */
175
    public function testEPKParameterAreMissing()
176
    {
177
        $sender = JWK::create([
178
            'kty' => 'EC',
179
            'crv' => 'P-256',
180
            'x' => 'gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0',
181
            'y' => 'SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps',
182
            'd' => '0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo',
183
        ]);
184
185
        $ecdh_es = new ECDHES();
186
        $ecdh_es->getAgreementKey(256, 'A128GCM', $sender);
187
    }
188
189
    /**
190
     * @expectedException \InvalidArgumentException
191
     * @expectedExceptionMessage The header parameter "epk" is not an array of parameter
192
     */
193
    public function testBadEPKParameter()
194
    {
195
        $header = ['epk' => 'foo'];
196
        $sender = JWK::create([
197
            'kty' => 'EC',
198
            'crv' => 'P-256',
199
            'x' => 'gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0',
200
            'y' => 'SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps',
201
            'd' => '0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo',
202
        ]);
203
204
        $ecdh_es = new ECDHES();
205
        $ecdh_es->getAgreementKey(256, 'A128GCM', $sender, $header);
206
    }
207
208
    /**
209
     * @expectedException \InvalidArgumentException
210
     * @expectedExceptionMessage The key parameter "x" is missing.
211
     */
212
    public function testECKeyHasMissingParameters()
213
    {
214
        $receiver = JWK::create([
215
            'kty' => 'EC',
216
            'dir' => Base64Url::encode('ABCD'),
217
        ]);
218
219
        $ecdh_es = new ECDHES();
220
        $ecdh_es->getAgreementKey(256, 'A128GCM', $receiver);
221
    }
222
223
    /**
224
     * @expectedException \InvalidArgumentException
225
     * @expectedExceptionMessage The curve "P-192" is not supported
226
     */
227
    public function testUnsupportedCurve()
228
    {
229
        $header = [
230
            'enc' => 'A128GCM',
231
            'apu' => 'QWxpY2U',
232
            'apv' => 'Qm9i',
233
        ];
234
235
        $receiver = JWK::create([
236
            'kty' => 'EC',
237
            'crv' => 'P-192',
238
            'x' => 'm2Jmp98NRH83ramvp0VVIQJXK56ZEwuM',
239
            'y' => '84lz6hQtPJe9WFPPgEyOUwh3tuW2kOS_',
240
        ]);
241
242
        $ecdh_es = new ECDHES();
243
        $ecdh_es->getAgreementKey(256, 'A128GCM', $receiver, $header);
244
    }
245
246
    /**
247
     * @see https://tools.ietf.org/html/rfc7518#appendix-C
248
     */
249
    public function testGetAgreementKeyWithX25519Curve()
250
    {
251
        $receiver_private_key = JWKFactory::createOKPKey('X25519');
252
        $receiver_public_key = $receiver_private_key->toPublic();
253
254
        $header = [
255
            'enc' => 'A128GCM',
256
            'apu' => 'QWxpY2U',
257
            'apv' => 'Qm9i',
258
        ];
259
260
        $ecdh_es = new ECDHES();
261
        $additional_header_values = [];
262
263
        $agreement_key_from_sender = $ecdh_es->getAgreementKey(128, 'A128GCM', $receiver_public_key, $header, $additional_header_values);
264
        $agreement_key_from_receiver = $ecdh_es->getAgreementKey(128, 'A128GCM', $receiver_private_key, array_merge($header, $additional_header_values));
265
266
        $this->assertTrue(array_key_exists('epk', $additional_header_values));
267
        $this->assertEquals($agreement_key_from_receiver, $agreement_key_from_sender);
268
    }
269
}
270