You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

KeyManager.php 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
  6. * @author Bjoern Schiessle <bjoern@schiessle.org>
  7. * @author Björn Schießle <bjoern@schiessle.org>
  8. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  9. * @author Clark Tomlinson <fallen013@gmail.com>
  10. * @author Julius Härtl <jus@bitgrid.net>
  11. * @author Lukas Reschke <lukas@statuscode.ch>
  12. * @author Morris Jobke <hey@morrisjobke.de>
  13. * @author Roeland Jago Douma <roeland@famdouma.nl>
  14. * @author Thomas Müller <thomas.mueller@tmit.eu>
  15. * @author Vincent Petry <vincent@nextcloud.com>
  16. *
  17. * @license AGPL-3.0
  18. *
  19. * This code is free software: you can redistribute it and/or modify
  20. * it under the terms of the GNU Affero General Public License, version 3,
  21. * as published by the Free Software Foundation.
  22. *
  23. * This program is distributed in the hope that it will be useful,
  24. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  26. * GNU Affero General Public License for more details.
  27. *
  28. * You should have received a copy of the GNU Affero General Public License, version 3,
  29. * along with this program. If not, see <http://www.gnu.org/licenses/>
  30. *
  31. */
  32. namespace OCA\Encryption;
  33. use OC\Encryption\Exceptions\DecryptionFailedException;
  34. use OC\Files\View;
  35. use OCA\Encryption\Crypto\Crypt;
  36. use OCA\Encryption\Crypto\Encryption;
  37. use OCA\Encryption\Exceptions\PrivateKeyMissingException;
  38. use OCA\Encryption\Exceptions\PublicKeyMissingException;
  39. use OCP\Encryption\Keys\IStorage;
  40. use OCP\IConfig;
  41. use OCP\ILogger;
  42. use OCP\IUserSession;
  43. use OCP\Lock\ILockingProvider;
  44. class KeyManager {
  45. /**
  46. * @var Session
  47. */
  48. protected $session;
  49. /**
  50. * @var IStorage
  51. */
  52. private $keyStorage;
  53. /**
  54. * @var Crypt
  55. */
  56. private $crypt;
  57. /**
  58. * @var string
  59. */
  60. private $recoveryKeyId;
  61. /**
  62. * @var string
  63. */
  64. private $publicShareKeyId;
  65. /**
  66. * @var string
  67. */
  68. private $masterKeyId;
  69. /**
  70. * @var string UserID
  71. */
  72. private $keyId;
  73. /**
  74. * @var string
  75. */
  76. private $publicKeyId = 'publicKey';
  77. /**
  78. * @var string
  79. */
  80. private $privateKeyId = 'privateKey';
  81. /**
  82. * @var string
  83. */
  84. private $shareKeyId = 'shareKey';
  85. /**
  86. * @var string
  87. */
  88. private $fileKeyId = 'fileKey';
  89. /**
  90. * @var IConfig
  91. */
  92. private $config;
  93. /**
  94. * @var ILogger
  95. */
  96. private $log;
  97. /**
  98. * @var Util
  99. */
  100. private $util;
  101. /**
  102. * @var ILockingProvider
  103. */
  104. private $lockingProvider;
  105. /**
  106. * @param IStorage $keyStorage
  107. * @param Crypt $crypt
  108. * @param IConfig $config
  109. * @param IUserSession $userSession
  110. * @param Session $session
  111. * @param ILogger $log
  112. * @param Util $util
  113. */
  114. public function __construct(
  115. IStorage $keyStorage,
  116. Crypt $crypt,
  117. IConfig $config,
  118. IUserSession $userSession,
  119. Session $session,
  120. ILogger $log,
  121. Util $util,
  122. ILockingProvider $lockingProvider
  123. ) {
  124. $this->util = $util;
  125. $this->session = $session;
  126. $this->keyStorage = $keyStorage;
  127. $this->crypt = $crypt;
  128. $this->config = $config;
  129. $this->log = $log;
  130. $this->lockingProvider = $lockingProvider;
  131. $this->recoveryKeyId = $this->config->getAppValue('encryption',
  132. 'recoveryKeyId');
  133. if (empty($this->recoveryKeyId)) {
  134. $this->recoveryKeyId = 'recoveryKey_' . substr(md5(time()), 0, 8);
  135. $this->config->setAppValue('encryption',
  136. 'recoveryKeyId',
  137. $this->recoveryKeyId);
  138. }
  139. $this->publicShareKeyId = $this->config->getAppValue('encryption',
  140. 'publicShareKeyId');
  141. if (empty($this->publicShareKeyId)) {
  142. $this->publicShareKeyId = 'pubShare_' . substr(md5(time()), 0, 8);
  143. $this->config->setAppValue('encryption', 'publicShareKeyId', $this->publicShareKeyId);
  144. }
  145. $this->masterKeyId = $this->config->getAppValue('encryption',
  146. 'masterKeyId');
  147. if (empty($this->masterKeyId)) {
  148. $this->masterKeyId = 'master_' . substr(md5(time()), 0, 8);
  149. $this->config->setAppValue('encryption', 'masterKeyId', $this->masterKeyId);
  150. }
  151. $this->keyId = $userSession && $userSession->isLoggedIn() ? $userSession->getUser()->getUID() : false;
  152. $this->log = $log;
  153. }
  154. /**
  155. * check if key pair for public link shares exists, if not we create one
  156. */
  157. public function validateShareKey() {
  158. $shareKey = $this->getPublicShareKey();
  159. if (empty($shareKey)) {
  160. $this->lockingProvider->acquireLock('encryption-generateSharedKey', ILockingProvider::LOCK_EXCLUSIVE, 'Encryption: shared key generation');
  161. try {
  162. $keyPair = $this->crypt->createKeyPair();
  163. // Save public key
  164. $this->keyStorage->setSystemUserKey(
  165. $this->publicShareKeyId . '.' . $this->publicKeyId, $keyPair['publicKey'],
  166. Encryption::ID);
  167. // Encrypt private key empty passphrase
  168. $encryptedKey = $this->crypt->encryptPrivateKey($keyPair['privateKey'], '');
  169. $header = $this->crypt->generateHeader();
  170. $this->setSystemPrivateKey($this->publicShareKeyId, $header . $encryptedKey);
  171. } catch (\Throwable $e) {
  172. $this->lockingProvider->releaseLock('encryption-generateSharedKey', ILockingProvider::LOCK_EXCLUSIVE);
  173. throw $e;
  174. }
  175. $this->lockingProvider->releaseLock('encryption-generateSharedKey', ILockingProvider::LOCK_EXCLUSIVE);
  176. }
  177. }
  178. /**
  179. * check if a key pair for the master key exists, if not we create one
  180. */
  181. public function validateMasterKey() {
  182. if ($this->util->isMasterKeyEnabled() === false) {
  183. return;
  184. }
  185. $publicMasterKey = $this->getPublicMasterKey();
  186. $privateMasterKey = $this->getPrivateMasterKey();
  187. if (empty($publicMasterKey) && empty($privateMasterKey)) {
  188. // There could be a race condition here if two requests would trigger
  189. // the generation the second one would enter the key generation as long
  190. // as the first one didn't write the key to the keystorage yet
  191. $this->lockingProvider->acquireLock('encryption-generateMasterKey', ILockingProvider::LOCK_EXCLUSIVE, 'Encryption: master key generation');
  192. try {
  193. $keyPair = $this->crypt->createKeyPair();
  194. // Save public key
  195. $this->keyStorage->setSystemUserKey(
  196. $this->masterKeyId . '.' . $this->publicKeyId, $keyPair['publicKey'],
  197. Encryption::ID);
  198. // Encrypt private key with system password
  199. $encryptedKey = $this->crypt->encryptPrivateKey($keyPair['privateKey'], $this->getMasterKeyPassword(), $this->masterKeyId);
  200. $header = $this->crypt->generateHeader();
  201. $this->setSystemPrivateKey($this->masterKeyId, $header . $encryptedKey);
  202. } catch (\Throwable $e) {
  203. $this->lockingProvider->releaseLock('encryption-generateMasterKey', ILockingProvider::LOCK_EXCLUSIVE);
  204. throw $e;
  205. }
  206. $this->lockingProvider->releaseLock('encryption-generateMasterKey', ILockingProvider::LOCK_EXCLUSIVE);
  207. } elseif (empty($publicMasterKey)) {
  208. $this->log->error('A private master key is available but the public key could not be found. This should never happen.');
  209. return;
  210. } elseif (empty($privateMasterKey)) {
  211. $this->log->error('A public master key is available but the private key could not be found. This should never happen.');
  212. return;
  213. }
  214. if (!$this->session->isPrivateKeySet()) {
  215. $masterKey = $this->getSystemPrivateKey($this->masterKeyId);
  216. $decryptedMasterKey = $this->crypt->decryptPrivateKey($masterKey, $this->getMasterKeyPassword(), $this->masterKeyId);
  217. $this->session->setPrivateKey($decryptedMasterKey);
  218. }
  219. // after the encryption key is available we are ready to go
  220. $this->session->setStatus(Session::INIT_SUCCESSFUL);
  221. }
  222. /**
  223. * @return bool
  224. */
  225. public function recoveryKeyExists() {
  226. $key = $this->getRecoveryKey();
  227. return !empty($key);
  228. }
  229. /**
  230. * get recovery key
  231. *
  232. * @return string
  233. */
  234. public function getRecoveryKey() {
  235. return $this->keyStorage->getSystemUserKey($this->recoveryKeyId . '.' . $this->publicKeyId, Encryption::ID);
  236. }
  237. /**
  238. * get recovery key ID
  239. *
  240. * @return string
  241. */
  242. public function getRecoveryKeyId() {
  243. return $this->recoveryKeyId;
  244. }
  245. /**
  246. * @param string $password
  247. * @return bool
  248. */
  249. public function checkRecoveryPassword($password) {
  250. $recoveryKey = $this->keyStorage->getSystemUserKey($this->recoveryKeyId . '.' . $this->privateKeyId, Encryption::ID);
  251. $decryptedRecoveryKey = $this->crypt->decryptPrivateKey($recoveryKey, $password);
  252. if ($decryptedRecoveryKey) {
  253. return true;
  254. }
  255. return false;
  256. }
  257. /**
  258. * @param string $uid
  259. * @param string $password
  260. * @param array $keyPair
  261. * @return bool
  262. */
  263. public function storeKeyPair($uid, $password, $keyPair) {
  264. // Save Public Key
  265. $this->setPublicKey($uid, $keyPair['publicKey']);
  266. $encryptedKey = $this->crypt->encryptPrivateKey($keyPair['privateKey'], $password, $uid);
  267. $header = $this->crypt->generateHeader();
  268. if ($encryptedKey) {
  269. $this->setPrivateKey($uid, $header . $encryptedKey);
  270. return true;
  271. }
  272. return false;
  273. }
  274. /**
  275. * @param string $password
  276. * @param array $keyPair
  277. * @return bool
  278. */
  279. public function setRecoveryKey($password, $keyPair) {
  280. // Save Public Key
  281. $this->keyStorage->setSystemUserKey($this->getRecoveryKeyId().
  282. '.' . $this->publicKeyId,
  283. $keyPair['publicKey'],
  284. Encryption::ID);
  285. $encryptedKey = $this->crypt->encryptPrivateKey($keyPair['privateKey'], $password);
  286. $header = $this->crypt->generateHeader();
  287. if ($encryptedKey) {
  288. $this->setSystemPrivateKey($this->getRecoveryKeyId(), $header . $encryptedKey);
  289. return true;
  290. }
  291. return false;
  292. }
  293. /**
  294. * @param $userId
  295. * @param $key
  296. * @return bool
  297. */
  298. public function setPublicKey($userId, $key) {
  299. return $this->keyStorage->setUserKey($userId, $this->publicKeyId, $key, Encryption::ID);
  300. }
  301. /**
  302. * @param $userId
  303. * @param string $key
  304. * @return bool
  305. */
  306. public function setPrivateKey($userId, $key) {
  307. return $this->keyStorage->setUserKey($userId,
  308. $this->privateKeyId,
  309. $key,
  310. Encryption::ID);
  311. }
  312. /**
  313. * write file key to key storage
  314. *
  315. * @param string $path
  316. * @param string $key
  317. * @return boolean
  318. */
  319. public function setFileKey($path, $key) {
  320. return $this->keyStorage->setFileKey($path, $this->fileKeyId, $key, Encryption::ID);
  321. }
  322. /**
  323. * set all file keys (the file key and the corresponding share keys)
  324. *
  325. * @param string $path
  326. * @param array $keys
  327. */
  328. public function setAllFileKeys($path, $keys) {
  329. $this->setFileKey($path, $keys['data']);
  330. foreach ($keys['keys'] as $uid => $keyFile) {
  331. $this->setShareKey($path, $uid, $keyFile);
  332. }
  333. }
  334. /**
  335. * write share key to the key storage
  336. *
  337. * @param string $path
  338. * @param string $uid
  339. * @param string $key
  340. * @return boolean
  341. */
  342. public function setShareKey($path, $uid, $key) {
  343. $keyId = $uid . '.' . $this->shareKeyId;
  344. return $this->keyStorage->setFileKey($path, $keyId, $key, Encryption::ID);
  345. }
  346. /**
  347. * Decrypt private key and store it
  348. *
  349. * @param string $uid user id
  350. * @param string $passPhrase users password
  351. * @return boolean
  352. */
  353. public function init($uid, $passPhrase) {
  354. $this->session->setStatus(Session::INIT_EXECUTED);
  355. try {
  356. if ($this->util->isMasterKeyEnabled()) {
  357. $uid = $this->getMasterKeyId();
  358. $passPhrase = $this->getMasterKeyPassword();
  359. $privateKey = $this->getSystemPrivateKey($uid);
  360. } else {
  361. $privateKey = $this->getPrivateKey($uid);
  362. }
  363. $privateKey = $this->crypt->decryptPrivateKey($privateKey, $passPhrase, $uid);
  364. } catch (PrivateKeyMissingException $e) {
  365. return false;
  366. } catch (DecryptionFailedException $e) {
  367. return false;
  368. } catch (\Exception $e) {
  369. $this->log->logException($e, [
  370. 'message' => 'Could not decrypt the private key from user "' . $uid . '"" during login. Assume password change on the user back-end.',
  371. 'level' => ILogger::WARN,
  372. 'app' => 'encryption',
  373. ]);
  374. return false;
  375. }
  376. if ($privateKey) {
  377. $this->session->setPrivateKey($privateKey);
  378. $this->session->setStatus(Session::INIT_SUCCESSFUL);
  379. return true;
  380. }
  381. return false;
  382. }
  383. /**
  384. * @param $userId
  385. * @return string
  386. * @throws PrivateKeyMissingException
  387. */
  388. public function getPrivateKey($userId) {
  389. $privateKey = $this->keyStorage->getUserKey($userId,
  390. $this->privateKeyId, Encryption::ID);
  391. if (strlen($privateKey) !== 0) {
  392. return $privateKey;
  393. }
  394. throw new PrivateKeyMissingException($userId);
  395. }
  396. /**
  397. * @param string $path
  398. * @param $uid
  399. * @return string
  400. */
  401. public function getFileKey($path, $uid) {
  402. if ($uid === '') {
  403. $uid = null;
  404. }
  405. $publicAccess = is_null($uid);
  406. $encryptedFileKey = $this->keyStorage->getFileKey($path, $this->fileKeyId, Encryption::ID);
  407. if (empty($encryptedFileKey)) {
  408. return '';
  409. }
  410. if ($this->util->isMasterKeyEnabled()) {
  411. $uid = $this->getMasterKeyId();
  412. $shareKey = $this->getShareKey($path, $uid);
  413. if ($publicAccess) {
  414. $privateKey = $this->getSystemPrivateKey($uid);
  415. $privateKey = $this->crypt->decryptPrivateKey($privateKey, $this->getMasterKeyPassword(), $uid);
  416. } else {
  417. // when logged in, the master key is already decrypted in the session
  418. $privateKey = $this->session->getPrivateKey();
  419. }
  420. } elseif ($publicAccess) {
  421. // use public share key for public links
  422. $uid = $this->getPublicShareKeyId();
  423. $shareKey = $this->getShareKey($path, $uid);
  424. $privateKey = $this->keyStorage->getSystemUserKey($this->publicShareKeyId . '.' . $this->privateKeyId, Encryption::ID);
  425. $privateKey = $this->crypt->decryptPrivateKey($privateKey);
  426. } else {
  427. $shareKey = $this->getShareKey($path, $uid);
  428. $privateKey = $this->session->getPrivateKey();
  429. }
  430. if ($encryptedFileKey && $shareKey && $privateKey) {
  431. return $this->crypt->multiKeyDecrypt($encryptedFileKey,
  432. $shareKey,
  433. $privateKey);
  434. }
  435. return '';
  436. }
  437. /**
  438. * Get the current version of a file
  439. *
  440. * @param string $path
  441. * @param View $view
  442. * @return int
  443. */
  444. public function getVersion($path, View $view) {
  445. $fileInfo = $view->getFileInfo($path);
  446. if ($fileInfo === false) {
  447. return 0;
  448. }
  449. return $fileInfo->getEncryptedVersion();
  450. }
  451. /**
  452. * Set the current version of a file
  453. *
  454. * @param string $path
  455. * @param int $version
  456. * @param View $view
  457. */
  458. public function setVersion($path, $version, View $view) {
  459. $fileInfo = $view->getFileInfo($path);
  460. if ($fileInfo !== false) {
  461. $cache = $fileInfo->getStorage()->getCache();
  462. $cache->update($fileInfo->getId(), ['encrypted' => $version, 'encryptedVersion' => $version]);
  463. }
  464. }
  465. /**
  466. * get the encrypted file key
  467. *
  468. * @param string $path
  469. * @return string
  470. */
  471. public function getEncryptedFileKey($path) {
  472. $encryptedFileKey = $this->keyStorage->getFileKey($path,
  473. $this->fileKeyId, Encryption::ID);
  474. return $encryptedFileKey;
  475. }
  476. /**
  477. * delete share key
  478. *
  479. * @param string $path
  480. * @param string $keyId
  481. * @return boolean
  482. */
  483. public function deleteShareKey($path, $keyId) {
  484. return $this->keyStorage->deleteFileKey(
  485. $path,
  486. $keyId . '.' . $this->shareKeyId,
  487. Encryption::ID);
  488. }
  489. /**
  490. * @param $path
  491. * @param $uid
  492. * @return mixed
  493. */
  494. public function getShareKey($path, $uid) {
  495. $keyId = $uid . '.' . $this->shareKeyId;
  496. return $this->keyStorage->getFileKey($path, $keyId, Encryption::ID);
  497. }
  498. /**
  499. * check if user has a private and a public key
  500. *
  501. * @param string $userId
  502. * @return bool
  503. * @throws PrivateKeyMissingException
  504. * @throws PublicKeyMissingException
  505. */
  506. public function userHasKeys($userId) {
  507. $privateKey = $publicKey = true;
  508. $exception = null;
  509. try {
  510. $this->getPrivateKey($userId);
  511. } catch (PrivateKeyMissingException $e) {
  512. $privateKey = false;
  513. $exception = $e;
  514. }
  515. try {
  516. $this->getPublicKey($userId);
  517. } catch (PublicKeyMissingException $e) {
  518. $publicKey = false;
  519. $exception = $e;
  520. }
  521. if ($privateKey && $publicKey) {
  522. return true;
  523. } elseif (!$privateKey && !$publicKey) {
  524. return false;
  525. } else {
  526. throw $exception;
  527. }
  528. }
  529. /**
  530. * @param $userId
  531. * @return mixed
  532. * @throws PublicKeyMissingException
  533. */
  534. public function getPublicKey($userId) {
  535. $publicKey = $this->keyStorage->getUserKey($userId, $this->publicKeyId, Encryption::ID);
  536. if (strlen($publicKey) !== 0) {
  537. return $publicKey;
  538. }
  539. throw new PublicKeyMissingException($userId);
  540. }
  541. public function getPublicShareKeyId() {
  542. return $this->publicShareKeyId;
  543. }
  544. /**
  545. * get public key for public link shares
  546. *
  547. * @return string
  548. */
  549. public function getPublicShareKey() {
  550. return $this->keyStorage->getSystemUserKey($this->publicShareKeyId . '.' . $this->publicKeyId, Encryption::ID);
  551. }
  552. /**
  553. * @param string $purpose
  554. * @param string $uid
  555. */
  556. public function backupUserKeys($purpose, $uid) {
  557. $this->keyStorage->backupUserKeys(Encryption::ID, $purpose, $uid);
  558. }
  559. /**
  560. * creat a backup of the users private and public key and then delete it
  561. *
  562. * @param string $uid
  563. */
  564. public function deleteUserKeys($uid) {
  565. $this->deletePublicKey($uid);
  566. $this->deletePrivateKey($uid);
  567. }
  568. /**
  569. * @param $uid
  570. * @return bool
  571. */
  572. public function deletePublicKey($uid) {
  573. return $this->keyStorage->deleteUserKey($uid, $this->publicKeyId, Encryption::ID);
  574. }
  575. /**
  576. * @param string $uid
  577. * @return bool
  578. */
  579. private function deletePrivateKey($uid) {
  580. return $this->keyStorage->deleteUserKey($uid, $this->privateKeyId, Encryption::ID);
  581. }
  582. /**
  583. * @param string $path
  584. * @return bool
  585. */
  586. public function deleteAllFileKeys($path) {
  587. return $this->keyStorage->deleteAllFileKeys($path);
  588. }
  589. /**
  590. * @param array $userIds
  591. * @return array
  592. * @throws PublicKeyMissingException
  593. */
  594. public function getPublicKeys(array $userIds) {
  595. $keys = [];
  596. foreach ($userIds as $userId) {
  597. try {
  598. $keys[$userId] = $this->getPublicKey($userId);
  599. } catch (PublicKeyMissingException $e) {
  600. continue;
  601. }
  602. }
  603. return $keys;
  604. }
  605. /**
  606. * @param string $keyId
  607. * @return string returns openssl key
  608. */
  609. public function getSystemPrivateKey($keyId) {
  610. return $this->keyStorage->getSystemUserKey($keyId . '.' . $this->privateKeyId, Encryption::ID);
  611. }
  612. /**
  613. * @param string $keyId
  614. * @param string $key
  615. * @return string returns openssl key
  616. */
  617. public function setSystemPrivateKey($keyId, $key) {
  618. return $this->keyStorage->setSystemUserKey(
  619. $keyId . '.' . $this->privateKeyId,
  620. $key,
  621. Encryption::ID);
  622. }
  623. /**
  624. * add system keys such as the public share key and the recovery key
  625. *
  626. * @param array $accessList
  627. * @param array $publicKeys
  628. * @param string $uid
  629. * @return array
  630. * @throws PublicKeyMissingException
  631. */
  632. public function addSystemKeys(array $accessList, array $publicKeys, $uid) {
  633. if (!empty($accessList['public'])) {
  634. $publicShareKey = $this->getPublicShareKey();
  635. if (empty($publicShareKey)) {
  636. throw new PublicKeyMissingException($this->getPublicShareKeyId());
  637. }
  638. $publicKeys[$this->getPublicShareKeyId()] = $publicShareKey;
  639. }
  640. if ($this->recoveryKeyExists() &&
  641. $this->util->isRecoveryEnabledForUser($uid)) {
  642. $publicKeys[$this->getRecoveryKeyId()] = $this->getRecoveryKey();
  643. }
  644. return $publicKeys;
  645. }
  646. /**
  647. * get master key password
  648. *
  649. * @return string
  650. * @throws \Exception
  651. */
  652. public function getMasterKeyPassword() {
  653. $password = $this->config->getSystemValue('secret');
  654. if (empty($password)) {
  655. throw new \Exception('Can not get secret from Nextcloud instance');
  656. }
  657. return $password;
  658. }
  659. /**
  660. * return master key id
  661. *
  662. * @return string
  663. */
  664. public function getMasterKeyId() {
  665. return $this->masterKeyId;
  666. }
  667. /**
  668. * get public master key
  669. *
  670. * @return string
  671. */
  672. public function getPublicMasterKey() {
  673. return $this->keyStorage->getSystemUserKey($this->masterKeyId . '.' . $this->publicKeyId, Encryption::ID);
  674. }
  675. /**
  676. * get public master key
  677. *
  678. * @return string
  679. */
  680. public function getPrivateMasterKey() {
  681. return $this->keyStorage->getSystemUserKey($this->masterKeyId . '.' . $this->privateKeyId, Encryption::ID);
  682. }
  683. }