GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( c2df17...4b5a21 )
by Joni
04:10
created

JWE::_encryptContent()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 23
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 3

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 23
ccs 12
cts 12
cp 1
rs 9.0856
cc 3
eloc 14
nc 3
nop 6
crap 3
1
<?php
2
3
namespace JWX\JWE;
4
5
use JWX\JWE\CompressionAlgorithm\CompressionFactory;
6
use JWX\JWT\Header\Header;
7
use JWX\JWT\Header\JOSE;
8
use JWX\Util\Base64;
9
10
11
/**
12
 * Class to represent JWE structure.
13
 *
14
 * @link https://tools.ietf.org/html/rfc7516#section-3
15
 */
16
class JWE
17
{
18
	/**
19
	 * Protected header.
20
	 *
21
	 * @var Header $_protectedHeader
22
	 */
23
	protected $_protectedHeader;
24
	
25
	/**
26
	 * Encrypted key.
27
	 *
28
	 * @var string $_encryptedKey
29
	 */
30
	protected $_encryptedKey;
31
	
32
	/**
33
	 * Initialization vector.
34
	 *
35
	 * @var string
36
	 */
37
	protected $_iv;
38
	
39
	/**
40
	 * Additional authenticated data.
41
	 *
42
	 * @var string $_aad
43
	 */
44
	protected $_aad;
45
	
46
	/**
47
	 * Ciphertext.
48
	 *
49
	 * @var string $_ciphertext
50
	 */
51
	protected $_ciphertext;
52
	
53
	/**
54
	 * Authentication tag.
55
	 *
56
	 * @var string $_authenticationTag
57
	 */
58
	protected $_authenticationTag;
59
	
60
	/**
61
	 * Constructor
62
	 *
63
	 * @param Header $protected_header JWE Protected Header
64
	 * @param string $encrypted_key Encrypted key
65
	 * @param string $iv Initialization vector
66
	 * @param string $ciphertext Ciphertext
67
	 * @param string $auth_tag Authentication tag
68
	 * @param string|null $aad Additional authenticated data
69
	 */
70 24
	public function __construct(Header $protected_header, $encrypted_key, $iv, 
71
			$ciphertext, $auth_tag, $aad = null) {
72 24
		$this->_protectedHeader = $protected_header;
73 24
		$this->_encryptedKey = $encrypted_key;
74 24
		$this->_iv = $iv;
75 24
		$this->_aad = $aad;
76 24
		$this->_ciphertext = $ciphertext;
77 24
		$this->_authenticationTag = $auth_tag;
78 24
	}
79
	
80
	/**
81
	 * Initialize from compact serialization.
82
	 *
83
	 * @param string $data
84
	 * @return self
85
	 */
86 6
	public static function fromCompact($data) {
87 6
		return self::fromParts(explode(".", $data));
88
	}
89
	
90
	/**
91
	 * Initialize from parts of compact serialization.
92
	 *
93
	 * @param array $parts
94
	 * @throws \UnexpectedValueException
95
	 * @return self
96
	 */
97 12
	public static function fromParts(array $parts) {
98 12
		if (count($parts) != 5) {
99 1
			throw new \UnexpectedValueException(
100 1
				"Invalid JWE compact serialization.");
101
		}
102 11
		$header = Header::fromJSON(Base64::urlDecode($parts[0]));
103 11
		$encrypted_key = Base64::urlDecode($parts[1]);
104 11
		$iv = Base64::urlDecode($parts[2]);
105 11
		$ciphertext = Base64::urlDecode($parts[3]);
106 11
		$auth_tag = Base64::urlDecode($parts[4]);
107 11
		return new self($header, $encrypted_key, $iv, $ciphertext, $auth_tag);
108
	}
109
	
110
	/**
111
	 * Initialize by encrypting the given payload.
112
	 *
113
	 * @param string $payload Payload
114
	 * @param KeyManagementAlgorithm $key_algo Key management algorithm
115
	 * @param ContentEncryptionAlgorithm $enc_algo Content encryption algorithm
116
	 * @param CompressionAlgorithm|null $zip_algo Optional compression algorithm
117
	 * @param Header|null $header Optional desired header. Algorithm specific
118
	 *        parameters are automatically added.
119
	 * @param string|null $cek Optional content encryption key. Randomly
120
	 *        generated if not set.
121
	 * @param string|null $iv Optional initialization vector. Randomly generated
122
	 *        if not set.
123
	 * @throws \RuntimeException If encrypt fails
124
	 * @return self
125
	 */
126 15
	public static function encrypt($payload, KeyManagementAlgorithm $key_algo, 
127
			ContentEncryptionAlgorithm $enc_algo, 
128
			CompressionAlgorithm $zip_algo = null, Header $header = null, $cek = null, 
129
			$iv = null) {
130
		// if header was not given, initialize empty
131 15
		if (!isset($header)) {
132 6
			$header = new Header();
133 6
		}
134
		// generate random CEK
135 15
		if (!isset($cek)) {
136 7
			$cek = $key_algo->cekForEncryption($enc_algo->keySize());
137 7
		}
138
		// generate random IV
139 15
		if (!isset($iv)) {
140 6
			$iv = openssl_random_pseudo_bytes($enc_algo->ivSize());
141 6
		}
142
		// compress
143 15
		if (isset($zip_algo)) {
144 3
			$payload = $zip_algo->compress($payload);
145 3
			$header = $header->withParameters(...$zip_algo->headerParameters());
146 3
		}
147 15
		return self::_encryptContent($payload, $cek, $iv, $key_algo, $enc_algo, 
148 15
			$header);
149
	}
150
	
151
	/**
152
	 * Encrypt content with explicit parameters.
153
	 *
154
	 * @param string $plaintext Plaintext content to encrypt
155
	 * @param string $cek Content encryption key
156
	 * @param string $iv Initialization vector
157
	 * @param KeyManagementAlgorithm $key_algo Key management algorithm
158
	 * @param ContentEncryptionAlgorithm $enc_algo Content encryption algorithm
159
	 * @param Header $header Header
160
	 * @throws \UnexpectedValueException
161
	 * @return self
162
	 */
163 15
	private static function _encryptContent($plaintext, $cek, $iv, 
164
			KeyManagementAlgorithm $key_algo, 
165
			ContentEncryptionAlgorithm $enc_algo, Header $header) {
166
		// check that content encryption key has correct size
167 15
		if (strlen($cek) != $enc_algo->keySize()) {
168 1
			throw new \UnexpectedValueException("Invalid key size.");
169
		}
170
		// check that initialization vector has correct size
171 14
		if (strlen($iv) != $enc_algo->ivSize()) {
172 1
			throw new \UnexpectedValueException("Invalid IV size.");
173
		}
174
		// add key and encryption algorithm parameters to the header
175 13
		$header = $header->withParameters(...$key_algo->headerParameters())
176 13
			->withParameters(...$enc_algo->headerParameters());
177
		// encrypt the content encryption key
178 13
		$encrypted_key = $key_algo->encrypt($cek, $header);
179
		// additional authenticated data
180 13
		$aad = Base64::urlEncode($header->toJSON());
181
		// encrypt
182 13
		list($ciphertext, $auth_tag) = $enc_algo->encrypt($plaintext, $cek, $iv, 
183 13
			$aad);
184 13
		return new self($header, $encrypted_key, $iv, $ciphertext, $auth_tag);
0 ignored issues
show
Bug introduced by
It seems like $header can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
185
	}
186
	
187
	/**
188
	 * Decrypt content.
189
	 *
190
	 * @param KeyManagementAlgorithm $key_algo
191
	 * @param ContentEncryptionAlgorithm $enc_algo
192
	 * @throws \RuntimeException If decrypt fails
193
	 * @return string Plaintext payload
194
	 */
195 11
	public function decrypt(KeyManagementAlgorithm $key_algo, 
196
			ContentEncryptionAlgorithm $enc_algo) {
197 11
		$cek = $key_algo->decrypt($this->_encryptedKey);
198 11
		$aad = Base64::urlEncode($this->_protectedHeader->toJSON());
199 11
		$payload = $enc_algo->decrypt($this->_ciphertext, $cek, $this->_iv, 
200 11
			$aad, $this->_authenticationTag);
201
		// decompress
202 11
		if ($this->_protectedHeader->hasCompressionAlgorithm()) {
203 2
			$comp_algo_name = $this->_protectedHeader->compressionAlgorithm()->value();
204 2
			$decompressor = CompressionFactory::algoByName($comp_algo_name);
205 2
			$payload = $decompressor->decompress($payload);
206 2
		}
207 11
		return $payload;
208
	}
209
	
210
	/**
211
	 * Get JOSE header.
212
	 *
213
	 * @return JOSE
214
	 */
215 2
	public function header() {
216 2
		return new JOSE($this->_protectedHeader);
217
	}
218
	
219
	/**
220
	 * Get encrypted CEK.
221
	 *
222
	 * @return string
223
	 */
224 1
	public function encryptedKey() {
225 1
		return $this->_encryptedKey;
226
	}
227
	
228
	/**
229
	 * Get initialization vector.
230
	 *
231
	 * @return string
232
	 */
233 1
	public function initializationVector() {
234 1
		return $this->_iv;
235
	}
236
	
237
	/**
238
	 * Get ciphertext.
239
	 *
240
	 * @return string
241
	 */
242 1
	public function ciphertext() {
243 1
		return $this->_ciphertext;
244
	}
245
	
246
	/**
247
	 * Get authentication tag.
248
	 *
249
	 * @return string
250
	 */
251 1
	public function authenticationTag() {
252 1
		return $this->_authenticationTag;
253
	}
254
	
255
	/**
256
	 * Convert to compact serialization.
257
	 *
258
	 * @return string
259
	 */
260 11
	public function toCompact() {
261 11
		return Base64::urlEncode($this->_protectedHeader->toJSON()) . "." .
262 11
			 Base64::urlEncode($this->_encryptedKey) . "." .
263 11
			 Base64::urlEncode($this->_iv) . "." .
264 11
			 Base64::urlEncode($this->_ciphertext) . "." .
265 11
			 Base64::urlEncode($this->_authenticationTag);
266
	}
267
	
268
	/**
269
	 * Convert JWE to string.
270
	 *
271
	 * @return string
272
	 */
273 1
	public function __toString() {
274 1
		return $this->toCompact();
275
	}
276
}
277