Completed
Push — stable8.2 ( 458a90...47a1fb )
by Morris
115:41
created

KeyManager::deletePublicKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2
Metric Value
dl 0
loc 3
ccs 0
cts 2
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 2
1
<?php
2
/**
3
 * @author Björn Schießle <[email protected]>
4
 * @author Clark Tomlinson <[email protected]>
5
 * @author Thomas Müller <[email protected]>
6
 *
7
 * @copyright Copyright (c) 2015, ownCloud, Inc.
8
 * @license AGPL-3.0
9
 *
10
 * This code is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU Affero General Public License, version 3,
12
 * as published by the Free Software Foundation.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
 * GNU Affero General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Affero General Public License, version 3,
20
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
21
 *
22
 */
23
namespace OCA\Encryption;
24
25
use OC\Encryption\Exceptions\DecryptionFailedException;
26
use OCA\Encryption\Crypto\Encryption;
27
use OCA\Encryption\Exceptions\PrivateKeyMissingException;
28
use OCA\Encryption\Exceptions\PublicKeyMissingException;
29
use OCA\Encryption\Crypto\Crypt;
30
use OCP\Encryption\Keys\IStorage;
31
use OCP\IConfig;
32
use OCP\ILogger;
33
use OCP\IUserSession;
34
35
class KeyManager {
36
37
	/**
38
	 * @var Session
39
	 */
40
	protected $session;
41
	/**
42
	 * @var IStorage
43
	 */
44
	private $keyStorage;
45
	/**
46
	 * @var Crypt
47
	 */
48
	private $crypt;
49
	/**
50
	 * @var string
51
	 */
52
	private $recoveryKeyId;
53
	/**
54
	 * @var string
55
	 */
56
	private $publicShareKeyId;
57
	/**
58
	 * @var string
59
	 */
60
	private $masterKeyId;
61
	/**
62
	 * @var string UserID
63
	 */
64
	private $keyId;
65
	/**
66
	 * @var string
67
	 */
68
	private $publicKeyId = 'publicKey';
69
	/**
70
	 * @var string
71
	 */
72
	private $privateKeyId = 'privateKey';
73
74
	/**
75
	 * @var string
76
	 */
77
	private $shareKeyId = 'shareKey';
78
79
	/**
80
	 * @var string
81
	 */
82
	private $fileKeyId = 'fileKey';
83
	/**
84
	 * @var IConfig
85
	 */
86
	private $config;
87
	/**
88
	 * @var ILogger
89
	 */
90
	private $log;
91
	/**
92
	 * @var Util
93
	 */
94
	private $util;
95
96
	/**
97
	 * @param IStorage $keyStorage
98
	 * @param Crypt $crypt
99
	 * @param IConfig $config
100
	 * @param IUserSession $userSession
101
	 * @param Session $session
102
	 * @param ILogger $log
103
	 * @param Util $util
104
	 */
105 42
	public function __construct(
106
		IStorage $keyStorage,
107
		Crypt $crypt,
108
		IConfig $config,
109
		IUserSession $userSession,
110
		Session $session,
111
		ILogger $log,
112
		Util $util
113
	) {
114
115 42
		$this->util = $util;
116 42
		$this->session = $session;
117 42
		$this->keyStorage = $keyStorage;
118 42
		$this->crypt = $crypt;
119 42
		$this->config = $config;
120 42
		$this->log = $log;
121
122 42
		$this->recoveryKeyId = $this->config->getAppValue('encryption',
123 42
			'recoveryKeyId');
124 42
		if (empty($this->recoveryKeyId)) {
125
			$this->recoveryKeyId = 'recoveryKey_' . substr(md5(time()), 0, 8);
126
			$this->config->setAppValue('encryption',
127
				'recoveryKeyId',
128
				$this->recoveryKeyId);
129
		}
130
131 42
		$this->publicShareKeyId = $this->config->getAppValue('encryption',
132 42
			'publicShareKeyId');
133 42 View Code Duplication
		if (empty($this->publicShareKeyId)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
134
			$this->publicShareKeyId = 'pubShare_' . substr(md5(time()), 0, 8);
135
			$this->config->setAppValue('encryption', 'publicShareKeyId', $this->publicShareKeyId);
136
		}
137
138 42
		$this->masterKeyId = $this->config->getAppValue('encryption',
139 42
			'masterKeyId');
140 42 View Code Duplication
		if (empty($this->masterKeyId)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
141
			$this->masterKeyId = 'master_' . substr(md5(time()), 0, 8);
142
			$this->config->setAppValue('encryption', 'masterKeyId', $this->masterKeyId);
143
		}
144
145 42
		$this->keyId = $userSession && $userSession->isLoggedIn() ? $userSession->getUser()->getUID() : false;
146 42
		$this->log = $log;
147 42
	}
148
149
	/**
150
	 * check if key pair for public link shares exists, if not we create one
151
	 */
152 5 View Code Duplication
	public function validateShareKey() {
153 5
		$shareKey = $this->getPublicShareKey();
154 5
		if (empty($shareKey)) {
155 1
			$keyPair = $this->crypt->createKeyPair();
156
157
			// Save public key
158 1
			$this->keyStorage->setSystemUserKey(
159 1
				$this->publicShareKeyId . '.publicKey', $keyPair['publicKey'],
160 1
				Encryption::ID);
161
162
			// Encrypt private key empty passphrase
163 1
			$encryptedKey = $this->crypt->encryptPrivateKey($keyPair['privateKey'], '');
164 1
			$header = $this->crypt->generateHeader();
165 1
			$this->setSystemPrivateKey($this->publicShareKeyId, $header . $encryptedKey);
166 1
		}
167 5
	}
168
169
	/**
170
	 * check if a key pair for the master key exists, if not we create one
171
	 */
172 7 View Code Duplication
	public function validateMasterKey() {
173 7
		$masterKey = $this->getPublicMasterKey();
174 7
		if (empty($masterKey)) {
175 2
			$keyPair = $this->crypt->createKeyPair();
176
177
			// Save public key
178 2
			$this->keyStorage->setSystemUserKey(
179 2
				$this->masterKeyId . '.publicKey', $keyPair['publicKey'],
180 2
				Encryption::ID);
181
182
			// Encrypt private key with system password
183 2
			$encryptedKey = $this->crypt->encryptPrivateKey($keyPair['privateKey'], $this->getMasterKeyPassword(), $this->masterKeyId);
184 2
			$header = $this->crypt->generateHeader();
185 2
			$this->setSystemPrivateKey($this->masterKeyId, $header . $encryptedKey);
186 2
		}
187 7
	}
188
189
	/**
190
	 * @return bool
191
	 */
192 10
	public function recoveryKeyExists() {
193 10
		$key = $this->getRecoveryKey();
194 10
		return (!empty($key));
195
	}
196
197
	/**
198
	 * get recovery key
199
	 *
200
	 * @return string
201
	 */
202 10
	public function getRecoveryKey() {
203 10
		return $this->keyStorage->getSystemUserKey($this->recoveryKeyId . '.publicKey', Encryption::ID);
204
	}
205
206
	/**
207
	 * get recovery key ID
208
	 *
209
	 * @return string
210
	 */
211 3
	public function getRecoveryKeyId() {
212 3
		return $this->recoveryKeyId;
213
	}
214
215
	/**
216
	 * @param $password
217
	 * @return bool
218
	 */
219 1
	public function checkRecoveryPassword($password) {
220 1
		$recoveryKey = $this->keyStorage->getSystemUserKey($this->recoveryKeyId . '.privateKey', Encryption::ID);
221 1
		$decryptedRecoveryKey = $this->crypt->decryptPrivateKey($recoveryKey, $password);
222
223 1
		if ($decryptedRecoveryKey) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $decryptedRecoveryKey of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
224 1
			return true;
225
		}
226
		return false;
227
	}
228
229
	/**
230
	 * @param string $uid
231
	 * @param string $password
232
	 * @param string $keyPair
233
	 * @return bool
234
	 */
235 5
	public function storeKeyPair($uid, $password, $keyPair) {
236
		// Save Public Key
237 5
		$this->setPublicKey($uid, $keyPair['publicKey']);
238
239 5
		$encryptedKey = $this->crypt->encryptPrivateKey($keyPair['privateKey'], $password, $uid);
240
241 5
		$header = $this->crypt->generateHeader();
242
243 5
		if ($encryptedKey) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $encryptedKey of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
244 5
			$this->setPrivateKey($uid, $header . $encryptedKey);
245 5
			return true;
246
		}
247
		return false;
248
	}
249
250
	/**
251
	 * @param string $password
252
	 * @param array $keyPair
253
	 * @return bool
254
	 */
255 1
	public function setRecoveryKey($password, $keyPair) {
256
		// Save Public Key
257 1
		$this->keyStorage->setSystemUserKey($this->getRecoveryKeyId().
258 1
			'.publicKey',
259 1
			$keyPair['publicKey'],
260 1
			Encryption::ID);
261
262 1
		$encryptedKey = $this->crypt->encryptPrivateKey($keyPair['privateKey'], $password);
263 1
		$header = $this->crypt->generateHeader();
264
265 1
		if ($encryptedKey) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $encryptedKey of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
266 1
			$this->setSystemPrivateKey($this->getRecoveryKeyId(), $header . $encryptedKey);
267 1
			return true;
268
		}
269
		return false;
270
	}
271
272
	/**
273
	 * @param $userId
274
	 * @param $key
275
	 * @return bool
276
	 */
277 6
	public function setPublicKey($userId, $key) {
278 6
		return $this->keyStorage->setUserKey($userId, $this->publicKeyId, $key, Encryption::ID);
279
	}
280
281
	/**
282
	 * @param $userId
283
	 * @param $key
284
	 * @return bool
285
	 */
286 6
	public function setPrivateKey($userId, $key) {
287 6
		return $this->keyStorage->setUserKey($userId,
288 6
			$this->privateKeyId,
289 6
			$key,
290 6
			Encryption::ID);
291
	}
292
293
	/**
294
	 * write file key to key storage
295
	 *
296
	 * @param string $path
297
	 * @param string $key
298
	 * @return boolean
299
	 */
300 5
	public function setFileKey($path, $key) {
301 5
		return $this->keyStorage->setFileKey($path, $this->fileKeyId, $key, Encryption::ID);
302
	}
303
304
	/**
305
	 * set all file keys (the file key and the corresponding share keys)
306
	 *
307
	 * @param string $path
308
	 * @param array $keys
309
	 */
310 5
	public function setAllFileKeys($path, $keys) {
311 5
		$this->setFileKey($path, $keys['data']);
312 5
		foreach ($keys['keys'] as $uid => $keyFile) {
313 5
			$this->setShareKey($path, $uid, $keyFile);
314 5
		}
315 5
	}
316
317
	/**
318
	 * write share key to the key storage
319
	 *
320
	 * @param string $path
321
	 * @param string $uid
322
	 * @param string $key
323
	 * @return boolean
324
	 */
325 5
	public function setShareKey($path, $uid, $key) {
326 5
		$keyId = $uid . '.' . $this->shareKeyId;
327 5
		return $this->keyStorage->setFileKey($path, $keyId, $key, Encryption::ID);
328
	}
329
330
	/**
331
	 * Decrypt private key and store it
332
	 *
333
	 * @param string $uid userid
334
	 * @param string $passPhrase users password
335
	 * @return boolean
336
	 */
337 7
	public function init($uid, $passPhrase) {
338
339 7
		$this->session->setStatus(Session::INIT_EXECUTED);
340
341
342
		try {
343 7
			if($this->util->isMasterKeyEnabled()) {
344 1
				$uid = $this->getMasterKeyId();
345 1
				$passPhrase = $this->getMasterKeyPassword();
346 1
				$privateKey = $this->getSystemPrivateKey($uid);
347 1
			} else {
348 6
				$privateKey = $this->getPrivateKey($uid);
349
			}
350 7
			$privateKey = $this->crypt->decryptPrivateKey($privateKey, $passPhrase, $uid);
351 7
		} catch (PrivateKeyMissingException $e) {
352
			return false;
353
		} catch (DecryptionFailedException $e) {
354
			return false;
355
		}
356
357 7
		if ($privateKey) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $privateKey of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
358 7
			$this->session->setPrivateKey($privateKey);
359 7
			$this->session->setStatus(Session::INIT_SUCCESSFUL);
360 7
			return true;
361
		}
362
363
		return false;
364
	}
365
366
	/**
367
	 * @param $userId
368
	 * @return mixed
369
	 * @throws PrivateKeyMissingException
370
	 */
371 10 View Code Duplication
	public function getPrivateKey($userId) {
372 10
		$privateKey = $this->keyStorage->getUserKey($userId,
373 10
			$this->privateKeyId, Encryption::ID);
374
375 10
		if (strlen($privateKey) !== 0) {
376 8
			return $privateKey;
377
		}
378 7
		throw new PrivateKeyMissingException($userId);
379
	}
380
381
	/**
382
	 * @param $path
383
	 * @param $uid
384
	 * @return string
385
	 */
386 13
	public function getFileKey($path, $uid) {
387 13
		$encryptedFileKey = $this->keyStorage->getFileKey($path, $this->fileKeyId, Encryption::ID);
388
389 13
		if (is_null($uid)) {
390
			$uid = $this->getPublicShareKeyId();
391
			$shareKey = $this->getShareKey($path, $uid);
392
			$privateKey = $this->keyStorage->getSystemUserKey($this->publicShareKeyId . '.privateKey', Encryption::ID);
393
			$privateKey = $this->crypt->decryptPrivateKey($privateKey);
394
		} else {
395
396 13
			if ($this->util->isMasterKeyEnabled()) {
397 4
				$uid = $this->getMasterKeyId();
398 4
			}
399
400 13
			$shareKey = $this->getShareKey($path, $uid);
401 13
			$privateKey = $this->session->getPrivateKey();
402
		}
403
404 13
		if ($encryptedFileKey && $shareKey && $privateKey) {
405 9
			return $this->crypt->multiKeyDecrypt($encryptedFileKey,
406 9
				$shareKey,
407 9
				$privateKey);
408
		}
409
410 9
		return '';
411
	}
412
413
	/**
414
	 * get the encrypted file key
415
	 *
416
	 * @param $path
417
	 * @return string
418
	 */
419 1
	public function getEncryptedFileKey($path) {
420 1
		$encryptedFileKey = $this->keyStorage->getFileKey($path,
421 1
			$this->fileKeyId, Encryption::ID);
422
423 1
		return $encryptedFileKey;
424
	}
425
426
	/**
427
	 * delete share key
428
	 *
429
	 * @param string $path
430
	 * @param string $keyId
431
	 * @return boolean
432
	 */
433 1
	public function deleteShareKey($path, $keyId) {
434 1
		return $this->keyStorage->deleteFileKey(
435 1
			$path,
436 1
			$keyId . '.' . $this->shareKeyId,
437 1
			Encryption::ID);
438
	}
439
440
441
	/**
442
	 * @param $path
443
	 * @param $uid
444
	 * @return mixed
445
	 */
446 13
	public function getShareKey($path, $uid) {
447 13
		$keyId = $uid . '.' . $this->shareKeyId;
448 13
		return $this->keyStorage->getFileKey($path, $keyId, Encryption::ID);
449
	}
450
451
	/**
452
	 * check if user has a private and a public key
453
	 *
454
	 * @param string $userId
455
	 * @return bool
456
	 * @throws PrivateKeyMissingException
457
	 * @throws PublicKeyMissingException
458
	 */
459 9
	public function userHasKeys($userId) {
460 9
		$privateKey = $publicKey = true;
461
462
		try {
463 9
			$this->getPrivateKey($userId);
464 9
		} catch (PrivateKeyMissingException $e) {
465 7
			$privateKey = false;
466 7
			$exception = $e;
467
		}
468
		try {
469 9
			$this->getPublicKey($userId);
470 9
		} catch (PublicKeyMissingException $e) {
471 7
			$publicKey = false;
472 7
			$exception = $e;
473
		}
474
475 9
		if ($privateKey && $publicKey) {
476 1
			return true;
477 8
		} elseif (!$privateKey && !$publicKey) {
478 6
			return false;
479
		} else {
480 2
			throw $exception;
481
		}
482
	}
483
484
	/**
485
	 * @param $userId
486
	 * @return mixed
487
	 * @throws PublicKeyMissingException
488
	 */
489 10 View Code Duplication
	public function getPublicKey($userId) {
490 10
		$publicKey = $this->keyStorage->getUserKey($userId, $this->publicKeyId, Encryption::ID);
491
492 10
		if (strlen($publicKey) !== 0) {
493 8
			return $publicKey;
494
		}
495 7
		throw new PublicKeyMissingException($userId);
496
	}
497
498 2
	public function getPublicShareKeyId() {
499 2
		return $this->publicShareKeyId;
500
	}
501
502
	/**
503
	 * get public key for public link shares
504
	 *
505
	 * @return string
506
	 */
507 7
	public function getPublicShareKey() {
508 7
		return $this->keyStorage->getSystemUserKey($this->publicShareKeyId . '.publicKey', Encryption::ID);
509
	}
510
511
	/**
512
	 * @param $purpose
513
	 * @param bool $timestamp
514
	 * @param bool $includeUserKeys
515
	 */
516
	public function backupAllKeys($purpose, $timestamp = true, $includeUserKeys = true) {
0 ignored issues
show
Unused Code introduced by
The parameter $purpose is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $timestamp is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $includeUserKeys is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
517
//		$backupDir = $this->keyStorage->;
518
	}
519
520
	/**
521
	 * @param string $uid
522
	 */
523
	public function replaceUserKeys($uid) {
524
		$this->backupAllKeys('password_reset');
525
		$this->deletePublicKey($uid);
526
		$this->deletePrivateKey($uid);
527
	}
528
529
	/**
530
	 * @param $uid
531
	 * @return bool
532
	 */
533
	public function deletePublicKey($uid) {
534
		return $this->keyStorage->deleteUserKey($uid, $this->publicKeyId, Encryption::ID);
535
	}
536
537
	/**
538
	 * @param $uid
539
	 * @return bool
540
	 */
541 1
	private function deletePrivateKey($uid) {
542 1
		return $this->keyStorage->deleteUserKey($uid, $this->privateKeyId, Encryption::ID);
543
	}
544
545 1
	public function deleteAllFileKeys($path) {
546 1
		return $this->keyStorage->deleteAllFileKeys($path);
547
	}
548
549
	/**
550
	 * @param array $userIds
551
	 * @return array
552
	 * @throws PublicKeyMissingException
553
	 */
554
	public function getPublicKeys(array $userIds) {
555
		$keys = [];
556
557
		foreach ($userIds as $userId) {
558
			try {
559
				$keys[$userId] = $this->getPublicKey($userId);
560
			} catch (PublicKeyMissingException $e) {
561
				continue;
562
			}
563
		}
564
565
		return $keys;
566
567
	}
568
569
	/**
570
	 * @param string $keyId
571
	 * @return string returns openssl key
572
	 */
573 1
	public function getSystemPrivateKey($keyId) {
574 1
		return $this->keyStorage->getSystemUserKey($keyId . '.' . $this->privateKeyId, Encryption::ID);
575
	}
576
577
	/**
578
	 * @param string $keyId
579
	 * @param string $key
580
	 * @return string returns openssl key
581
	 */
582 3
	public function setSystemPrivateKey($keyId, $key) {
583 3
		return $this->keyStorage->setSystemUserKey(
584 3
			$keyId . '.' . $this->privateKeyId,
585 3
			$key,
586 3
			Encryption::ID);
587
	}
588
589
	/**
590
	 * add system keys such as the public share key and the recovery key
591
	 *
592
	 * @param array $accessList
593
	 * @param array $publicKeys
594
	 * @param string $uid
595
	 * @return array
596
	 * @throws PublicKeyMissingException
597
	 */
598 9
	public function addSystemKeys(array $accessList, array $publicKeys, $uid) {
599 9
		if (!empty($accessList['public'])) {
600 2
			$publicShareKey = $this->getPublicShareKey();
601 2
			if (empty($publicShareKey)) {
602
				throw new PublicKeyMissingException($this->getPublicShareKeyId());
603
			}
604 2
			$publicKeys[$this->getPublicShareKeyId()] = $publicShareKey;
605 2
		}
606
607 9
		if ($this->recoveryKeyExists() &&
608 9
			$this->util->isRecoveryEnabledForUser($uid)) {
609
610 2
			$publicKeys[$this->getRecoveryKeyId()] = $this->getRecoveryKey();
611 2
		}
612
613 9
		return $publicKeys;
614
	}
615
616
	/**
617
	 * get master key password
618
	 *
619
	 * @return string
620
	 * @throws \Exception
621
	 */
622 3
	protected function getMasterKeyPassword() {
623 3
		$password = $this->config->getSystemValue('secret');
624 3
		if (empty($password)){
625 1
			throw new \Exception('Can not get secret from ownCloud instance');
626
		}
627
628 2
		return $password;
629
	}
630
631
	/**
632
	 * return master key id
633
	 *
634
	 * @return string
635
	 */
636 5
	public function getMasterKeyId() {
637 5
		return $this->masterKeyId;
638
	}
639
640
	/**
641
	 * get public master key
642
	 *
643
	 * @return string
644
	 */
645 6
	public function getPublicMasterKey() {
646 6
		return $this->keyStorage->getSystemUserKey($this->masterKeyId . '.publicKey', Encryption::ID);
647
	}
648
}
649