Failed Conditions
Pull Request — master (#151)
by Florent
03:08
created

AESGCMKW::checkAdditionalParameters()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
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
namespace Jose\Algorithm\KeyEncryption;
13
14
use AESGCM\AESGCM;
15
use Assert\Assertion;
16
use Base64Url\Base64Url;
17
use Crypto\Cipher;
18
use Jose\Object\JWKInterface;
19
20
/**
21
 * Class AESGCMKW.
22
 */
23
abstract class AESGCMKW implements KeyWrappingInterface
24
{
25
    /**
26
     * {@inheritdoc}
27
     */
28
    public function wrapKey(JWKInterface $key, $cek, array $complete_headers, array &$additional_headers)
29
    {
30
        $this->checkKey($key);
31
        $kek = Base64Url::decode($key->get('k'));
32
        $iv = random_bytes(96 / 8);
33
        $additional_headers['iv'] = Base64Url::encode($iv);
34
35
        list($encrypted_cek, $tag) = AESGCM::encrypt($kek, $iv, $cek, null);
36
        $additional_headers['tag'] = Base64Url::encode($tag);
37
38
        return $encrypted_cek;
39
    }
40
41
    /**
42
     * {@inheritdoc}
43
     */
44
    public function unwrapKey(JWKInterface $key, $encrypted_cek, array $header)
45
    {
46
        $this->checkKey($key);
47
        $this->checkAdditionalParameters($header);
48
49
        $kek = Base64Url::decode($key->get('k'));
50
        $tag = Base64Url::decode($header['tag']);
51
        $iv = Base64Url::decode($header['iv']);
52
53
        if (version_compare(PHP_VERSION, '7.1.0') >= 0) {
54
            return openssl_decrypt($encrypted_cek, $this->getMode($kek), $kek, OPENSSL_RAW_DATA, $iv, $tag, null);
55
        } elseif (class_exists('\Crypto\Cipher')) {
56
            $cipher = Cipher::aes(Cipher::MODE_GCM, $this->getKeySize());
57
            $cipher->setTag($tag);
58
            $cipher->setAAD(null);
59
60
            $cek = $cipher->decrypt($encrypted_cek, $kek, $iv);
61
62
            return $cek;
63
        }
64
65
        return AESGCM::decrypt($kek, $iv, $encrypted_cek, null, $tag);
66
    }
67
68
    /**
69
     * @param string $k
70
     *
71
     * @return string
72
     */
73
    private function getMode($k)
74
    {
75
        return 'aes-'.(8 * mb_strlen($k, '8bit')).'-gcm';
76
    }
77
78
    /**
79
     * {@inheritdoc}
80
     */
81
    public function getKeyManagementMode()
82
    {
83
        return self::MODE_WRAP;
84
    }
85
86
    /**
87
     * @param JWKInterface $key
88
     */
89
    protected function checkKey(JWKInterface $key)
90
    {
91
        Assertion::eq($key->get('kty'), 'oct', 'Wrong key type.');
92
        Assertion::true($key->has('k'), 'The key parameter "k" is missing.');
93
    }
94
95
    /**
96
     * @param array $header
97
     */
98
    protected function checkAdditionalParameters(array $header)
99
    {
100
        Assertion::keyExists($header, 'iv', 'Parameter "iv" is missing.');
101
        Assertion::keyExists($header, 'tag', 'Parameter "tag" is missing.');
102
    }
103
104
    /**
105
     * @return int
106
     */
107
    abstract protected function getKeySize();
108
}
109