1
0

KeyManager.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  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->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. * @param ?bool $useLegacyFileKey null means try both
  400. * @return string
  401. */
  402. public function getFileKey(string $path, ?string $uid, ?bool $useLegacyFileKey): string {
  403. if ($uid === '') {
  404. $uid = null;
  405. }
  406. $publicAccess = is_null($uid);
  407. $encryptedFileKey = '';
  408. if ($useLegacyFileKey ?? true) {
  409. $encryptedFileKey = $this->keyStorage->getFileKey($path, $this->fileKeyId, Encryption::ID);
  410. if (empty($encryptedFileKey) && $useLegacyFileKey) {
  411. return '';
  412. }
  413. }
  414. if ($this->util->isMasterKeyEnabled()) {
  415. $uid = $this->getMasterKeyId();
  416. $shareKey = $this->getShareKey($path, $uid);
  417. if ($publicAccess) {
  418. $privateKey = $this->getSystemPrivateKey($uid);
  419. $privateKey = $this->crypt->decryptPrivateKey($privateKey, $this->getMasterKeyPassword(), $uid);
  420. } else {
  421. // when logged in, the master key is already decrypted in the session
  422. $privateKey = $this->session->getPrivateKey();
  423. }
  424. } elseif ($publicAccess) {
  425. // use public share key for public links
  426. $uid = $this->getPublicShareKeyId();
  427. $shareKey = $this->getShareKey($path, $uid);
  428. $privateKey = $this->keyStorage->getSystemUserKey($this->publicShareKeyId . '.' . $this->privateKeyId, Encryption::ID);
  429. $privateKey = $this->crypt->decryptPrivateKey($privateKey);
  430. } else {
  431. $shareKey = $this->getShareKey($path, $uid);
  432. $privateKey = $this->session->getPrivateKey();
  433. }
  434. if ($useLegacyFileKey ?? true) {
  435. if ($encryptedFileKey && $shareKey && $privateKey) {
  436. return $this->crypt->multiKeyDecryptLegacy($encryptedFileKey,
  437. $shareKey,
  438. $privateKey);
  439. }
  440. }
  441. if (!($useLegacyFileKey ?? false)) {
  442. if ($shareKey && $privateKey) {
  443. return $this->crypt->multiKeyDecrypt($shareKey, $privateKey);
  444. }
  445. }
  446. return '';
  447. }
  448. /**
  449. * Get the current version of a file
  450. *
  451. * @param string $path
  452. * @param View $view
  453. * @return int
  454. */
  455. public function getVersion($path, View $view) {
  456. $fileInfo = $view->getFileInfo($path);
  457. if ($fileInfo === false) {
  458. return 0;
  459. }
  460. return $fileInfo->getEncryptedVersion();
  461. }
  462. /**
  463. * Set the current version of a file
  464. *
  465. * @param string $path
  466. * @param int $version
  467. * @param View $view
  468. */
  469. public function setVersion($path, $version, View $view) {
  470. $fileInfo = $view->getFileInfo($path);
  471. if ($fileInfo !== false) {
  472. $cache = $fileInfo->getStorage()->getCache();
  473. $cache->update($fileInfo->getId(), ['encrypted' => $version, 'encryptedVersion' => $version]);
  474. }
  475. }
  476. /**
  477. * get the encrypted file key
  478. *
  479. * @param string $path
  480. * @return string
  481. */
  482. public function getEncryptedFileKey($path) {
  483. $encryptedFileKey = $this->keyStorage->getFileKey($path,
  484. $this->fileKeyId, Encryption::ID);
  485. return $encryptedFileKey;
  486. }
  487. /**
  488. * delete share key
  489. *
  490. * @param string $path
  491. * @param string $keyId
  492. * @return boolean
  493. */
  494. public function deleteShareKey($path, $keyId) {
  495. return $this->keyStorage->deleteFileKey(
  496. $path,
  497. $keyId . '.' . $this->shareKeyId,
  498. Encryption::ID);
  499. }
  500. /**
  501. * @param $path
  502. * @param $uid
  503. * @return mixed
  504. */
  505. public function getShareKey($path, $uid) {
  506. $keyId = $uid . '.' . $this->shareKeyId;
  507. return $this->keyStorage->getFileKey($path, $keyId, Encryption::ID);
  508. }
  509. /**
  510. * check if user has a private and a public key
  511. *
  512. * @param string $userId
  513. * @return bool
  514. * @throws PrivateKeyMissingException
  515. * @throws PublicKeyMissingException
  516. */
  517. public function userHasKeys($userId) {
  518. $privateKey = $publicKey = true;
  519. $exception = null;
  520. try {
  521. $this->getPrivateKey($userId);
  522. } catch (PrivateKeyMissingException $e) {
  523. $privateKey = false;
  524. $exception = $e;
  525. }
  526. try {
  527. $this->getPublicKey($userId);
  528. } catch (PublicKeyMissingException $e) {
  529. $publicKey = false;
  530. $exception = $e;
  531. }
  532. if ($privateKey && $publicKey) {
  533. return true;
  534. } elseif (!$privateKey && !$publicKey) {
  535. return false;
  536. } else {
  537. throw $exception;
  538. }
  539. }
  540. /**
  541. * @param $userId
  542. * @return mixed
  543. * @throws PublicKeyMissingException
  544. */
  545. public function getPublicKey($userId) {
  546. $publicKey = $this->keyStorage->getUserKey($userId, $this->publicKeyId, Encryption::ID);
  547. if (strlen($publicKey) !== 0) {
  548. return $publicKey;
  549. }
  550. throw new PublicKeyMissingException($userId);
  551. }
  552. public function getPublicShareKeyId() {
  553. return $this->publicShareKeyId;
  554. }
  555. /**
  556. * get public key for public link shares
  557. *
  558. * @return string
  559. */
  560. public function getPublicShareKey() {
  561. return $this->keyStorage->getSystemUserKey($this->publicShareKeyId . '.' . $this->publicKeyId, Encryption::ID);
  562. }
  563. /**
  564. * @param string $purpose
  565. * @param string $uid
  566. */
  567. public function backupUserKeys($purpose, $uid) {
  568. $this->keyStorage->backupUserKeys(Encryption::ID, $purpose, $uid);
  569. }
  570. /**
  571. * create a backup of the users private and public key and then delete it
  572. *
  573. * @param string $uid
  574. */
  575. public function deleteUserKeys($uid) {
  576. $this->deletePublicKey($uid);
  577. $this->deletePrivateKey($uid);
  578. }
  579. /**
  580. * @param $uid
  581. * @return bool
  582. */
  583. public function deletePublicKey($uid) {
  584. return $this->keyStorage->deleteUserKey($uid, $this->publicKeyId, Encryption::ID);
  585. }
  586. /**
  587. * @param string $uid
  588. * @return bool
  589. */
  590. private function deletePrivateKey($uid) {
  591. return $this->keyStorage->deleteUserKey($uid, $this->privateKeyId, Encryption::ID);
  592. }
  593. /**
  594. * @param string $path
  595. * @return bool
  596. */
  597. public function deleteAllFileKeys($path) {
  598. return $this->keyStorage->deleteAllFileKeys($path);
  599. }
  600. public function deleteLegacyFileKey(string $path): bool {
  601. return $this->keyStorage->deleteFileKey($path, $this->fileKeyId, Encryption::ID);
  602. }
  603. /**
  604. * @param array $userIds
  605. * @return array
  606. * @throws PublicKeyMissingException
  607. */
  608. public function getPublicKeys(array $userIds) {
  609. $keys = [];
  610. foreach ($userIds as $userId) {
  611. try {
  612. $keys[$userId] = $this->getPublicKey($userId);
  613. } catch (PublicKeyMissingException $e) {
  614. continue;
  615. }
  616. }
  617. return $keys;
  618. }
  619. /**
  620. * @param string $keyId
  621. * @return string returns openssl key
  622. */
  623. public function getSystemPrivateKey($keyId) {
  624. return $this->keyStorage->getSystemUserKey($keyId . '.' . $this->privateKeyId, Encryption::ID);
  625. }
  626. /**
  627. * @param string $keyId
  628. * @param string $key
  629. * @return string returns openssl key
  630. */
  631. public function setSystemPrivateKey($keyId, $key) {
  632. return $this->keyStorage->setSystemUserKey(
  633. $keyId . '.' . $this->privateKeyId,
  634. $key,
  635. Encryption::ID);
  636. }
  637. /**
  638. * add system keys such as the public share key and the recovery key
  639. *
  640. * @param array $accessList
  641. * @param array $publicKeys
  642. * @param string $uid
  643. * @return array
  644. * @throws PublicKeyMissingException
  645. */
  646. public function addSystemKeys(array $accessList, array $publicKeys, $uid) {
  647. if (!empty($accessList['public'])) {
  648. $publicShareKey = $this->getPublicShareKey();
  649. if (empty($publicShareKey)) {
  650. throw new PublicKeyMissingException($this->getPublicShareKeyId());
  651. }
  652. $publicKeys[$this->getPublicShareKeyId()] = $publicShareKey;
  653. }
  654. if ($this->recoveryKeyExists() &&
  655. $this->util->isRecoveryEnabledForUser($uid)) {
  656. $publicKeys[$this->getRecoveryKeyId()] = $this->getRecoveryKey();
  657. }
  658. return $publicKeys;
  659. }
  660. /**
  661. * get master key password
  662. *
  663. * @return string
  664. * @throws \Exception
  665. */
  666. public function getMasterKeyPassword() {
  667. $password = $this->config->getSystemValue('secret');
  668. if (empty($password)) {
  669. throw new \Exception('Can not get secret from Nextcloud instance');
  670. }
  671. return $password;
  672. }
  673. /**
  674. * return master key id
  675. *
  676. * @return string
  677. */
  678. public function getMasterKeyId() {
  679. return $this->masterKeyId;
  680. }
  681. /**
  682. * get public master key
  683. *
  684. * @return string
  685. */
  686. public function getPublicMasterKey() {
  687. return $this->keyStorage->getSystemUserKey($this->masterKeyId . '.' . $this->publicKeyId, Encryption::ID);
  688. }
  689. /**
  690. * get public master key
  691. *
  692. * @return string
  693. */
  694. public function getPrivateMasterKey() {
  695. return $this->keyStorage->getSystemUserKey($this->masterKeyId . '.' . $this->privateKeyId, Encryption::ID);
  696. }
  697. }