Completed
Push — master ( d32900...5d9144 )
by Florent
02:42
created

AESGCMKW::unwrapKey()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 1
Metric Value
c 2
b 1
f 1
dl 0
loc 23
rs 9.0856
cc 3
eloc 15
nc 3
nop 3
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 Base64Url\Base64Url;
15
use Crypto\Cipher;
16
use Jose\Object\JWKInterface;
17
use Jose\Util\GCM;
18
use Jose\Util\StringUtil;
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 = StringUtil::generateRandomBytes(96 / 8);
33
        $additional_headers['iv'] = Base64Url::encode($iv);
34
35
        if (class_exists('\Crypto\Cipher')) {
36
            $cipher = Cipher::aes(Cipher::MODE_GCM, $this->getKeySize());
37
            $cipher->setAAD(null);
38
            $encrypted_cek = $cipher->encrypt($cek, $kek, $iv);
39
40
            $additional_headers['tag'] = Base64Url::encode($cipher->getTag());
41
        } elseif (version_compare(PHP_VERSION, '7.1.0') >= 0) {
42
            $encrypted_cek = openssl_encrypt($cek, $this->getMode($kek), $kek, OPENSSL_RAW_DATA, $iv, $tag , null, 16);
0 ignored issues
show
Bug introduced by
The variable $tag seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
43
            $additional_headers['tag'] = Base64Url::encode($tag);
0 ignored issues
show
Bug introduced by
The variable $tag seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
44
        } else {
45
            list($encrypted_cek, $tag) = GCM::encrypt($kek, $iv, $cek, null);
46
            $additional_headers['tag'] = Base64Url::encode($tag);
47
        }
48
49
        return $encrypted_cek;
50
    }
51
52
    /**
53
     * {@inheritdoc}
54
     */
55
    public function unwrapKey(JWKInterface $key, $encrypted_cek, array $header)
56
    {
57
        $this->checkKey($key);
58
        $this->checkAdditionalParameters($header);
59
        
60
        $kek = Base64Url::decode($key->get('k'));
61
        $tag = Base64Url::decode($header['tag']);
62
        $iv = Base64Url::decode($header['iv']);
63
64
        if (class_exists('\Crypto\Cipher')) {
65
            $cipher = Cipher::aes(Cipher::MODE_GCM, $this->getKeySize());
66
            $cipher->setTag($tag);
67
            $cipher->setAAD(null);
68
69
            $cek = $cipher->decrypt($encrypted_cek, $kek, $iv);
70
71
            return $cek;
72
        } elseif (version_compare(PHP_VERSION, '7.1.0') >= 0) {
73
            return openssl_decrypt($cek, $this->getMode($kek), $kek, OPENSSL_RAW_DATA, $iv, $tag , null);
0 ignored issues
show
Bug introduced by
The variable $cek seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
74
        }
75
76
        return GCM::decrypt($kek, $iv, $encrypted_cek, null, $tag);
77
    }
78
79
    /**
80
     * @param string $k
81
     *
82
     * @return string
83
     */
84
    private function getMode($k)
85
    {
86
        return 'aes-'.(8 *  strlen($k)).'-gcm';
87
    }
88
89
    /**
90
     * {@inheritdoc}
91
     */
92
    public function getKeyManagementMode()
93
    {
94
        return self::MODE_WRAP;
95
    }
96
97
    /**
98
     * @param JWKInterface $key
99
     */
100
    protected function checkKey(JWKInterface $key)
101
    {
102
        if ('oct' !== $key->get('kty') || !$key->has('k')) {
103
            throw new \InvalidArgumentException('The key is not valid');
104
        }
105
    }
106
107
    /**
108
     * @param array $header
109
     */
110
    protected function checkAdditionalParameters(array $header)
111
    {
112
        if (!array_key_exists('iv', $header) || !array_key_exists('tag', $header)) {
113
            throw new \InvalidArgumentException("Missing parameters 'iv' or 'tag'.");
114
        }
115
    }
116
117
    /**
118
     * @return int
119
     */
120
    abstract protected function getKeySize();
121
}
122