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 ( e7c776...4b2105 )
by Joni
05:35
created

JWE   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 282
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 10

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 0 Features 1
Metric Value
wmc 23
c 2
b 0
f 1
lcom 2
cbo 10
dl 0
loc 282
ccs 85
cts 85
cp 1
rs 10

14 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A fromCompact() 0 3 1
A fromParts() 0 12 2
B encrypt() 0 24 5
B _encryptContent() 0 27 4
A decrypt() 0 14 2
A decryptWithJWK() 0 7 1
A header() 0 3 1
A encryptedKey() 0 3 1
A initializationVector() 0 3 1
A ciphertext() 0 3 1
A authenticationTag() 0 3 1
A toCompact() 0 7 1
A __toString() 0 3 1
1
<?php
2
3
namespace JWX\JWE;
4
5
use JWX\JWE\CompressionAlgorithm\CompressionFactory;
6
use JWX\JWE\EncryptionAlgorithm\EncryptionAlgorithmFactory;
7
use JWX\JWE\KeyAlgorithm\KeyAlgorithmFactory;
8
use JWX\JWK\JWK;
9
use JWX\JWT\Header\Header;
10
use JWX\JWT\Header\JOSE;
11
use JWX\Util\Base64;
12
13
14
/**
15
 * Class to represent JWE structure.
16
 *
17
 * @link https://tools.ietf.org/html/rfc7516#section-3
18
 */
19
class JWE
20
{
21
	/**
22
	 * Protected header.
23
	 *
24
	 * @var Header $_protectedHeader
25
	 */
26
	protected $_protectedHeader;
27
	
28
	/**
29
	 * Encrypted key.
30
	 *
31
	 * @var string $_encryptedKey
32
	 */
33
	protected $_encryptedKey;
34
	
35
	/**
36
	 * Initialization vector.
37
	 *
38
	 * @var string
39
	 */
40
	protected $_iv;
41
	
42
	/**
43
	 * Additional authenticated data.
44
	 *
45
	 * @var string $_aad
46
	 */
47
	protected $_aad;
48
	
49
	/**
50
	 * Ciphertext.
51
	 *
52
	 * @var string $_ciphertext
53
	 */
54
	protected $_ciphertext;
55
	
56
	/**
57
	 * Authentication tag.
58
	 *
59
	 * @var string $_authenticationTag
60
	 */
61
	protected $_authenticationTag;
62
	
63
	/**
64
	 * Constructor
65
	 *
66
	 * @param Header $protected_header JWE Protected Header
67
	 * @param string $encrypted_key Encrypted key
68
	 * @param string $iv Initialization vector
69
	 * @param string $ciphertext Ciphertext
70
	 * @param string $auth_tag Authentication tag
71
	 * @param string|null $aad Additional authenticated data
72
	 */
73 24
	public function __construct(Header $protected_header, $encrypted_key, $iv, 
74
			$ciphertext, $auth_tag, $aad = null) {
75 24
		$this->_protectedHeader = $protected_header;
76 24
		$this->_encryptedKey = $encrypted_key;
77 24
		$this->_iv = $iv;
78 24
		$this->_aad = $aad;
79 24
		$this->_ciphertext = $ciphertext;
80 24
		$this->_authenticationTag = $auth_tag;
81 24
	}
82
	
83
	/**
84
	 * Initialize from compact serialization.
85
	 *
86
	 * @param string $data
87
	 * @return self
88
	 */
89 6
	public static function fromCompact($data) {
90 6
		return self::fromParts(explode(".", $data));
91
	}
92
	
93
	/**
94
	 * Initialize from parts of compact serialization.
95
	 *
96
	 * @param array $parts
97
	 * @throws \UnexpectedValueException
98
	 * @return self
99
	 */
100 12
	public static function fromParts(array $parts) {
101 12
		if (count($parts) != 5) {
102 1
			throw new \UnexpectedValueException(
103 1
				"Invalid JWE compact serialization.");
104
		}
105 11
		$header = Header::fromJSON(Base64::urlDecode($parts[0]));
106 11
		$encrypted_key = Base64::urlDecode($parts[1]);
107 11
		$iv = Base64::urlDecode($parts[2]);
108 11
		$ciphertext = Base64::urlDecode($parts[3]);
109 11
		$auth_tag = Base64::urlDecode($parts[4]);
110 11
		return new self($header, $encrypted_key, $iv, $ciphertext, $auth_tag);
111
	}
112
	
113
	/**
114
	 * Initialize by encrypting the given payload.
115
	 *
116
	 * @param string $payload Payload
117
	 * @param KeyManagementAlgorithm $key_algo Key management algorithm
118
	 * @param ContentEncryptionAlgorithm $enc_algo Content encryption algorithm
119
	 * @param CompressionAlgorithm|null $zip_algo Optional compression algorithm
120
	 * @param Header|null $header Optional desired header. Algorithm specific
121
	 *        parameters are automatically added.
122
	 * @param string|null $cek Optional content encryption key. Randomly
123
	 *        generated if not set.
124
	 * @param string|null $iv Optional initialization vector. Randomly generated
125
	 *        if not set.
126
	 * @throws \RuntimeException If encrypt fails
127
	 * @return self
128
	 */
129 16
	public static function encrypt($payload, KeyManagementAlgorithm $key_algo, 
130
			ContentEncryptionAlgorithm $enc_algo, 
131
			CompressionAlgorithm $zip_algo = null, Header $header = null, $cek = null, 
132
			$iv = null) {
133
		// if header was not given, initialize empty
134 16
		if (!isset($header)) {
135 7
			$header = new Header();
136 7
		}
137
		// generate random CEK
138 16
		if (!isset($cek)) {
139 8
			$cek = $key_algo->cekForEncryption($enc_algo->keySize());
140 8
		}
141
		// generate random IV
142 16
		if (!isset($iv)) {
143 7
			$iv = openssl_random_pseudo_bytes($enc_algo->ivSize());
144 7
		}
145
		// compress
146 16
		if (isset($zip_algo)) {
147 3
			$payload = $zip_algo->compress($payload);
148 3
			$header = $header->withParameters(...$zip_algo->headerParameters());
149 3
		}
150 16
		return self::_encryptContent($payload, $cek, $iv, $key_algo, $enc_algo, 
151 16
			$header);
152
	}
153
	
154
	/**
155
	 * Encrypt content with explicit parameters.
156
	 *
157
	 * @param string $plaintext Plaintext content to encrypt
158
	 * @param string $cek Content encryption key
159
	 * @param string $iv Initialization vector
160
	 * @param KeyManagementAlgorithm $key_algo Key management algorithm
161
	 * @param ContentEncryptionAlgorithm $enc_algo Content encryption algorithm
162
	 * @param Header $header Header
163
	 * @throws \UnexpectedValueException
164
	 * @return self
165
	 */
166 16
	private static function _encryptContent($plaintext, $cek, $iv, 
167
			KeyManagementAlgorithm $key_algo, 
168
			ContentEncryptionAlgorithm $enc_algo, Header $header) {
169
		// check that content encryption key has correct size
170 16
		if (strlen($cek) != $enc_algo->keySize()) {
171 1
			throw new \UnexpectedValueException("Invalid key size.");
172
		}
173
		// check that initialization vector has correct size
174 15
		if (strlen($iv) != $enc_algo->ivSize()) {
175 1
			throw new \UnexpectedValueException("Invalid IV size.");
176
		}
177
		// add key and encryption algorithm parameters to the header
178 14
		$header = $header->withParameters(...$key_algo->headerParameters())
179 14
			->withParameters(...$enc_algo->headerParameters());
180
		// encrypt the content encryption key
181 14
		$encrypted_key = $key_algo->encrypt($cek, $header);
182
		// sanity check that header wasn't unset via reference
183 14
		if (!$header instanceof Header) {
184 1
			throw new \RuntimeException("Broken key algorithm.");
185
		}
186
		// additional authenticated data
187 13
		$aad = Base64::urlEncode($header->toJSON());
188
		// encrypt
189 13
		list($ciphertext, $auth_tag) = $enc_algo->encrypt($plaintext, $cek, $iv, 
190 13
			$aad);
191 13
		return new self($header, $encrypted_key, $iv, $ciphertext, $auth_tag);
192
	}
193
	
194
	/**
195
	 * Decrypt content.
196
	 *
197
	 * @param KeyManagementAlgorithm $key_algo
198
	 * @param ContentEncryptionAlgorithm $enc_algo
199
	 * @throws \RuntimeException If decrypt fails
200
	 * @return string Plaintext payload
201
	 */
202 12
	public function decrypt(KeyManagementAlgorithm $key_algo, 
203
			ContentEncryptionAlgorithm $enc_algo) {
204 12
		$cek = $key_algo->decrypt($this->_encryptedKey);
205 12
		$aad = Base64::urlEncode($this->_protectedHeader->toJSON());
206 12
		$payload = $enc_algo->decrypt($this->_ciphertext, $cek, $this->_iv, 
207 12
			$aad, $this->_authenticationTag);
208
		// decompress
209 12
		if ($this->_protectedHeader->hasCompressionAlgorithm()) {
210 2
			$comp_algo_name = $this->_protectedHeader->compressionAlgorithm()->value();
211 2
			$decompressor = CompressionFactory::algoByName($comp_algo_name);
212 2
			$payload = $decompressor->decompress($payload);
213 2
		}
214 12
		return $payload;
215
	}
216
	
217
	/**
218
	 * Decrypt content using given JWK.
219
	 *
220
	 * Key management and content encryption algorithms are determined from the
221
	 * header.
222
	 *
223
	 * @param JWK $jwk JSON Web Key
224
	 * @return string Plaintext payload
225
	 */
226 1
	public function decryptWithJWK(JWK $jwk) {
227 1
		$header = $this->header();
228 1
		$key_algo_factory = new KeyAlgorithmFactory($header);
229 1
		$key_algo = $key_algo_factory->algoByKey($jwk);
230 1
		$enc_algo = EncryptionAlgorithmFactory::algoByHeader($header);
231 1
		return $this->decrypt($key_algo, $enc_algo);
232
	}
233
	
234
	/**
235
	 * Get JOSE header.
236
	 *
237
	 * @return JOSE
238
	 */
239 3
	public function header() {
240 3
		return new JOSE($this->_protectedHeader);
241
	}
242
	
243
	/**
244
	 * Get encrypted CEK.
245
	 *
246
	 * @return string
247
	 */
248 1
	public function encryptedKey() {
249 1
		return $this->_encryptedKey;
250
	}
251
	
252
	/**
253
	 * Get initialization vector.
254
	 *
255
	 * @return string
256
	 */
257 1
	public function initializationVector() {
258 1
		return $this->_iv;
259
	}
260
	
261
	/**
262
	 * Get ciphertext.
263
	 *
264
	 * @return string
265
	 */
266 1
	public function ciphertext() {
267 1
		return $this->_ciphertext;
268
	}
269
	
270
	/**
271
	 * Get authentication tag.
272
	 *
273
	 * @return string
274
	 */
275 1
	public function authenticationTag() {
276 1
		return $this->_authenticationTag;
277
	}
278
	
279
	/**
280
	 * Convert to compact serialization.
281
	 *
282
	 * @return string
283
	 */
284 11
	public function toCompact() {
285 11
		return Base64::urlEncode($this->_protectedHeader->toJSON()) . "." .
286 11
			 Base64::urlEncode($this->_encryptedKey) . "." .
287 11
			 Base64::urlEncode($this->_iv) . "." .
288 11
			 Base64::urlEncode($this->_ciphertext) . "." .
289 11
			 Base64::urlEncode($this->_authenticationTag);
290
	}
291
	
292
	/**
293
	 * Convert JWE to string.
294
	 *
295
	 * @return string
296
	 */
297 1
	public function __toString() {
298 1
		return $this->toCompact();
299
	}
300
}
301